Edited at

Android apkやmappingファイルをコピーするgradleスクリプトのGradle3.3+で出る警告の対処


前提

"apkコピータスク"をこんな感じで作っていました。

applicationVariants.all { variant ->

if (variant.buildType.name.equals("release")) {
variant.outputs.each { output ->
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {
// Rename APK
def versionCode = defaultConfig.versionCode
def versionName = defaultConfig.versionName
def date = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
def newName = "AppName_r${versionCode}_v${versionName}_${date}.apk"

def publish = project.tasks.create("publishAll")

// Move and Rename APK
def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy)
task.from(output.outputFile)
task.rename(output.outputFile.name, newName)
task.into(deployTo)

task.dependsOn variant.assemble
publish.dependsOn task

// Move ProGuard
if (variant.buildType.minifyEnabled) {
def copyTask = project.tasks.create("copy${variant.name.capitalize()}MappingText", Copy)
def buildTypeName = variant.buildType.name
copyTask.from(file("build/outputs/mapping/${buildTypeName}").path)
copyTask.into(deployTo + "/mapping")

copyTask.dependsOn variant.assemble
task.dependsOn copyTask
}
}
}
}
}

apkをリネームしてcleanされない別フォルダにコピー、さらにproguardのmapping関係ファイルもコピーするというよく見るやつです。


発端

AndroidStudio3.3に上げたら警告が出るようになりました。

WARNING: API 'variant.getAssemble()' is obsolete and has been replaced with 'variant.getAssembleProvider()'.

調べると、com.android.tools.build:gradleが3.3以上で出る警告のようです。


修正


修正1

メッセージは、variant.getAssembleは使えなくなったのでvariant.getAssembleProvider()を使えと言うことなので、早速次のように変えます。

   task.dependsOn variant.assembleProvider.get()

もう一箇所有るのでそちらも忘れずに。


修正2

1を処置してsyncすると、エラーメッセージが変わりました。

WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.

packageApplication()なんて箇所無いし、困った・・・と思ったら調査方法が書いてありました。

To determine what is calling variantOutput.getPackageApplication(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.

実行コマンドにパラメータ追加すれば良いようですが、AndroidStudioのsyncボタンだし・・・(gradlewコマンドたたくの面倒くさいし・・・)と思って調べたら、gradle.propertiesに追記すれば良いと分かりました。


gradle.properties

android.debug.obsoleteApi=true


これでsyncすると、エラーの行を示してくれます。

それで調べると、どうやら引っかかっているのはoutput.outputFileの記述の箇所のようでした。

かなり難航しましたが、こちらのページを参考に、何とか解決しました。

(※中国語は読めません。コードだけで何とか言わんとすることを解釈しました。プログラミング言語は世界共通!)


修正前

if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {

...

task.from(output.outputFile)
task.rename(output.outputFile.name, newName)



修正後

if (output.outputFileName.endsWith('.apk')) {

...

def srcDir = new File(variant.packageApplicationProvider.get().outputDirectory,
output.outputFileName)
task.from(srcDir)
task.rename(output.outputFileName, newName)


outputFile.nameは、outputFileNameに置き換えるだけで良かったのですが、それ以外に少し手間取りました。

つまりoutput.outputFile(AndroidのGradlePluginのメソッドのようです)が内部でgetPackageApplication()している箇所があって、その実装を追っていって下さったのが先ほど紹介した中国語のページです。

内部の実装を表に引っ張ってきて解決した、という形です。

※StackOverflow等では、「この警告はGoogleが直すべき」と言っている意見もありました。

Googleの修正を待ち自分は変更しない、というスタンスも有りだと思います。


完成形

ついでにequalsはoperatorに変更できるよと親切に教えてくれたのでその通りに直しました。

applicationVariants.all { variant ->

if (variant.buildType.name == "release") {
variant.outputs.each { output ->
if (output.outputFileName.endsWith('.apk')) {
// Rename APK
def versionCode = defaultConfig.versionCode
def versionName = defaultConfig.versionName
def date = new java.text.SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date())
def newName = "AppName_r${versionCode}_v${versionName}_${date}.apk"

def publish = project.tasks.create("publishAll")

// Move and Rename APK
def task = project.tasks.create("publish${variant.name.capitalize()}Apk", Copy)
def srcDir = new File(variant.packageApplicationProvider.get().outputDirectory,
output.outputFileName)
task.from(srcDir)
task.rename(output.outputFileName, newName)
task.into(deployTo)

task.dependsOn variant.assembleProvider.get()
publish.dependsOn task

// Move ProGuard
if (variant.buildType.minifyEnabled) {
def copyTask = project.tasks.create("copy${variant.name.capitalize()}MappingText", Copy)
def buildTypeName = variant.buildType.name
copyTask.from(file("build/outputs/mapping/${buildTypeName}").path)
copyTask.into(deployTo + "/mapping")

copyTask.dependsOn variant.assembleProvider.get()
task.dependsOn copyTask
}
}
}
}
}

最後に、gradle.propertiesに書いたフラグ(android.debug.obsoleteApi=true)をコメントアウトしておきましょう。

ビルドに時間がかかるようになるので「常時書いておくな」と説明が出ています。


参考

リリースビルドタスクでproguard関連ファイルをコピーする

Android Gradle 3.0以上で出力するapkのファイル名を変更する