[英]FCM Push Notification with Action Button Not Working
我開發了一個Android應用程序,用戶可以在其中接收地震信息。 如果用戶的設備位置靠近地震位置,通知將有2個按鈕,以確認他們是否安全或從發生的地震中撤離。 當用戶按下通知中的2個按鈕中的1個(SAFE或EVACUATED)時,我陷入了一個過程。
這是我的代碼:
MyFirebaseInstanceService.java
private void showNotification(String title, String body) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String NOTIFICATION_CHANNEL_ID = "com.example.yohan.notifgempafcm";
Intent amanIntent = setIntent(body, "SAFE");
Intent evakuasiIntent = setIntent(body, "EVACUATED");
PendingIntent pendingIntentAman = PendingIntent.getBroadcast(this, 0, amanIntent, PendingIntent.FLAG_UPDATE_CURRENT);
PendingIntent pendingIntentEvakuasi = PendingIntent.getActivity(this, 1, evakuasiIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Notification",
NotificationManager.IMPORTANCE_DEFAULT);
notificationChannel.enableLights(true);
notificationChannel.setDescription("Info Gempa");
notificationChannel.setLightColor(Color.BLUE);
if (title.contains("WASPADA GEMPA")) {
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
}
notificationManager.createNotificationChannel(notificationChannel);
}
NotificationCompat.Action actAman = new NotificationCompat.Action.Builder(android.R.drawable.ic_secure, "AMAN", pendingIntentAman).build();
NotificationCompat.Action actEvakuasi = new NotificationCompat.Action.Builder(android.R.drawable.ic_partial_secure, "EVAKUASI", pendingIntentEvakuasi).build();
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
notificationBuilder.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.setContentText(body)
.setContentInfo("Info");
if (title.contains("WASPADA GEMPA")) {
notificationBuilder.addAction(actAman);
notificationBuilder.addAction(actEvakuasi);
}
final Notification notification = notificationBuilder.build();
notificationManager.notify(11111, notification);
}
public Intent setIntent(String body, String status){
Intent intent = new Intent(this, NotificationActionReceiver.class);
intent.putExtra("tanggal", (body.split(" ")[2] + " " + body.split(" ")[3]));
intent.putExtra("token", token);
intent.putExtra("status", status);
return intent;
}
NotificationActionReceiver.java
public class NotificationActionReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String tanggal = intent.getStringExtra("tanggal");
String token = intent.getStringExtra("token");
String status = intent.getStringExtra("status");
konfirmasi(context, tanggal, token, status);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(11111);
}
public void konfirmasi(final Context context, String tanggal, String token, String status){
HashMap<String, String> data = pushData(tanggal, token, status);
PostResponseAsyncTask konfirm = new PostResponseAsyncTask(context, data, new AsyncResponse() {
@Override
public void processFinish(String s) {
if (s.equals("UPDATED")){
Toast.makeText(context, "Konfirmasi berhasil disimpan", Toast.LENGTH_SHORT).show();
}
}
});
konfirm.execute(LoginActivity.URL + "notifikasi/changeStatus");
}
public HashMap<String, String> pushData(String tanggal, String token, String status){
HashMap<String, String> data = new HashMap<>();
data.put("datetime", tanggal);
data.put("token", token);
data.put("konfirmasi", status);
return data;
}
}
我希望(例子)如果用戶在通知中按下SAFE
按鈕,它將保證用戶的確認狀態從NOTIFIED
(默認)到數據庫服務器中的SAFE
,依此類推。 但它返回一個錯誤:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.yohan.notifgempafcm, PID: 3821
java.lang.RuntimeException: Unable to start receiver com.example.yohan.notifgempafcm.NotificationActionReceiver: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2621)
at android.app.ActivityThread.access$1700(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:569)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:282)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
at android.app.Dialog.show(Dialog.java:298)
at com.kosalgeek.genasync12.PostResponseAsyncTask.onPreExecute(PostResponseAsyncTask.java:151)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)
at android.os.AsyncTask.execute(AsyncTask.java:539)
at com.example.yohan.notifgempafcm.NotificationActionReceiver.konfirmasi(NotificationActionReceiver.java:36)
at com.example.yohan.notifgempafcm.NotificationActionReceiver.onReceive(NotificationActionReceiver.java:21)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:2614)
at android.app.ActivityThread.access$1700(ActivityThread.java:153)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1382)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5293)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
有解決方案嗎
在這種情況下,容易出錯的代碼是
Toast.makeText(context, "Konfirmasi berhasil disimpan", Toast.LENGTH_SHORT).show();
BroadcastReceiver
允許運行最多10秒。 如果你訪問后面的上下文它將無效(這是你的情況)。 此外,如果這是當時進程中唯一的內容,那么此進程將被終止,並且它不會關心您的API是否被調用。 因此,您不應該直接在#onReceive()
內部進行長時間運行。
文檔
要使用代碼解決此問題,可以使用goAsync() 。 這將在從該功能返回后保持廣播活動。 在使用之前,請閱讀#goAsync()
的文檔。
以下是goAsync()的示例 。
為此更優雅的方式您可以啟動一個IntentService
,它自動處理后台線程中的API調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.