I develop an Android application, where the user can receive an earthquake information. If user's device has location close to the earthquake location, the notification will have 2 buttons to confirm if they're being safe or evacuated from that happening earthquake. I'm stuck in a process while the user press 1 of the 2 buttons in notification (SAFE or EVACUATED).
Here is my code :
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;
}
}
I expect (example) if user press SAFE
button in notification, it will safe the confirmation status from the user from NOTIFIED
(default) to SAFE
in database server, and so on. But it returns an error :
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)
Any solution?