簡體   English   中英

具有操作按鈕的FCM推送通知不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM