🎃

AWS Amplifyを使わず直PinpointからPush通知を受け取ってデータをactivityに渡す方法(android側の実装)

2022/11/25に公開約6,200字

※android側の実装しか書いてないです。
サーバーサイドはドキュメント通りで大丈夫なはずです。

結論

  • receiveOnBackGroundには受け取れるもののPushが届かないのでPush通知自体は自作する必要がある
  • データはIntent.putExtraして渡す
  • dataはPinpointのカスタムプロパティにJson形式で突っ込んでおくと楽
  • 受け取りはactivity.intent.extras.getStringして取得する

サンプルコード

override fun receiveOnBackGround(intent: Intent) {
        super.receiveOnBackGround(intent)
        val bundle = intent.extras ?: return
        val notificationJson =
            bundle.getString(PushNotificationKeyType.PinpointJsonBody.keyName) ?: return
        val notificationData = Json.decodeFromString<PushResponse>(notificationJson)

        // 通知チャンネルの作成
        val name = "hogehoge"
        val descriptionText = "fugafuga"
        val channelId = BuildConfig.APPLICATION_ID + name
        val channel =
            NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_DEFAULT).apply {
                description = descriptionText
            }
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // チャンネルをシステムに登録
        notificationManager.createNotificationChannel(channel)

        val senderId = bundle.getString(PushNotificationKeyType.SenderId.keyName)?.toIntOrNull()
            ?: (0..9999999).random()
        val pendingIntent: PendingIntent = Intent(this, MainActivity::class.java).let {
            it.putExtra(
                PushNotificationKeyType.PinpointJsonBody.keyName,
                notificationJson
            )
            it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            it.action = PushNotificationKeyType.PendingIntentPushActionId.keyName
            PendingIntent.getActivity(
                this,
                senderId,
                it,
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
                    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
                else PendingIntent.FLAG_UPDATE_CURRENT
            )
        }

        //通知の実施
        notificationManager.notify(
            senderId,
            notificationCompatBuilder(
                this,
                channelId,
                bundle.getString(PushNotificationKeyType.PinpointNotificationTitle.keyName),
                bundle.getString(PushNotificationKeyType.PinpointNotificationBody.keyName),
                pendingIntent,
                bundle.getString(PushNotificationKeyType.PinpointNotificationImageUrl.keyName)
            ).build()
        )
    }
    
private fun getBitmapFromUrl(url: String?): Bitmap? =
        if (!url.isNullOrBlank()) URL(url).openStream().use {
            BitmapFactory.decodeStream(it)
        } else null
    
private fun notificationCompatBuilder(
        context: Context,
        channelId: String,
        title: String?,
        message: String?,
        pendingIntent: PendingIntent?,
        imageUrl: String?
    ) = NotificationCompat.Builder(context, channelId)
        .setContentTitle(title)
        .setContentText(message)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)
        .setStyle(
            NotificationCompat.BigPictureStyle()
                .bigPicture(
                    getBitmapFromUrl(imageUrl)
                )
        )

Bundle[mParcelledData.dataSize=]ってなんやねん

ハマりポイント1

push通知からputExtraして起動するactivityに値を渡し際に

activityから取得できる値が

Bundle[mParcelledData.dataSize=120]

みたいな感じになってしまっている

ハマりポイント1@結論 受け取れている

for (key in intent.extras?.keySet() ?: listOf()) {
            val value = intent.extras?.getString(key)
            Timber.d(
                "extrasKeyValue: $key $value}"
            )
        }

するとことで値をちゃんと確認できる。

元々普通に確認できていた気がしていたので謎のmParcelledDataになっていて無駄にハマった

ハマりポイント2

Push通知にintent.extrasして画面遷移させる場合

遷移した後バックしても無限ループしてしまう


ハマりポイント2@結論 ちゃんと消してあげる

activity?.intent?.removeExtra(PushNotificationKeyType.PinpointJsonBody.keyName)

的なことをして遷移処理した後でちゃんと値を消してあげる。

safeArgsで渡す場合は

private val args by navArgs<HogeArgs>()
private var navArgs: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        navArgs = args.announcementId
    }

してnavArgsの方を参照するようにしてあげる。


ハマりポイント3

// クラッシュする
// 通知チャンネルの作成
        val name = ""
        val descriptionText = ""
        val channelId = BuildConfig.APPLICATION_ID + name
        val channel =
            NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_DEFAULT).apply {
                description = descriptionText
            }
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // チャンネルをシステムに登録
        notificationManager.createNotificationChannel(channel)
	
// クラッシュしない
// 通知チャンネルの作成
        val name = "hogehoge"
        val descriptionText = "fugafuga"
        val channelId = BuildConfig.APPLICATION_ID + name
        val channel =
            NotificationChannel(channelId, name, NotificationManager.IMPORTANCE_DEFAULT).apply {
                description = descriptionText
            }
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // チャンネルをシステムに登録
        notificationManager.createNotificationChannel(channel)

チャンネルネームが空文字だとクラッシュする模様

https://stackoverflow.com/questions/49072959/creating-a-notificationchannel-throws-an-illegalargumentexception

参考記事

https://developer.android.com/training/notify-user/build-notification?hl=ja

https://firebase.google.com/docs/cloud-messaging/android/receive#handling_messages

https://qiita.com/ryo_mm2d/items/77cf4e6da7add219c75c

https://muumuutech.hatenablog.com/entry/2021/05/31/205855

https://stackoverflow.com/questions/62639146/android-navargs-clear-on-back

https://www.chikach.net/category/android-app/appwidget-listview-fillin/

https://stackoverflow.com/questions/4520961/removing-extras-from-passed-in-intent

https://stackoverflow.com/questions/36877196/android-intents-passed-one-bundle-to-secondactivity

Discussion

ログインするとコメントできます