Я использую pyFCM на удаленном сервере для отправки уведомлений о событиях в мое приложение. Уведомление также содержит полезные данные, и это необходимо для внесения некоторых изменений в пользовательский интерфейс.
Когда приложение сервера отправляет приложению уведомление, на телефоне появляется всплывающее уведомление, при нажатии которого открывается действие по умолчанию. Кроме того, я переопределил onMessageReceived в службе, расширяющей FirebaseMessagingService, и полезная нагрузка данных затем берется из сообщения и обрабатывается.
Я видел несколько вопросов по SO, например:
- Как открыть фрагмент по нажатию push-уведомления
- Открыть фрагмент из уведомления, когда приложение в фоновом режиме
- Как открыть фрагмент страницы, когда нажимается уведомление в android
- Открытие фрагмента при нажатии уведомления в андроиде
Одна из общих черт со всеми вышеупомянутыми вопросами SO заключается в том, что они включают создание уведомления с использованием Notification.Builder , а затем настройку открываемого Activity ( или запуск по onNewIntent в зависимости от от того, является ли это Android: launchMode является "singleTop" в манифесте ). Насколько я понимаю, это будет работать, если использовать FCM для отправки приложению сообщения данных , а не уведомления.
Вопрос (ы)
Что я действительно не понимаю, так это то, как настройка уведомления после получения данных от FCM помогает мне изменить поведение уведомления, полученного от толчка FCM. Это вообще возможно, или я что-то не так понял?
Вторая часть этого вопроса: как мне обработать щелчок пользователя на push-уведомлении, чтобы загрузить определенный фрагмент в моей деятельности (когда я не тот, кто создает фрагмент в приложении - только что полученный через FCM)?
Это текущий код, который работает в моем приложении.
Полученный код onMessage:
@Override
public void onMessageReceived(RemoteMessage remoteMessagenew) {
this.remoteMessage = remoteMessagenew;
super.onMessageReceived (remoteMessage);
database = MyDatabase.getDatabase(getApplication());
appuser = database.AppDao().getUserDetails();
Log.d(TAG, "onMessageReceived: ");
Log.d (TAG, "onMessageReceived: #########################################################");
Log.d (TAG, "onMessageReceived: #########################################################");
Log.d (TAG, "onMessageReceived: Message Data is : " + remoteMessage.getData ());
Map messageData = remoteMessage.getData ();
// Broadcast
args = new Bundle ();
int stage = 0 ;
Log.d (TAG, "onMessageReceived: ");
if(messageData.containsKey ("otherid")) {
incidenthandler(messageData);
} else if(messageData.containsKey ("itemid")) {
itemhandler(messageData);
}
}
Обработчик элементов для обработки данных, которые необходимо обновить на экране приложения
private void itemhandler(Map messageData) {
messagebody = remoteMessage.getNotification().getBody();
if(messageData.containsKey("itemid")) {
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: UPDATING");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
String item = (String ) messageData.get("itemid");
JsonParser jsonParser = new JsonParser();
JsonObject jsonObject = (JsonObject)jsonParser.parse(item);
item refreshedItem = parseFromJson(jsonObject);
database.revivDao().upsert(refreshedItem);
} else {
// this really shouldn't happen, but putting in a scenario where this does
// syncing the db with the app
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: REFRESHING ");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
// this triggers a call to my intentservice to refresh the db
Log.d(TAG, "itemhandler: refreshing items");
Intent intent = new Intent ("refreshitems");
Bundle clickdata = new Bundle();
data.putString("item_sub1", item_sub1);
data.putString("item_sub1", item_sub1);
intent.putExtra("data", clickdata) ; // add Bundle to Intent
localBroadcastManager.getInstance(getApplication()).sendBroadcast(intent); // Broadcast Intent
}
String itemid = messageData.get("itemid").toString();
try{
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: sending localbroadcast");
Log.d(TAG, "itemhandler: #######################");
Log.d(TAG, "itemhandler: #######################");
// this is where I try and switch to the screen to display some info - if the app is running
Intent notificationIntent = new Intent("switchtofragment");
notificationIntent.putExtra("launchitemfragment", true);
notificationIntent.putExtra("itemid", itemid);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
if(localBroadcastManager == null) localBroadcastManager = LocalBroadcastManager.getInstance(getApplication());
localBroadcastManager.sendBroadcast(notificationIntent);
// now override the notification to load the fragment on click
setupNotification(itemid, messagebody);
notificationManager.notify(1, builder.build());
} catch (NullPointerException e){
return;
}
}
Наконец, функция для обработки уведомления:
private void setupNotification(String housecallid, String message) {
//Log.d(TAG, "setting up notification");
String idChannel = ANDROID_CHANNEL_ID;
Context context = getApplicationContext();
Intent notificationIntent = new Intent(getApplicationContext(), Reviv.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
notificationIntent.putExtra("housecallid", housecallid);
notificationIntent.putExtra("launchhousecallfragment", true);
Bundle extras = new Bundle();
extras.putBoolean("launchhousecallfragment", true);
extras.putString("housecallid", housecallid);
notificationIntent.putExtras(extras);
notificationIntent.putExtra("data", extras);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0, notificationIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
if(notificationManager == null )
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
builder = new NotificationCompat.Builder(context, null);
builder. setSmallIcon(R.drawable.heart)
.setLargeIcon(BitmapFactory.decodeResource(context.getResources(),
R.drawable.heart))
.setContentIntent(pendingIntent)
.setContentTitle("Reviv")
.setContentText(message);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if(notificationChannel == null) {
notificationChannel = new NotificationChannel(idChannel, context.getString(R.string.app_name), importance);
// Configure the notification channel.
notificationChannel.setDescription("Reviv Housecall Notification");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
notificationManager.createNotificationChannel(notificationChannel);
builder.setChannelId(idChannel);
builder.setAutoCancel(true);
}
} else {
builder.setContentTitle(context.getString(R.string.app_name))
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setColor(ContextCompat.getColor(context, R.color.transparent))
.setVibrate(new long[]{100, 250})
.setLights(Color.RED, 500, 5000)
.setAutoCancel(true);
}
builder.setContentIntent(pendingIntent);
}