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

# 前提

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

```gradle:
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()`を使えと言うことなので、早速次のように変えます。

```gradle:
   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:gradle.properties
android.debug.obsoleteApi=true
```

これでsyncすると、エラーの行を示してくれます。
それで調べると、どうやら引っかかっているのは`output.outputFile`の記述の箇所のようでした。

かなり難航しましたが、[こちら](https://objectville.github.io/2019/01/22/Android-%E8%A7%A3%E5%86%B3-API-variantOutput-getPackageApplication-is-obsolete-%E7%9A%84%E5%B0%8F%E9%97%AE%E9%A2%98/)のページを参考に、何とか解決しました。
(※中国語は読めません。コードだけで何とか言わんとすることを解釈しました。プログラミング言語は世界共通！)

```gradle:修正前
if (output.outputFile != null && output.outputFile.name.endsWith('.apk')) {

...

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

```gradle:修正後
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()`している箇所があって、その実装を追っていって下さったのが[先ほど紹介した中国語のページ](https://objectville.github.io/2019/01/22/Android-%E8%A7%A3%E5%86%B3-API-variantOutput-getPackageApplication-is-obsolete-%E7%9A%84%E5%B0%8F%E9%97%AE%E9%A2%98/)です。
内部の実装を表に引っ張ってきて解決した、という形です。

※StackOverflow等では、「この警告はGoogleが直すべき」と言っている意見もありました。
Googleの修正を待ち自分は変更しない、というスタンスも有りだと思います。

# 完成形

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

```gradle
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関連ファイルをコピーする](https://qiita.com/le_skamba/items/55016c17513ba545fa11)

[Android Gradle 3.0以上で出力するapkのファイル名を変更する](https://qiita.com/yamacraft/items/301f188b2433f47669ee)