Androidのシステムは、デバイスに他のAppがインストールされたり削除されるブロードキャストイベントを送出します。 アプリがイベントを受け取る関連インテントをBroadcastReceiverに登録をします。
次のような状況には、次のようなActionのインテントがブロードキャストされます。
- アプリがデバイスに最初にインストールされたとき:
android.intent.action.PACKAGE_ADDED
- アプリが更新される:
android.intent.action.PACKAGE_REPLACED
- アプリ(現在Userのみ)削除される:
android.intent.action.PACKAGE_REMOVED
- アプリがデバイスから完全に削除されたとき:
android.intent.action.PACKAGE_FULLY_REMOVED
特に、アプリが更新されると更新されるアプリ、自分には android.intent.action.MY_PACKAGE_REPLACED
が渡されます。
このインテントは、名前のように、他のアプリでは、転送されません。
それぞれのインテントの受信機をどのように登録するかを知ってみましょう。
ACTION_PACKAGE_ADDED:アプリのインストールイベント
Android 8.0のBroadcast Limitations政策的には、暗黙的インテントに渡されるブロードキャストは、AppのAndroidManifest.xmlに登録されたレシーバでは配信されません。これはTarget APIが26以上であるアプリを対象とします。 API 26未満アプリはすべて渡されます。
Target API 26以上のアプリがブロードキャストを受信する Context.registerReceiver()
APIを使用して受信機を登録する必要があります。
暗黙的インテントは、次のようにインテントにpackageの情報がないことを意味します。
val intent = Intent(Intent.ACTION_MAIN)
明示的インテントは、次のようにインテントにpackageの情報があることを意味します。
val intent = Intent(Intent.ACTION_MAIN)
intent.`package` = "target.package.name"
ACTION_PACKAGE_ADDED
は、暗黙的インテントに渡されるインテントです。したがってTarget 26以上では、AppのManifestにレシーバを登録すると、インテントが配信されません。
Contextを使用して登録する必要があります。
API 26以上では、レシーバの登録
ACTION_PACKAGE_ADDED
は、API 26以上でContextのみ登録する必要があります。
次のようにレシーバを登録することができます。
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addDataScheme("package")
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("MyReceiver", "onReceive: $intent")
}
}
context.registerReceiver(receiver, intentFilter)
例では、Receiverは、匿名オブジェクトで生成しました。
そしてIntentFilterを生成する際にschemeを必ず "package"に設定する必要があります。 その理由は、配信されるインテントのdataのschemeが "package"に設定されているからです。そのため、schemeを "package"に設定しない場合は、イベントを受け取ることができません。
次のログは、上記のコードでレシーバを登録してアプリをインストールしたときに出力されるログです。
07-02 21:12:48.021 6331 6331 D MyReceiver: onReceive: Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.codechacha.myapplication flg=0x4000010 (has extras) }
API 26未満では、レシーバの登録
API 26未満ではContextとManifestを利用して、すべてのレシーバを登録することができます。
次のようにAndroidManifest.xmlにレシーバを登録することができます。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
上記で使用 MyReceiver
クラスは、次のように実装しました。
class MyReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("MyReceiver", "onReceive: $intent")
}
}
Contextコードは上で紹介したものと同じです。
ACTION_PACKAGE_REPLACED:アプリの更新イベント
ACTION_PACKAGE_REPLACED
は、アプリが更新されるときに送出さインテントです。このインテントも暗黙的インテントです。
API 26以上では、レシーバの登録
API 26以上では、Contextのみ登録が可能です。
次のように登録することができます。 actionが異なり ACTION_PACKAGE_ADDED
コードと同じです。
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED)
intentFilter.addDataScheme("package")
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("MyReceiver", "onReceive: $intent")
}
}
API 26未満では、レシーバの登録
次のようにレシーバを登録することができます。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
アプリのアップデート時に、インテント伝達順
デバイスにアプリが最初にインストールがされると、 ACTION_PACKAGE_ADDED
のみ渡されます。
しかし、アプリが更新されるときは、次のテントが順次配信されます。
1. ACTION_PACKAGE_REMOVED
2. ACTION_PACKAGE_ADDED
3. ACTION_PACKAGE_REPLACED
ACTION_PACKAGE_REMOVED
が配信されている理由は、更新前のバージョンのアプリが削除されたことを意味であり、新しいバージョンがインストールされ、更新された意味でADDEDとREPLACEDインテントが配信されます。
ACTION_PACKAGE_ADDEDインテントにアプリの更新情報の確認
ACTION_PACKAGE_ADDED
インテントは、Intent.EXTRA_REPLACING
という名前のExtraにREPLACEDの情報を持っています。
したがって、 PACKAGE_ADDED
インテントを受けるならPACKAGE_REPLACED
を追加で必要ありません。
次のように ACTION_PACKAGE_ADDED
でReplaced情報を得ることができます。
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addDataScheme("package")
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val replaced = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
Log.d("MyReceiver", "onReceive: $intent")
Log.d("MyReceiver", "Replaced ? $replaced")
}
}
以下は、最初のインストールされるときのログと更新されるのログです。
更新される Intent.EXTRA_REPLACING
がtrueに渡されます。
// first install
07-02 21:35:20.022 7040 7040 D MyReceiver: onReceive: Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.codechacha.myapplication flg=0x4000010 (has extras) }
07-02 21:35:20.022 7040 7040 D MyReceiver: Replaced ? false
// upgrade
07-02 21:35:20.667 7040 7040 D MyReceiver: onReceive: Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.codechacha.myapplication flg=0x4000010 (has extras) }
07-02 21:35:20.667 7040 7040 D MyReceiver: Replaced ? true
ACTION_PACKAGE_REMOVED:アプリの削除イベント
ACTION_PACKAGE_REMOVED
はアプリが削除されるときに送出さインテントであり、暗黙的インテントに渡されます。
AndroidはMulti userをサポートし、それぞれのUserにアプリがインストールされることがあります。 このインテントは、いくつかのUserでアプリが削除されるときに送出されます。このインテントを受けて、デバイスから完全にアプリが削除されたことを意味はしません。
デバイスから(すべてのMulti userで)アプリが完全に削除されたときは ACTION_PACKAGE_FULLY_REMOVED
インテントが配信されます。
API 26以上では、レシーバの登録
API 26以上のアプリは、次のようにレシーバを登録することができます。
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addDataScheme("package")
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("MyReceiver", "onReceive: $intent")
}
}
context.registerReceiver(receiver, intentFilter)
API 26未満では、レシーバの登録
API 26未満アプリは、次のようにインテントを渡すことができます。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
ACTION_PACKAGE_FULLY_REMOVED:デバイス全体でアプリの削除
ACTION_PACKAGE_FULLY_REMOVED
は、デバイス全体でアプリが削除されるときに送出されるイベントです。
暗黙的なイベントであるが、このインテントは、例外的にManifestに登録することができます。
例外的にいくつかの暗黙的インテントは、Manifestにレシーバの登録を許可します。 Implicit Broadcast Exceptionsを見ればどのようなインテントが例外なのか知ることができます。
したがって、Target APIレベルの区別なくManifestとContextに登録可能です。
他のインテントと同様の形式でManifestにレシーバを登録することができます。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Output:
07-02 21:46:31.388 7845 7845 D MyReceiver: onReceive: Intent { act=android.intent.action.PACKAGE_FULLY_REMOVED dat=package:com.codechacha.myapplication flg=0x5000010 cmp=com.codechacha.packageintent/.MyReceiver (has extras) }
Contextに登録することも、他のインテントの例と同様です。
ACTION_MY_PACKAGE_REPLACED:アプリ自分に更新イベント伝達
ACTION_MY_PACKAGE_REPLACED
インテントは、例えばcom.codechacha.myapplication
というアプリを更新するときに com.codechacha.myapplication
アプリに伝達するインテントです。
このインテントは、明示的インテントで、ManifestとContextの両方レシーバー登録が可能です。しかし、更新されアプリ自身は終了するので、Contextにされません。
次のManifestにレシーバを登録することができます。配信されるインテントには、scheme情報がないため、IntentFilterもschemeを設定しないでください。
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Related Posts
- Android - 振動、Vibrator、VibrationEffectの例
- Android - TabLayoutの実装方法(+ ViewPager2)
- Android - PackageManagerにPackage情報を取得する
- Android - ACTION_BOOT_COMPLETEDイベント受信
- Android - FusedLocationProviderClientに位置情報を取得する
- Android - GPS、Network位置情報を取得する(LocationManager)
- Android - Foreground Service実行
- Android - 時間、日付、変更イベント受信
- Android - currentTimeMillis()、elapsedRealtime()、uptimeMillis()
- Android-PowerManager WakeLock
- Android - ファイル入出力の例(Read、Write、内部、外部ストレージ)
- Android - Screen On / Offイベントの受信、状態確認
- Android - 他のアプリのServiceにバインド
- Android - Handler vs Executor
- Android - Darkmode有効にする方法
- Android - hasSystemFeature()、サポートされているFeature確認
- Android - アプリの権限を確認(Permission check)
- Android - インストールされてアプリリストをインポートする
- Android App Shortcuts実装
- Android - ContentProviderを実装、および例
- Android - AIDLを利用して、Remote Serviceの実装
- Android - Uri、Scheme、SSP(Scheme Specific Part)説明
- Android - アプリのインストール、削除、イベントダウンロード(BroadcastReceiverインテントを受け取る)
- Android - SharedPreferencesに簡単なデータを保存する方法
- Android - AlarmManagerにアラームを登録する方法、および例
- Android - Quick SettingsにCustom Tile追加する方法(kotlin)
- Android - Broadcast Receiver登録およびイベントの受信方法
- Android - Runtime permissionリクエスト方法と例(kotlin)
- Android - ネットワーク(WIFI)の接続状態を確認し、変更の検出
- Mockito - static、final methodをmockingする方法
- Andriod - カスタムパーミッションを定義する方法
- RobolectricにUnit Testを作成する(kotlin)
- Android Mockitoのテストコードを作成する(kotlin)
- Android - Handlerの使用方法、および例
- Android - IntentService使用方法
- Android - JobIntentService使用方法