Androidアプリの依存関係をmavenのローカルリポジトリで解決する方法を調べた

公開:2021/02/05
更新:2021/02/05
3 min読了の目安(約3500字TECH技術記事

jcenter シャットダウン対策で...
本来は依存関係をアップデートすべきだが, 事情によりそうもいかないことがある.
ここでは例として org.jetbrains.trove4j:trove4j:20160824maven のローカルリポジトリで解決してみようと思う.

  1. build.gradlejcenter()mavenCentral() に置き換えてビルドする
  2. 依存関係が解決できなかったライブラリをメモする. 前述の通り, ここでは org.jetbrains.trove4j:trove4j:20160824 が解決できなかったとする
  3. maven をインストールする. インストール方法はググれば出てくるのでここでは触れない
  4. ~/.m2/repository にある maven のローカルリポジトリを消す. ローカルリポジトリの場所を変更している場合は置き換えて読んで欲しい
  5. 適当な作業ディレクトリを作成する
  6. 作業ディレクトリ内に以下の pom.xml を作成する
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>example</artifactId>
  <version>1.0.0</version>
  <packaging>apk</packaging>
  <build>
    <plugins>
      <plugin>
        <groupId>com.simpligility.maven.plugins</groupId>
        <artifactId>android-maven-plugin</artifactId>
        <version>4.3.0</version>
        <extensions>true</extensions>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
    <repository>
      <id>jcenter</id>
      <url>https://jcenter.bintray.com</url>
      <releases>
        <enabled>true</enabled>
      </releases>
    </repository>
  </repositories>
  <dependencies>
    <dependency>
      <groupId>org.jetbrains.trove4j</groupId>
      <artifactId>trove4j</artifactId>
      <version>20160824</version>
    </dependency>
  </dependencies>
</project>
  1. mvn clean を実行する. ~/.m2/repository にライブラリがインストールされる
  2. build.gradlerepositoriesmavenLocal() を追加してアプリをビルドする. repositoriesbuildscriptallprojects の2箇所にあるが, 両方に追加した方がよいだろう
  3. 今度は org.jetbrains.trove4j:trove4j:20160824 の依存関係が解決できたはずである
  4. あとは全ての依存関係が解決できるようになるまで, 依存関係が解決できなかったライブラリを pom.xml に追加→mvn clean→アプリをビルドを繰り返す

ここまでの手順で, ~/.m2/repository は依存関係を解決するローカルリポジトリとして十分なものになっているが, mavenCentral に存在するライブラリも含まれており無駄がある.
そこで

  1. ~/.m2/repository を削除する
  2. mvn clean -l maven.log を実行する
  3. maven.log にライブラリがどこからダウンロードされたか出力されているので, これをもとに ~/.m2/repository 以下の mavenCentral からダウンロードされたライブラリを消す

とすると無駄のないローカルリポジトリが残る.
この maven ローカルリポジトリをどう扱うかは自由だが, 自分はCIで利用するために別のgitリポジトリを作成してプッシュし, CIのビルドスクリプトの中で ~/.m2/repository にクローンすることにした.

付録: mavenCentralからダウンロードされたライブラリをローカルリポジトリから消す

macとlinux用.
手近な python3 で書いたが, シェル職人ならシェルで書き直せる気がする.

import os
from pathlib import Path
import re


jar_pom_dict = {}
for p1 in (Path(os.environ['HOME']) / '.m2' / 'repository').rglob('*'):
    if p1.suffix in ('.jar', '.pom'):
        jar_pom_dict[p1.name] = p1


with open('maven.log', 'r', encoding='utf_8') as f:
    for line in f:
        if line.startswith('[INFO] Downloaded from central:'):
            m = re.search(r'/([^/]*?\.(jar|pom))', line)
            if m:
                p2 = jar_pom_dict.pop(m.group(1), None)
                if p2:
                    p2.unlink()

付録2: aarの依存関係を解決する

aarpom.xml に追加するときは

<dependency>
  <groupId>com.android.volley</groupId>
  <artifactId>volley</artifactId>
  <version>1.1.1</version>
  <type>aar</type>
</dependency>

のように <type>aar</type> が必要である.
つけないと

[ERROR] Failed to execute goal on project example: Could not resolve dependencies for project com.example:example:apk:1.0.0: Failure to find com.android.volley:volley:jar:1.1.1 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced -> [Help 1]

とエラーを吐いて失敗する.