Android Gradle Pluginを4.0.0から4.0.1へアップデート ( Android11 の Package visibility )

Android Gradle Pluginのバージョン4.0.0から4.0.1へアップデート。何が変わったのでしょうか? https://developer.android.com/studio/releases/gradle-plugin#4-0-0

This minor update supports compatibility with new default settings and features for package visibility in Android 11.

Package visibilityの管理ができるようになりました!

なんだそれは?調べてみると、他のアプリとの連携を細かく制御できるようです。 developer.android.com

アプリのtargetがAndroid 11 (API Level 30)以上で、他のアプリと連携したい場合、manifestファイルに <queries> という要素を書かないといけない場合ができたようです。


例えば、PackageManagerで情報を取得するケースを試してみます。

targetSdkVersion 30 のアプリA ( info.bati11.example.a )とアプリB ( info.bati11.example.b ) を用意する。アプリAからPackageManagerを使ってアプリBの情報を取得してみることにする。

package info.bati11.example.a

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        findViewById<Button>(R.id.button).setOnClickListener {
            val packageName = "info.bati11.example.b"
            Log.i(
                "test",
                packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES).toString()
            )
        }
    }
}

API Level29のエミュレータで試すと問題なし。

2020-09-14 23:50:27.850 5962-5962/info.bati11.example.a I/test: PackageInfo{19d4329 info.bati11.example.b}

API Level30のエミュレータで試すと以下のExceptionが発生!

2020-09-14 23:59:17.151 5734-5734/info.bati11.example.a E/AndroidRuntime: FATAL EXCEPTION: main
    Process: info.bati11.example.a, PID: 5734
    java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
     Caused by: android.content.pm.PackageManager$NameNotFoundException: info.bati11.example.b
        at android.app.ApplicationPackageManager.getPackageInfoAsUser(ApplicationPackageManager.java:206)
        at android.app.ApplicationPackageManager.getPackageInfo(ApplicationPackageManager.java:178)
        at info.bati11.example.a.MainActivity$onCreate$1.onClick(MainActivity.kt:20)
        at android.view.View.performClick(View.java:7448)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

アプリAのAndroidManifest.xmlに <queries> を記述してみる。

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="info.bati11.example.a">
    <queries>
        <package android:name="info.bati11.example.b" />
    </queries>

    ...

これでAPI Level30のエミュレータでもOK!

2020-09-15 00:13:56.601 2388-2388/info.bati11.example.a I/test: PackageInfo{7ea0aab info.bati11.example.b}


ちなみに、アプリAの targetSdkVersion30 から 29 に変えれば例外は発生しませんでした。

また、 startActivity でアプリAからアプリBを起動する場合に <query> は必要なかったです。

公式ドキュメントにも記載されてますね。

https://developer.android.com/training/basics/intents/package-visibility#automatic

Note: If your app targets Android 10 (API level 29) or lower, all apps are visible to your app automatically.

...

In addition, you can start another app's activity using either an implicit or explicit intent, regardless of whether that other app is visible to your app.