違い
公式のドキュメントのPendingIntent.FLAG_IMMUTABLEのところには次のように書かれてました。
FLAG_IMMUTABLE only limits the ability to alter the semantics of the intent that is sent by send() by the invoker of send()
意味としては、
FLAG_IMMUTABLEを設定するとsend()の呼び出しによって送信されるインテントのセマンティクスを変更する機能のみを制限します。
という感じなので、インテントの情報を変更できないよという事になる。
逆にMUTABLEの方は変更可能であると書かれているので、PendingIntent経由で何か情報を受け取りたい時はMUTABLEの設定すればよいと思われる。
具体例
NFCカードを読み取ろうとしている際にIMMUTABLEかMUTABLEかの違いで詰まりました。
NFCの読み取りに関する詳細は今回割愛しまが、したのコードを簡単に説明すると、onResumeではNFCカードを読み取ったら現在のアクティビティを開始するように設定していて、onNewIntentではNFCを読み取った際のintentを受け取ってintentのactionを表示するというコードになっています。
override fun onResume() {
super.onResume()
val intent = Intent(this, this.javaClass)
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, PendingIntent.FLAG_IMMUTABLE)
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null)
}
override fun onPause() {
super.onPause()
mNfcAdapter.disableForegroundDispatch(this)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
println("onNewIntent action: ${intent?.action}")
// 本来ここでandroid.nfc.action.NDEF_DISCOVEREDなどと表示されてほしかった。
}
そしてこのコードがうまく動かない原因はフラグにIMMUTABLEを設定していた事でした。
onResumeの4行目でPendingIntentのフラグにIMMUTABLEを設定している事によってonNewIntentで受け取るintentの引数がnullになりNFCカードをかざすと反応はするが、情報は取れないということになり詰まってました。
上記のプログラムを動くように修正すると下のようになります。(PendingIntent.FLAG_IMMUTABLEをMUTABLEに変更しただけですが、、)
override fun onResume() {
super.onResume()
val intent = Intent(this, this.javaClass)
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
val pendingIntent = PendingIntent.getActivity(applicationContext, 0, intent, PendingIntent.FLAG_MUTABLE)
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null)
}
override fun onPause() {
super.onPause()
mNfcAdapter.disableForegroundDispatch(this)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
println("onNewIntent action: ${intent?.action}")
// 本来ここでandroid.nfc.action.NDEF_DISCOVEREDなどと表示されてほしかった。
}