私のチームと私は最近、アプリで 64K メソッド参照に達しました。これは、dex ファイルでサポートされる最大数です。この制限を回避するには、プログラムの一部を複数のセカンダリ dex ファイルに分割し、実行時にロードする必要があります。
Ant ベースの古いビルド システムの質問で言及されているブログ投稿に従いましたが、すべて正常に機能していました。しかし最近、Gradle ベースの新しいビルド システムに移行する必要性を感じました。
この回答は、完全なブログ投稿を完全な例に置き換えることを意図したものではありません。代わりに、Gradle を使用してビルド プロセスを微調整し、同じことを達成する方法を簡単に説明します。これはおそらくそれを行うための 1 つの方法であり、現在チームで行っている方法であることに注意してください。必ずしもそれが唯一の方法であるとは限りません。
私たちのプロジェクトの構造は少し異なります。この例は、すべてのソース コードを .class ファイルにコンパイルし、それらを単一の .dex ファイルにアセンブルし、最後にその単一の .dex ファイルを .jar にパッケージ化する個別の Java プロジェクトとして機能します。ファイル。
はじめましょう...
ルートのbuild.gradleには、いくつかのデフォルトを定義する次のコードがあります。
ext.androidSdkDir = System.env.ANDROID_HOME
if(androidSdkDir == null) {
Properties localProps = new Properties()
localProps.load(new FileInputStream(file('local.properties')))
ext.androidSdkDir = localProps['sdk.dir']
}
ext.buildToolsVersion = '18.0.1'
ext.compileSdkVersion = 18
この例は個別の Java プロジェクトですが、Android SDK のコンポーネントを使用する必要があるため、上記のコードが必要です。また、後で他のプロパティのいくつかも必要になります...したがって、メイン プロジェクトのbuild.gradleには、次の依存関係があります。
dependencies {
compile files("${androidSdkDir}/platforms/android-${compileSdkVersion}/android.jar")
}
また、このプロジェクトのソース セットを簡素化していますが、これはプロジェクトには必要ない場合があります。
sourceSets {
main {
java.srcDirs = ['src']
}
}
次に、組み込みタスクのデフォルト構成を変更して、すべての .class ファイルではなくjar
、単にclasses.dexファイルを含めるようにします。
configure(jar) {
include 'classes.dex'
}
ここで、実際にすべての .class ファイルを単一の .dex ファイルにアセンブルする新しいタスクが必要です。この場合、Protobuf ライブラリ JAR を .dex ファイルに含める必要もあります。だから私はここの例にそれを含めています:
task dexClasses << {
String protobufJarPath = ''
String cmdExt = Os.isFamily(Os.FAMILY_WINDOWS) ? '.bat' : ''
configurations.compile.files.find {
if(it.name.startsWith('protobuf-java')) {
protobufJarPath = it.path
}
}
exec {
commandLine "${androidSdkDir}/build-tools/${buildToolsVersion}/dx${cmdExt}", '--dex',
"--output=${buildDir}/classes/main/classes.dex",
"${buildDir}/classes/main", "${protobufJarPath}"
}
}
また、 build.gradleファイルのどこかに (通常はもちろん一番上に) 次のインポートがあることを確認してください。
import org.apache.tools.ant.taskdefs.condition.Os
ここで、最終的な .jar ファイルがアセンブルされる前にタスクが実行されるように、jar
タスクをタスクに依存させる必要があります。dexClasses
簡単なコード行でそれを行います。
jar.dependsOn(dexClasses)
これで完了です... 通常のassemble
タスクで Gradle を呼び出すだけで、最終的な .jar ファイルに${buildDir}/libs/${archivesBaseName}.jar
は単一のclasses.dexファイルが含まれます (MANIFEST.MF ファイルに加えて)。それをアプリのアセット フォルダーにコピーするだけで (私たちが行ったように Gradle を使用していつでも自動化できますが、それはこの質問の範囲外です)、残りのブログ投稿に従ってください。
質問がある場合は、コメントで叫んでください。できる限りのお手伝いをさせていただきます。