読者です 読者をやめる 読者になる 読者になる

メモ2ブログ

メモtoウェブログ。旧ブログはこちら。 http://sakebook.blogspot.jp/

アプリのインストール・更新・アンインストールの検知

Broadcast

アプリの情報の変化に関するものは、BroadcastがOSから投げられるので、それを受け取るように作れば、検知できます。

引っかかったところ

  • アンインストール時には、android.intent.action.PACKAGE_REMOVED が、投げられるので、それで良いと思っていたのですが、これはアプリの更新時にも投げられます。

  • アプリの更新時には、
    android.intent.action.PACKAGE_REMOVED android.intent.action.PACKAGE_ADDED android.intent.action.PACKAGE_REPLACED
    という風に複数Broadcastが投げられます。

  • インストールのときは、android.intent.action.PACKAGE_INSTALLを受け取れば良いと思っていたのですが、API Level14からDeprecatedになっていました。

  • プリインアプリのアップデートのアンインストールは更新時と同じBroadcastが投げられます。

getExtra()の値で判断

判断に必要な値は、Bundleされているのでそれを確認することで正しく検知できます。

Intent.EXTRA_REPLACING

異なるバージョンのAPKかどうかをtrue/falseで持っています。
端末内に同じPackageNameがなければ false, あれば trueを返します。
この値は
android.intent.action.PACKAGE_ADDED // false android.intent.action.PACKAGE_REMOVED // true android.intent.action.PACKAGE_FULLY_REMOVED //false
Bundleされています。

Intent.EXTRA_DATA_REMOVED

データとAPK本体を含めて端末から削除されたかどうかをtrue/falseで持っています。
どちらも削除された場合は true, そうでなければ false を返します。
この値は
android.intent.action.PACKAGE_REMOVED // true or false android.intent.action.PACKAGE_FULLY_REMOVED //true
Bundleされています。

これを踏まえると、インストール、更新、アンインストールは次のように判定することができます。

インストール

Broadcast android.intent.action.PACKAGE_ADDED intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) = false

更新

Broadcast android.intent.action.PACKAGE_ADDED intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) = true

or

Broadcast android.intent.action.PACKAGE_REMOVED intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED) = false intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) = true

or

Broadcast android.intent.action.PACKAGE_REPLACED

アンインストール

Broadcast android.intent.action.PACKAGE_REMOVED intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED) = true intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) = false

or

Broadcast android.intent.action.PACKAGE_FULLY_REMOVED intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED) = true

プリインアプリのアンインストール(アップデートのアンインストール)

Broadcast android.intent.action.PACKAGE_REMOVED intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED) = true intent.getExtras().getBoolean(Intent.EXTRA_REPLACING) = true

サンプルコード

...
        <receiver android:name=".receiver.MyReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />

                <data android:scheme="package" />
            </intent-filter>
        </receiver>
...
...
public class MyReceiver extends BroadcastReceiver {

    private final static String TAG = MyReceiver.class.getSimpleName();
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {

        if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                 && !intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
            Log.d(TAG, "インストール");
        }

        if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {

            if (intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED)
                    && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
                Log.d(TAG, "アップデートのアンインストール");
            }
            if (!intent.getExtras().getBoolean(Intent.EXTRA_DATA_REMOVED)
                    && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
                Log.d(TAG, "更新");
            }
        }

        if (Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(intent.getAction())) {
            Log.d(TAG, "アンインストール");
        }
    }
}

参考

Intent / Android Developer Reference