Firebase (FCM): открывать активность и передавать данные по уведомлению. андроид
Должна быть четкая реализация того, как работать с уведомлением и данными Firebase. Я прочитал много ответов, но не могу заставить его работать. вот мои шаги:
1.) Я передаю уведомление и данные в андроид в PHP, и это кажется прекрасным:
$msg = array
(
"body" => $body,
"title" => $title,
"sound" => "mySound"
);
$data = array
(
"user_id" => $res_id,
"date" => $date,
"hal_id" => $hal_id,
"M_view" => $M_view
);
$fields = array
(
'registration_ids' => $registrationIds,
'notification' => $msg,
'data' => $data
);
$headers = array
(
'Authorization: key='.API_ACCESS_KEY,
'Content-Type: application/json'
);
$ch = curl_init();
curl_setopt( $ch,CURLOPT_URL, 'https://android.googleapis.com/gcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
2.), когда уведомление и данные получены в Android, он показывает уведомление. Когда я нажимаю на это уведомление, он открывает приложение. Но я не могу понять способ обработки данных при открытии приложения. Есть несколько отличий, когда приложение находится на переднем плане и на заднем плане. Код, который у меня есть, следующий:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String user_id = "0";
String date = "0";
String cal_id = "0";
String M_view = "0";
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
user_id = remoteMessage.getData().get("user_id");
date = remoteMessage.getData().get("date");
hal_id = remoteMessage.getData().get("hal_id");
M_view = remoteMessage.getData().get("M_view");
}
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody(), user_id, date, hal_id, M_view);
}
private void sendNotification(String messageBody, String user_id, String date, String hal_id, String M_view) {
Intent intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("fcm_notification", "Y");
intent.putExtra("user_id", user_id);
intent.putExtra("date", date);
intent.putExtra("hal_id", hal_id);
intent.putExtra("M_view", M_view);
int uniqueInt = (int) (System.currentTimeMillis() & 0xff);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), uniqueInt, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.drawable.ic_launcher)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}}
3.) Когда я использую код выше, и когда я нажимаю на уведомление, все, что он делает, открывает приложение, если в фоновом режиме. Если приложение на переднем плане, то при уведомлении нажмите его, просто отклонит уведомление. Тем не менее, я хочу получать данные и открывать конкретную активность в обоих сценариях (фон и переднем плане). У меня в MainActivity следующий код, но я не могу получить данные. fcm_notification, date, hal_id возвращает null.
public class MainActivity extends Activity {
UserFunctions userFunctions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
Intent intent_o = getIntent();
}
@Override
protected void onResume() {
super.onResume();
userFunctions = new UserFunctions();
if(userFunctions.isUserLoggedIn(getApplicationContext())){
Intent intent_o = getIntent();
String fcm_notification = intent_o.getStringExtra("fcm_notification") ;
String user_id = intent_o.getStringExtra("user_id");
String date = intent_o.getStringExtra("date");
String hal_id = intent_o.getStringExtra("hal_id");
String M_view = intent_o.getStringExtra("M_view");
Intent intent = new Intent(this, JobList.class);
// THIS RETURNS NULL, user_id = null
System.out.print("FCM" + user_id);
startActivity(intent);
finish();
}else{
// user is not logged in show login screen
Intent login = new Intent(this, LoginActivity.class);
startActivity(login);
// Closing dashboard screen
finish();
}
}}
ЕСЛИ кто-нибудь может направить или посоветовать, как я могу получить данные в MainActivity.java из Firebase в любом сценарии (на переднем плане или в фоновом режиме), который был бы фантастическим.
Ответы
Ответ 1
После того, как все ответы и блоги пришли к решению, если кому-то нужно, пожалуйста, используйте это видео как ссылку
https://www.youtube.com/watch?v=hi8IPLNq59o
В добавлении к видео, чтобы добавить намерения в MyFirebaseMessagingService:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "MyFirebaseMsgService";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
String user_id = "0";
String date = "0";
String hal_id = "0";
String M_view = "0";
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
user_id = remoteMessage.getData().get("user_id");
date = remoteMessage.getData().get("date");
cal_id = remoteMessage.getData().get("hal_id");
M_view = remoteMessage.getData().get("M_view");
}
String click_action = remoteMessage.getNotification().getClickAction();
//Calling method to generate notification
sendNotification(remoteMessage.getNotification().getBody(), remoteMessage.getNotification().getTitle(), user_id, date, hal_id, M_view, click_action);
}
private void sendNotification(String messageBody, String messageTitle, String user_id, String date, String hal_id, String M_view, String click_action) {
Intent intent = new Intent(click_action);
intent.putExtra("user_id", user_id);
intent.putExtra("date", date);
intent.putExtra("hal_id", hal_id);
intent.putExtra("M_view", M_view);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this);
notificationBuilder.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(messageTitle)
.setContentText(messageBody)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}}
и в новой активности NotificationReceive в onCreate или onResume добавьте это
notification_Y_N = (TextView) findViewById(R.id.notification_Y_N);
user_id_text = (TextView) findViewById(R.id.user_id_text);
Intent intent_o = getIntent();
String user_id = intent_o.getStringExtra("user_id");
String date = intent_o.getStringExtra("date");
String hal_id = intent_o.getStringExtra("hal_id");
String M_view = intent_o.getStringExtra("M_view");
notification_Y_N.setText(date);
user_id_text.setText(hal_id);
Ответ 2
Итак, прежде всего, я расскажу о деталях, упомянутых в "Обработка сообщений" .
В сводке в строке Both показано, что когда приложение находится на переднем плане, полезная нагрузка будет обрабатываться в вашем onMessageReceived()
.
Чтобы открыть активность из onMessageReceived()
, вы должны проверить, нужны ли данные в полезной нагрузке, если это так, вызовите свое конкретное действие, а затем передайте все другие детали, которые вам нужны, с помощью намерения.
Теперь, если приложение находится в фон, в документах указано, что уведомление получено на панели задач Android и что полезная нагрузка data
может быть извлечена из дополнительных настроек намерения.
Просто добавьте подробности из моего ответа здесь, который в значительной степени просто дает инструкцию docs и ссылку на образец:
Отправлять уведомления в фоновом приложении
Когда ваше приложение находится в фоновом режиме, Android направляет уведомления на системный трей. Пользователь по нажатию на уведомление открывает панель запуска приложения по умолчанию.
Это включает сообщения, содержащие как полезную нагрузку уведомлений и данных (и все сообщения, отправленные с консоли уведомлений). В этих случаях уведомление доставляется на системный лоток устройства, а полезная нагрузка данных доставляется в дополнение к цели вашей активности запуска.
Я думаю, что этот ответ от @ArthurThompson очень хорошо объясняет:
Когда вы отправляете сообщение уведомления с полезной нагрузкой (уведомлением и данными), а приложение находится в фоновом режиме, вы можете получить данные из дополнительных функций намерения, которые запускаются в результате нажатия пользователем уведомления.
Из образец FCM, который запускает MainActivity при прослушивании уведомления:
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
String value = getIntent().getExtras().getString(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
}
}
Ответ 3
Чтобы вызвать метод onMessageReceived()
, вам нужно будет использовать другой метод для отправки уведомлений (например, создание веб-API для отправки уведомлений). Затем, используя его,
удалите полезную нагрузку уведомления из ваших сообщений FCM, чтобы получить полезную нагрузку данных, переданную методу onMessageReceived()
.
Когда ваше приложение находится в фоновом режиме, полезная нагрузка данных доставляется методу onMessageReceived
только в том случае, если нет полезной нагрузки для уведомления.
В случае, если обе полезной нагрузки существуют, система автоматически обрабатывает (системный лоток), и ваше приложение получает полезную нагрузку данных в дополнительные сведения о намерении запуска программы (после того, как пользователь нажал уведомление).
Для получения дополнительной информации см. следующие ссылки:
Ответ 4
Вам не нужно выполнять sendNotification
и onMessageReceived
самостоятельно.
При отправке:
$data = array
(
"user_id" => $res_id
//whatever fields you want to include
);
$msg = array
(
"body" => $body,
"title" => $title,
"data" => $data
// more fields
);
Сторона андроида (на вашем MainACtivity
:
private void handleIntent(Intent intent) {
String user_id= intent.getStringExtra("user_id");
if(user_id!= null)
Log.d(TAG, user_id);
}
и, конечно же,
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handleIntent(getIntent());
}
любые поля, которые вы помещаете в data
будут отправлены на ваше намерение extra
.