【Android】AndroidXマイグレートついでにライブラリをアップデートした時に遭遇したエラーと対処内容

**気が付けば昔にリリースしたAndroidアプリが使っているライブラリが古くなってしまった..**
という事はよくあるかと思います。
筆者も少し前にリリースしたAndroidアプリを**AndroidX**にマイグレートしようかと思い立ち、
使っているライブラリも見てみるとバージョンが古くなっていたので、ついでにバージョンアップしたら、
色々エラーが出てすんなり行かなかったので、エラーと対処内容をつらつらと書いて行こうかと思います。

また「ここはこうした方が良い」や「この対処方法はまずいのでは。。」等ありましたら
お知らせ頂けると嬉しいです。:pray:

----
### ライブラリのバージョンアップ前にやった事

- AndroidStudioを現時点の最新Ver3.2.1にアップデート
- `compileSdkVersion`と`targetSdkVersion`を28に変更
- `buildToolsVersion`を`28.0.3`に変更
- `build.gradle`の`dependencies`>`classpath`の各Verを以下に変更

```gradle
    dependencies {
        classpath 'com.android.tools.build:gradle:3.2.1' // 3.0.1 -> 3.2.1
        classpath 'com.google.gms:google-services:4.1.0' // 3.1.0 -> 4.1.0
    }
```

----
### Google maps Android SDK v16.0.0にアップした時のエラー :bomb: 

Google maps Android SDKを`10.2.6`から`16.0.0`にバージョンアップし、
Pixel 2 API28 (Android9.0)のエミュレータでアプリを起動させたら以下エラーが発生しました。

- **Caused by java.lang.ClassNotFoundException: Didn't find class "org.apache.http.ProtocolVersion"**

```
Caused by java.lang.ClassNotFoundException: Didn't find class "org.apache.http.ProtocolVersion" on path: DexPathList[[zip file "/data/user_de/0/com.google.android.gms/app_chimera/m/00000014/MapsDynamite.apk"],nativeLibraryDirectories=[/data/user_de/0/com.google.android.gms/app_chimera/m/00000014/MapsDynamite.apk!/lib/x86, /system/lib]]
       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
       at ac.loadClass(:com.google.android.gms.dynamite_dynamiteloader@14367084@14.3.67 (100700-216465562):4)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
       at ew.b(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):3)
       at ev.a(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):3)
       at ex.a(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):14)
       at com.google.maps.api.android.lib6.drd.al.a(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):6)
       at dz.a(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):21)
       at dz.run(:com.google.android.gms.dynamite_mapsdynamite@14367084@14.3.67 (100700-216465562):8)
```

- **原因**
    原因はエラー内容の通りですが、`org.apache.http.ProtocolVersion`クラスを使おうとしたけど、
    クラスが見付からないので`ClassNotFoundException`が発生している様です。

- **解決方法**
    使おうとしている共有ライブラリ`org.apache.http.legacy`をこのアプリでは使いますよ
    という事をAndroidManifestに追記してあげる。

    ```xml
        <application>
            <uses-library android:name="org.apache.http.legacy" android:required="false"/>
    ```

    ※参考 [stackoverflow](https://stackoverflow.com/questions/50782806/android-google-maps-java-lang-noclassdeffounderror-failed-resolution-of-lorg-a)

----
### AndroidManifestにDeep Link関連の警告が表示 :bomb:

AndroidStudioでAndroidManifestを開くと、全体的に警告が出ており、
以下の警告内容が表示されている。

```
App is not indexable by Google Search;
consider adding at least one Activity with an ACTION-VIEW intent filter.
See issue explanation for more details. 
Adds URLs to get your app into the Google index, to get installs and traffic to your app from Google Search.  
Issue id: GoogleAppIndexingWarning 
More info: https://g.co/AppIndexing/AndroidStudio
```

- **原因**

  AndroidManifestにDeepLinkの設定が無いと警告が出ている。

- **解決方法**

  アプリによっては次の2通り

#### 1. そもそもDeepLink使わないアプリの場合
`app/build.gradle`にDeepLinkのチェックを無効にする設定を追加する

```gradle:app/build.gradle
    lintOptions {
        disable 'GoogleAppIndexingWarning'
    }
```

#### 2. DeepLinkを使うアプリの場合

```xml:AndroidManifest.xml
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />

                <!-- 以下を追加 -->
                <action android:name="android.intent.action.VIEW" /  >
                <category android:name="android.intent.category.DEFAULT" / >
                <category android:name="android.intent.category.BROWSABLE" / >
                <data
                    android:host="sample-host"
                    android:scheme="sample-scheme" / >
                <!-- ここまで -->
            </intent-filter>
        </activity>
```
`sample-host`と`sample-scheme`は設定したい値に変える。

----
### DataBindingUtil#setContentViewを使っている箇所でエラー :bomb:

下のようなエラーが表示されるが、ビルドは通ってアプリも動く状態。

```
Type parameter T has incompatible upper bounds : ViewDataBinding and MainActivity
```

[stackoverflow](https://stackoverflow.com/questions/34368329/data-binding-android-type-parameter-t-has-incompatible-upper-bounds-viewdata)にかかれてある通り、

1. 該当のlayoutファイルを選択
2. 右クリック > Refactor > Rename で一旦別の名前に変更する
3. 再度元の名前に戻すとエラーが消えている...

----
### AndroidXにマイグレートして出たエラー :bomb:

AndroidStudioで`app/build.gradle`を開くと下記のようなエラーが表示。

```
'com.theartofdev.edmodo.cropper.CropImageActivity' is not assignable to 'android.app.Activity' less... (⌘F1) 
Validates resource references inside Android XML files.
```

ただ、こちらのエラーは、AndroidStudio上でエラー表示されてはいるが、ビルドは成功し
アプリは普通に動いているという状態です。AndroidStudioを再起動したりしても消えずに表示されており
ちょっと気持ち悪かったので対応しました。

- **原因**

`gradle.properties`に`android.enableJetifier=true`は設定されているが、エラーを見る限り
AndroidXにマイグレートした為、`support.v4.xxxx`の`AppCompatActivity`が解決出来ていない様子でした。
ビルドも通り、アプリも起動して動作するのでAndroidStudio上でLintエラーが出ていて、それが表示されているだけの様な感じでした。

- **解決方法**

今回の場合はライブラリの最新Verで`AndroidX`に対応してたのでバージョンアップするだけでOKでした。
https://github.com/ArthurHub/Android-Image-Cropper/releases/tag/2.8.0

AndroidXに対応していないライブラリ等で上記のエラーが出た場合は、
ライブラリがAndroidX対応するのを待つか、ライブラリをForkして自分でAndroidX対応する方法になりそうですが、
ビルドも通るし、アプリも起動して動作するので気持ち悪さを我慢できればそこまでしなくても良いかもしれませんw