Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

前提

"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のファイル名を変更する

kasa_le
言語経験はC→C++→Java+Android(たまにiOS/swift経験なし)→Kotlin Flutterも良いよ. 独学でPHPとpython
Leading-Edge
ITエンジニアの生涯価値向上を目指し、派遣・紹介・教育・自社開発など様々な分野から全方位支援を行っております。
https://www.leadinge.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away