首页 > 解决方案 > 基于应用状态的 Firebase 推送通知

问题描述

我目前正在使用 Firebase Cloud Messaging 处理推送通知。我实现的一切工作正常,我正在接收我想要的推送通知(关于我的应用程序是在前台、后台还是被杀死)但我的问题是:

(为了便于阅读,我将分步提出我的问题)

  1. 我的应用程序正在运行并且它在前台。
  2. 我收到推送通知,但我没有立即打开它
  3. 我通过任务管理器杀死应用程序
  4. 我尝试使用通知打开应用程序,但我的应用程序中断并且无法打开。(我知道这是因为我之前制作的 Intent 对象,但我没有找到任何关于这种情况的文档。有什么方法可以操纵托盘中已经显示的相同通知,以便其意图发生变化? )

我的应用程序骨架由几个活动和许多片段组成。它从启动器活动开始,如果它检查的每个参数都很好,它会调用我的主要活动。

我的推送通知应该打开一个通知片段,如果 Intent 用于相同的应用程序状态(背景、前景或已终止),它会这样做。

这是我的 Firebase 课程

class MyFirebaseMessagingService : FirebaseMessagingService() {

    val userPreferences = UserPreferences()

    /**
     * Called when message is received.
     *
     * @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
     */
    // [START receive_message]
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        // [START_EXCLUDE]
        // There are two types of messages data messages and notification messages. Data messages are handled
        // here in onMessageReceived whether the app is in the foreground or background. Data messages are the type
        // traditionally used with GCM. Notification messages are only received here in onMessageReceived when the app
        // is in the foreground. When the app is in the background an automatically generated notification is displayed.
        // When the user taps on the notification they are returned to the app. Messages containing both notification
        // and data payloads are treated as notification messages. The Firebase console always sends notification
        // messages. For more see: https://firebase.google.com/docs/cloud-messaging/concept-options
        // [END_EXCLUDE]

        // TODO(developer): Handle FCM messages here.
        // Not getting messages here? See why this may be:

        // Check if message contains a data payload.
        remoteMessage.data.isNotEmpty().let {
            val messageTitle: String = remoteMessage.data["title"] ?: "Hotel"
            val message: String = remoteMessage.data["message"] ?: "You have new notification"
            val groupId: String = remoteMessage.data["group_id"]?: "0"
            val id: String = remoteMessage.data["id"]?: "0"

            if(!userPreferences.visibleFragment.isNullOrEmpty() && groupId=="3")//IF NOT NULL OR EMPTY MUST BE CHATFRAGMENT
            {
                //no message since its chat notification and the chatfragment is visible
            }
            else
            {
                if(groupId=="4")
                {
                    MainActivity.isNotificationIconVisible.postValue(true)
                    userPreferences.isNotificationIconVisible=true
                }
                sendNotification(messageTitle, message, groupId, id)
            }
        }
        // Check if message contains a notification payload.
        remoteMessage.notification?.let {
        }



        // Also if you intend on generating your own notifications as a result of a received FCM
        // message, here is where that should be initiated. See sendNotification method below.
    }
    // [END receive_message]

    // [START on_new_token]
    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {


    }
    // [END on_new_token]



    /**
     * Handle time allotted to BroadcastReceivers.
     */
    private fun handleNow() {

    }

    /**
     * Persist token to third-party servers.
     *
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private fun sendRegistrationToServer(token: String?) {

    }

    /**
     * Create and show a simple notification containing the received FCM message.
     *
     * @param messageBody FCM message body received.
     */
    private fun sendNotification(messageTitle: String, messageBody: String, groupId : String, id : String) {

        val intent =
                if (userPreferences.isAppDestroyed) {
                    Intent(this, MainActivity::class.java)
                } else {
                    Intent(this, MainActivity::class.java)
                        .putExtra("id", id)
                        .putExtra("groupid", groupId)
                        .putExtra("appDestroyed", userPreferences.isAppDestroyed)
                }
            val pendingIntent =
                if(userPreferences.isAppDestroyed)
                {
                    TaskStackBuilder.create(this).run {
                        addNextIntentWithParentStack(intent)
                        editIntentAt(0).putExtra("id", id).putExtra("groupid", groupId).putExtra("appDestroyed", userPreferences.isAppDestroyed)
                        getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
                    }
                }
                else
                {
                    PendingIntent.getActivity(this, 0 , intent, PendingIntent.FLAG_UPDATE_CURRENT)
                }

        val mode = applicationContext?.resources?.configuration?.uiMode?.and(Configuration.UI_MODE_NIGHT_MASK)
        val channelId = "1"
        val defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
        val notificationBuilder = NotificationCompat.Builder(this, channelId)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            when (mode) {
                Configuration.UI_MODE_NIGHT_YES -> {
                    notificationBuilder.setSmallIcon(R.drawable.ic_notification_icon_from_asset)
                    notificationBuilder.setColor(Color.TRANSPARENT)
                }
                Configuration.UI_MODE_NIGHT_NO -> {
                    notificationBuilder.setSmallIcon(R.drawable.ic_notification_icon_from_asset)
                    notificationBuilder.setColor(Color.GRAY)
                }
                else -> {
                    notificationBuilder.setSmallIcon(R.drawable.ic_notification_icon_from_asset)
                    notificationBuilder.setColor(Color.TRANSPARENT)
                }
            }

        } else {
            notificationBuilder.setSmallIcon(R.mipmap.ic_notification_icons)
        }
            .setContentTitle(messageTitle)
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent)

        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Since android Oreo notification channel is needed.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(channelId,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT)
            notificationManager.createNotificationChannel(channel)
        }
        notificationManager.notify(1, notificationBuilder.build())
    }
}

MainActivity onNewIntent fun(片段事务代码被注释,测试了一些东西)

    override fun onNewIntent(intent: Intent?) {
            super.onNewIntent(intent)
            val data = intent?.extras
            val groupId = data?.getString("groupid")
            val id = data?.getString("id")
            if (data != null) {
                if (groupId == "4") {
                    val bundle = bundleOf("pushNotificationId" to id)
                    navController.navigate(R.id.notificationDetailsFragment, bundle)
                    /*val fragment = NotificationDetailsFragment()
                    fragment.arguments=bundle
                    val ft = supportFragmentManager.beginTransaction()
                    ft.replace(R.id.main_nav_fragment, fragment)
                    ft.commit()*/
                }
                else return
            }
            return
        }
    }

启动器活动

class LauncherActivity : AppCompatActivity(){

    private val vm: LauncherViewModel by viewModel()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        injectFeature()
        // set observables
        vm.isSplashScreenShown.observe(this, Observer {

            finish()

            when (it) {
                true -> startActivity(Intent(this, MainActivity::class.java).putExtra("id",intent?.extras?.getString("id"))
                    .putExtra("groupid",intent?.extras?.getString("groupid")))
                false -> startActivity(Intent(this, WelcomeActivity::class.java))
            }
        })
    }
}

如果需要,我的清单的一部分

<activity
            android:name=".presentation.launcher.LauncherActivity"
            android:label="@string/app_name"
            android:theme="@style/BaseAppTheme.NoActionBar.SplashScreenTheme"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".presentation.welcome.WelcomeActivity"
            android:screenOrientation="portrait"
            android:theme="@style/BaseAppTheme.NoActionBar.TransparentTheme"
            android:windowSoftInputMode="adjustResize" />
        <activity
            android:name=".presentation.error.ErrorActivity"
            android:screenOrientation="portrait"
            android:theme="@style/BaseAppTheme.NoActionBar.TransparentTheme" />
        <activity
            android:name=".presentation.main.MainActivity"
            android:theme="@style/BaseAppTheme.NoActionBar.TransparentTheme"
            android:screenOrientation="portrait"
            android:launchMode="singleTask"
            android:parentActivityName=".presentation.launcher.LauncherActivity"/>

我很想像 Whatsapp 一样完成它(whatsapp 会打开他们的聊天,即使重复我为我的应用程序所做的步骤)

非常感谢,如果需要更多内容或我需要重新格式化我的问题,请建议我这样做。

标签: androidfirebaseandroid-intentpush-notificationfirebase-cloud-messaging

解决方案


推荐阅读