Есть активити MainActivity и сервис MyFirebaseMessagingService, который получает пуш-сообщение. Мне это сообщение нужно вывести в виде диалога. Проблема в том, что Toast выводится, а вот AlertDialog нет - приложение крашиться. Вот мой код в сервисе:
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "Adrenalin:MyFirebaseMsgService";
/**
* Called when message is received.
*
* @param remoteMessage Object representing the message received from Firebase Cloud Messaging.
*/
// [START receive_message]
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
if (/* Check if data needs to be processed by long running job */ true) {
// For long-running tasks (10 seconds or more) use Firebase Job Dispatcher.
//scheduleJob();
} else {
// Handle message within 10 seconds
handleNow();
}
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
final String remMesBody = remoteMessage.getNotification().getBody();
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
//Toast.makeText(getApplicationContext(),remMesBody,Toast.LENGTH_LONG).show();
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setTitle("Важное сообщение!")
.setMessage(remMesBody)
.setIcon(R.drawable.ic_adrenalin)
.setCancelable(false)
.setNegativeButton("ОК",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
});
}
// 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.
}
/**
* Handle time allotted to BroadcastReceivers.
*/
private void handleNow() {
Log.d(TAG, "Short lived task is done.");
}
}
Там виден закоментированный Toast, который успешно работает.
Лог краша:
05-25 09:00:32.122 2700-2700/ru.arm_prokat.bicycle.adrenalin E/AndroidRuntime: FATAL EXCEPTION: main
Process: ru.arm_prokat.bicycle.adrenalin, PID: 2700
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:800)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:351)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.app.Dialog.show(Dialog.java:322)
at ru.arm_prokat.bicycle.adrenalin.MyFirebaseMessagingService$1.run(MyFirebaseMessagingService.java:65)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Вы используете режим Data и в таком случае ваш сервис может получить сообщение в том числе когда нет приложения в Foreground, соответственно нет лупера и т.д.
Правильно это делать так - делать нотификацию для открытия активити с определенными параметры, которые уже инициируют dialog - либо более кастомизированную карточку нотификации.
Если все таки вам надо диалог, то думаю что надо делать: - на уровне приложения подписаться на события жизненного цикла - через broadcast listener кинуть нотификацию - если мы в режиме foreground таки показать диалог. Но вообще так делать не принято.
В общем просидел полдня над этой задачей, но решил её! В классе mainActivity добавил следующее:
@Override
protected void onResume(){
super.onResume();
IntentFilter intentFilter = new IntentFilter(MyFirebaseMessagingService.ACTION_FILTER);
intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(broadcastReceiver, intentFilter);
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//do something
String msg = intent.getStringExtra("text_for_alert");
Log.d(TAG, "Message from BroadcastReceiver: " + msg);
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Важное сообщение!")
.setMessage(msg)
.setIcon(R.drawable.ic_adrenalin)
.setCancelable(false)
.setNegativeButton("ОК",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
abortBroadcast(); //отменяет дальнейшую обработку бродкаста
}
};
А в сервисе
public static final String ACTION_FILTER = "ru.adrenalin.DIALOG";
//
//
//
//
if (remoteMessage.getNotification() != null) {
final String remMesBody = remoteMessage.getNotification().getBody();
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
Intent intent = new Intent(ACTION_FILTER);
intent.putExtra("text_for_alert",remMesBody);
sendOrderedBroadcast(intent, null);
}
Теперь при получении сообщения, когда активно приложение - открывается алерт. Само приложение у меня основано на webview, там просто подгружаются данные из вебсайта и разная информация. Следующий этап - хочу сделать так, чтобы когда получается пуш-уведомление в бэкграунде, то при тапе по пушу - открывалась в приложении какая-то информация, а то сейчас просто происходит открытие приложения
Возможно где-то криво, но всего несколько дней изучаю андроид! Надеюсь кому-нибудь поможет данный код!
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Какие существуют виды рекламных бордов и как выбрать подходящий?
В бд первичный ключ находится в столбце id_dish(проверено 10 тыщ раз))
Для обращения из внутреннего класса Inner к экземпляру обрамляющего класса Outer используется следующая запись:
Как добавить javadoc в jar файл при сборке проекта командой gradle build?