Android FCM 在应用被终止时部分工作
Android FCM working partly while app is killed
我的 MyFirebaseMessagingService.java 中有 2 种通知生成器,一种传递名为 'lecture_date' 的字符串并打开 Lectures_graph.class,而另一种传递名为 'web_url' 的字符串并打开webview_base.class 单击时。
我想要实现的目标:即使应用程序被终止,FCM 通知也能完全正常工作,通知必须在单击后打开 activity(带有附加功能)。
我有多远:我可以收到打开 Lectures_graph.class 的通知,带有 intent extras,一切都加载并工作正常。即使我收到 webview_base.class activity 的通知,当我点击通知时也没有任何反应。
可能有一件事指向问题 - Logcat 经常告诉我:
E/FirebaseMessaging: Notification pending intent canceled
我正在使用 PHP 发送通知(该代码 100% 正确且有效),下面的代码显示了 JSON 为 webview_base.class [=51] 发送的想法=].要发送 Lectures_graph.class activity 的通知,我只需将 click_action 从“OPEN_ACTIVITY_WEBVIEW”交换为“OPEN_ACTIVITY_LECTURES”并更改数据负载。 PHP for webview_base.class activity 送走这样的数据:
$msg = array
(
'body' => 'test body',
'title' => "test title",
'click_action' => 'OPEN_ACTIVITY_WEBVIEW',
'channelId' => "newsfeed",
'vibrate' => 1,
'sound' => 1
);
//sends notifications via topics
$fields = array
(
"data" => [
'web_url' => $_POST['notification_url']
],
'notification' => $msg,
'to' => '/topics/test'
);
这是我来自 Android 工作室的完整清单文件:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="secret">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme.CustomTheme"
android:usesCleartextTraffic="true"
tools:targetApi="m">
<activity
android:name=".systems.webview_activity.webview_base"
android:configChanges="orientation|screenSize">
<intent-filter>
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="file" />
<data android:mimeType="\*/\*" />
<data android:pathPattern=".*\.kdb" />
<data android:host="*" />
//even if this method worked with Lectures_graph activity
//it doesnt work with this one
<action android:name="OPEN_ACTIVITY_WEBVIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".systems.lectures.Lectures_graph"
android:configChanges="keyboardHidden|screenSize"
android:label="@string/title_lectures_graph"
>
<intent-filter>
//this intent filter provides correct response
//to click_action which is provided in my PHP file
<action android:name="OPEN_ACTIVITY_LECTURES" />
<action android:name = "android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".SplashScreen"
android:configChanges="keyboardHidden|orientation|screenSize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NoInternetConnection"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name="secret.systems.about.about_app"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullscreenTheme" />
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
<service
android:name="secret.services.MyFirebaseMessagingService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
MyFirebaseMessagingService.java:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
//get key/value from notification
String lectureDate = remoteMessage.getData().get("lecture_date");
String web_url = remoteMessage.getData().get("web_url");
if(lectureDate != null)sendLecturesNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), lectureDate);
else if(web_url != null) sendNotificationWithURL(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), web_url);
else Log.e(TAG, "Message.notification is empty!");
}
}
@Override
public void onNewToken(@NonNull String token) {
Log.d(TAG, "Refreshed token: " + token);
}
private void sendLecturesNotification(String title,String messageBody, String date) {
Intent intent;
intent = new Intent(this, Lectures_graph.class).putExtra("lecture_date", date).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.lectures_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Lectures notification built with date:"+date);
}
private void sendNotificationWithURL(String title, String messageBody, String web_url) {
Intent intent;
intent = new Intent(this, webview_base.class).putExtra("web_url", web_url).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.newsfeed_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Webview notification built with URL:"+web_url);
}
}
不久前,我在 logcat 中收到一条错误消息,内容类似于“未定义默认 FCM 通道”,但我不太确定这就是问题所在。
即使我搜索了整个网络,我也希望看到更好的 solutions/suggestions 在应用程序被杀死时处理通知(及其有效负载)。
所以我解决了我的噩梦,方法如下:
既然我无法从通知中打开多个特定 activity,为什么我只能打开我的应用程序主 class 并从那里处理额外的变量?
而不是每个人都想要activity
<intent-filter>
<action android:name="OPEN_ACTIVITY_???????" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
我做了这个:
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="OPEN_APP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
我向通知负载添加了额外的变量(示例:'activity' => 'webview')并在我的 PHP 代码中重命名为 click_action。我处理了 MainActivity.class 中的所有有效负载,并从那里调用了 wanted android activity。主要活动代码:
Bundle extras = getIntent().getExtras();
if(extras == null) {
Log.e("MainActivity", "No Activities passed in notification extras");
} else {
//get opening activity from notification payload
String activity = extras.getString("activity");
if( activity != null){
switch (activity){
//webview activity
case "webview":
//gets url for webview
String web_url = extras.getString("web_url");
if(web_url != null){
finish();
startActivity(new Intent(this, webview_base.class).putExtra("web_url", web_url));
}
break;
//lectures activity
case "lectures":
//gets lecture date
String lecture_date = extras.getString("lecture_date");
if(lecture_date != null){
finish();
startActivity(new Intent(this, Lectures_graph.class).putExtra("lecture_date", lecture_date));
}
break;
}
}
}
希望有一天这对某人有所帮助..
干杯。
我的 MyFirebaseMessagingService.java 中有 2 种通知生成器,一种传递名为 'lecture_date' 的字符串并打开 Lectures_graph.class,而另一种传递名为 'web_url' 的字符串并打开webview_base.class 单击时。
我想要实现的目标:即使应用程序被终止,FCM 通知也能完全正常工作,通知必须在单击后打开 activity(带有附加功能)。
我有多远:我可以收到打开 Lectures_graph.class 的通知,带有 intent extras,一切都加载并工作正常。即使我收到 webview_base.class activity 的通知,当我点击通知时也没有任何反应。
可能有一件事指向问题 - Logcat 经常告诉我:
E/FirebaseMessaging: Notification pending intent canceled
我正在使用 PHP 发送通知(该代码 100% 正确且有效),下面的代码显示了 JSON 为 webview_base.class [=51] 发送的想法=].要发送 Lectures_graph.class activity 的通知,我只需将 click_action 从“OPEN_ACTIVITY_WEBVIEW”交换为“OPEN_ACTIVITY_LECTURES”并更改数据负载。 PHP for webview_base.class activity 送走这样的数据:
$msg = array
(
'body' => 'test body',
'title' => "test title",
'click_action' => 'OPEN_ACTIVITY_WEBVIEW',
'channelId' => "newsfeed",
'vibrate' => 1,
'sound' => 1
);
//sends notifications via topics
$fields = array
(
"data" => [
'web_url' => $_POST['notification_url']
],
'notification' => $msg,
'to' => '/topics/test'
);
这是我来自 Android 工作室的完整清单文件:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="secret">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/AppTheme.CustomTheme"
android:usesCleartextTraffic="true"
tools:targetApi="m">
<activity
android:name=".systems.webview_activity.webview_base"
android:configChanges="orientation|screenSize">
<intent-filter>
<category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.intent.action.VIEW" />
<data android:scheme="file" />
<data android:mimeType="\*/\*" />
<data android:pathPattern=".*\.kdb" />
<data android:host="*" />
//even if this method worked with Lectures_graph activity
//it doesnt work with this one
<action android:name="OPEN_ACTIVITY_WEBVIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".systems.lectures.Lectures_graph"
android:configChanges="keyboardHidden|screenSize"
android:label="@string/title_lectures_graph"
>
<intent-filter>
//this intent filter provides correct response
//to click_action which is provided in my PHP file
<action android:name="OPEN_ACTIVITY_LECTURES" />
<action android:name = "android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".SplashScreen"
android:configChanges="keyboardHidden|orientation|screenSize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NoInternetConnection"
android:configChanges="keyboardHidden|orientation|screenSize" />
<activity
android:name="secret.systems.about.about_app"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullscreenTheme" />
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
<service
android:name="secret.services.MyFirebaseMessagingService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
MyFirebaseMessagingService.java:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
//get key/value from notification
String lectureDate = remoteMessage.getData().get("lecture_date");
String web_url = remoteMessage.getData().get("web_url");
if(lectureDate != null)sendLecturesNotification(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), lectureDate);
else if(web_url != null) sendNotificationWithURL(remoteMessage.getNotification().getTitle(), remoteMessage.getNotification().getBody(), web_url);
else Log.e(TAG, "Message.notification is empty!");
}
}
@Override
public void onNewToken(@NonNull String token) {
Log.d(TAG, "Refreshed token: " + token);
}
private void sendLecturesNotification(String title,String messageBody, String date) {
Intent intent;
intent = new Intent(this, Lectures_graph.class).putExtra("lecture_date", date).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.lectures_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Lectures notification built with date:"+date);
}
private void sendNotificationWithURL(String title, String messageBody, String web_url) {
Intent intent;
intent = new Intent(this, webview_base.class).putExtra("web_url", web_url).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, ((int) System.currentTimeMillis()) /* Request code */, intent,
0);
String channelId = getString(R.string.newsfeed_channel_id);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, channelId)
.setSmallIcon(R.drawable.secret)
.setContentTitle(title)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.notify(((int) System.currentTimeMillis()), notificationBuilder.build());
}
Log.d(TAG, "Webview notification built with URL:"+web_url);
}
}
不久前,我在 logcat 中收到一条错误消息,内容类似于“未定义默认 FCM 通道”,但我不太确定这就是问题所在。
即使我搜索了整个网络,我也希望看到更好的 solutions/suggestions 在应用程序被杀死时处理通知(及其有效负载)。
所以我解决了我的噩梦,方法如下:
既然我无法从通知中打开多个特定 activity,为什么我只能打开我的应用程序主 class 并从那里处理额外的变量?
而不是每个人都想要activity
<intent-filter>
<action android:name="OPEN_ACTIVITY_???????" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
我做了这个:
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter>
<action android:name="OPEN_APP" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
我向通知负载添加了额外的变量(示例:'activity' => 'webview')并在我的 PHP 代码中重命名为 click_action。我处理了 MainActivity.class 中的所有有效负载,并从那里调用了 wanted android activity。主要活动代码:
Bundle extras = getIntent().getExtras();
if(extras == null) {
Log.e("MainActivity", "No Activities passed in notification extras");
} else {
//get opening activity from notification payload
String activity = extras.getString("activity");
if( activity != null){
switch (activity){
//webview activity
case "webview":
//gets url for webview
String web_url = extras.getString("web_url");
if(web_url != null){
finish();
startActivity(new Intent(this, webview_base.class).putExtra("web_url", web_url));
}
break;
//lectures activity
case "lectures":
//gets lecture date
String lecture_date = extras.getString("lecture_date");
if(lecture_date != null){
finish();
startActivity(new Intent(this, Lectures_graph.class).putExtra("lecture_date", lecture_date));
}
break;
}
}
}
希望有一天这对某人有所帮助..
干杯。