Search code examples
androidkotlinandroid-intentandroid-pendingintentandroid-intent-chooser

PendingIntent with Intent Chooser


I'm trying to send a notification from Firebase with some info. Then, when the message is received I want to create a notification that has an action when a button on that notification is clicked. I want that action to be an IntentChooser. I'm creating the notification like so:

            val intentChooser: Intent = IntentUtils.getChoosingIntent(this)
            val pendingIntent =
                PendingIntent.getActivity(
                    this,
                    reqCode,
                    intentChooser,
                    PendingIntent.FLAG_IMMUTABLE
                )

            val CHANNEL_ID = "channel_name" // The id of the channel.

            val notificationBuilder: NotificationCompat.Builder =
                NotificationCompat.Builder(this, CHANNEL_ID)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentTitle(it.title)
                    .setContentText(it.body)
                    .setAutoCancel(true)
                    .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
                    .setContentIntent(pendingIntent)
                    .addAction(
                        NotificationCompat.Action(
                            R.drawable.baseline_assistant_direction_24,
                            "Directions",
                            pendingIntent
                        )
                    )
            val notificationManager =
                this.getSystemService(NOTIFICATION_SERVICE) as NotificationManager

            val name: CharSequence = "Channel Name" // The user-visible name of the channel.
            val importance = NotificationManager.IMPORTANCE_HIGH
            val mChannel = NotificationChannel(CHANNEL_ID, name, importance)
            notificationManager.createNotificationChannel(mChannel)

            notificationManager.notify(
                reqCode,
                notificationBuilder.build()
            ) // 0 is the request code, it should be unique id

And the getChoosingIntent()is this:

        fun getChoosingIntent(context: Context, lat: Double, long: Double): Intent {

        val arr = arrayListOf<Intent>()

        val intent1 = Intent(Intent.ACTION_VIEW, Uri.parse(someUri))
        intent1.setPackage(somePackage)
        arr.add(intent1)

        val intent2 = Intent(Intent.ACTION_VIEW, Uri.parse(someUri))
        intent2.setPackage(somePackage)
        arr.add(intent2)

        val mainIntent = Intent(Intent.ACTION_VIEW)
        val title = "title"
        val chooserIntent = Intent.createChooser(mainIntent, title)
        chooserIntent.putParcelableArrayListExtra(Intent.EXTRA_INITIAL_INTENTS, arr)
        chooserIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
        return chooserIntent
    }

This is throwing an error:

Attempt to cast generated internal exception:
                                                                                                    java.lang.ClassCastException: java.util.ArrayList cannot be cast to android.os.Parcelable[]
                                                                                                        at android.os.Bundle.getParcelableArray(Bundle.java:980)
                                                                                                        at android.content.Intent.getParcelableArrayExtra(Intent.java:8974)
                                                                                                        at android.content.Intent.migrateExtraStreamToClipData(Intent.java:12111)
                                                                                                        at android.app.PendingIntent.getActivityAsUser(PendingIntent.java:486)
                                                                                                        at android.app.PendingIntent.getActivity(PendingIntent.java:470)
                                                                                                        at android.app.PendingIntent.getActivity(PendingIntent.java:434)
                                                                                                        at com.rfsfernandes.findmyhere.firebase.MobileFirebaseMessageService.onMessageReceived(MobileFirebaseMessageService.kt:46)
                                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.dispatchMessage(FirebaseMessagingService.java:243)
                                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.passMessageIntentToSdk(FirebaseMessagingService.java:193)
                                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.handleMessageIntent(FirebaseMessagingService.java:179)
                                                                                                        at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(FirebaseMessagingService.java:168)
                                                                                                        at com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$com-google-firebase-messaging-EnhancedIntentService(EnhancedIntentService.java:82)
                                                                                                        at com.google.firebase.messaging.EnhancedIntentService$$ExternalSyntheticLambda0.run(Unknown Source:6)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
                                                                                                        at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.1.0:2)
                                                                                                        at java.lang.Thread.run(Thread.java:1012)

Is there something else that I should try? I really don't want to manually create a chooser


Solution

  • try this

    fun getChoosingIntent(context: Context, lat: Double, long: Double): Intent {
        val gmmIntentUri = Uri.parse("geo:$lat,$long?q=$lat,$long")
        val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
        mapIntent.setPackage("com.google.android.apps.maps")
    
        val chooserIntent = Intent.createChooser(mapIntent, "Open with")
    
        val otherIntents = ArrayList<Intent>()
        val additionalIntent = Intent(Intent.ACTION_VIEW, Uri.parse("someUri"))
        additionalIntent.setPackage("com.example.app")
        otherIntents.add(additionalIntent)
    
        if (otherIntents.isNotEmpty()) {
            val extraIntents = otherIntents.toTypedArray()
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents)
        }
    
        return chooserIntent
    }
    

    and where you handle the notification use something like this

    val intentChooser = getChoosingIntent(this, latitude, longitude) // Replace with actual values
    val pendingIntent = PendingIntent.getActivity(
        this,
        reqCode,
        intentChooser,
        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )