android - 基于应用状态的 Firebase 推送通知
问题描述
我目前正在使用 Firebase Cloud Messaging 处理推送通知。我实现的一切工作正常,我正在接收我想要的推送通知(关于我的应用程序是在前台、后台还是被杀死)但我的问题是:
(为了便于阅读,我将分步提出我的问题)
- 我的应用程序正在运行并且它在前台。
- 我收到推送通知,但我没有立即打开它
- 我通过任务管理器杀死应用程序
- 我尝试使用通知打开应用程序,但我的应用程序中断并且无法打开。(我知道这是因为我之前制作的 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 会打开他们的聊天,即使重复我为我的应用程序所做的步骤)
非常感谢,如果需要更多内容或我需要重新格式化我的问题,请建议我这样做。
解决方案
推荐阅读
- java - 如何在java中重复代码
- swift - 生成枚举的这段代码如何在 Swift 中工作?
- python - 如何使用带空格的命令名称?
- api - 发送消息 API 响应中的 Mandrill status = "invalid" 是什么意思
- javascript - jQuery | 如何将下一个json提取到控制台?
- python - 在python中使用滑动窗口概念的GC skew方法
- sql - 使用动态数据库比较两个表
- python - 客观论点在 python 的 xgboost 中是如何工作的?
- javascript - CSS/JS 图像点击更改在多个设备上同步
- c++ - 更好的 CPU 运行时间,并且可以轻松修改以支持 GPU