アプリケーションが開いていて、通知を受け取ったとき、ユーザーが通知をタップしなくても、関連付けられているアクティビティをすぐに開くことができるようにしたいと考えています。
この質問はよく似ています: Firebase通知でアプリを開く(FCM)
しかし、バックグラウンドのときにアプリを開きます。アプリがフォアグラウンドのときに開く必要があります。
firebaseドキュメント から:
アプリがバックグラウンドにあるときに配信される通知。この場合、通知はデバイスのシステムトレイに配信されます。ユーザーが通知をタップすると、デフォルトでアプリランチャーが開きます。通知とデータペイロードの両方を備えたメッセージ(バックグラウンドとフォアグラウンドの両方)。この場合、通知はデバイスのシステムトレイに配信され、データペイロードはランチャーアクティビティのインテントのエクストラで配信されます。
これはonMessageReceived
の私の実装です
_@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification( remoteMessage);
}
}
/**
* Create and show a simple notification containing the received FCM message.
*
* @param remoteMessage FCM message message received.
*/
private void sendNotification(RemoteMessage remoteMessage) {
Intent intent = new Intent(this, MyActivity.class);
Map<String, String> hmap ;
hmap = remoteMessage.getData();
hmap.get("data_info");
intent.putExtra("data_info", hmap.get("data_info"));
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
}
_
通知を正しく受け取ることはできますが、システムトレイの通知をタップして初めてアクティビティが開始されます。
フォアグラウンドで通知をタップせずにアクティビティを開始する方法はありますか?
クラスMyFirebaseMessagingService
のメソッドonMessageReceived()
、つまり_extends FirebaseMessagingService
_がフォアグラウンドで正しく呼び出されていますが、アクティビティは開始されていません。私もフラグ_FLAG_ACTIVITY_NEW_TASK
_を試してみましたが、運もありませんでした。前もって感謝します。
フォアグラウンドアクティビティでのブロードキャストレシーバーの登録と、onReceiveMessage()メソッドからのブロードキャストの送信を実現できます。
ForegroundActivity
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Intent myNewActivity = new Intent(this, MyActivity.class);
startActivity(myNewActivity);
}
};
mIntentFilter=new IntentFilter("OPEN_NEW_ACTIVITY");
@Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
@Override
protected void onPause() {
if(mReceiver != null)
unregisterReceiver(mReceiver);
mReceiver = null;
}
super.onPause();
}
FirebaseNotificationReceiver
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
sendNotification( remoteMessage);
Intent broadcast = new Intent();
broadcast.setAction("OPEN_NEW_ACTIVITY);
sendBroadcast(broadcast);
}
}
アプリがフォアグラウンドにある かどうかを確認するチェックを追加して、通知を送信するか、ブロードキャストを送信するかを選択できます。
(kotlin)チェックするアプリがフォアグラウンドまたはバックグラウンドのいずれかである場合は、onMessageReceived内でこのコードを使用します
var foreground = false
try {
foreground = ForegroundCheckTask().execute(this).get()
} catch (e: InterruptedException) {
e.printStackTrace()
} catch (e: ExecutionException) {
e.printStackTrace()
}
次に、「フォアグラウンド」変数を使用して、必要に応じてアクションを実行します
if (foregroud) { //app in foreground
intent = Intent(this, ChatAdminActivity::class.Java)
intent.putExtra("intent_backchat", 1)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
pendingIntent = PendingIntent.getActivity(this, Integer.valueOf(random) /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
startActivity(intent) // to directly open activity if app is foreground
} else { //app in background
intent = Intent(this, ChatAdminActivity::class.Java)
intent.putExtra("intent_backchat", 1)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
pendingIntent = PendingIntent.getActivity(this, Integer.valueOf(random) /* Request code */, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
.....
その助けを願っています...
そして、私の完全なFCMServiceを見ることができます code
PendingIntentでsend()を呼び出すことでこれを達成できました。
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
try {
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
BroadcastReceiverの作成は、シナリオを処理する最良の方法です。ただし、ユーザーが使用しているアクティビティを知る必要があります。
すべてのアクティビティでBroadcastReceiverを作成すると、奇妙に見えます。したがって、アクティビティを拡張するBaseActivity
を1つ作成します。 BaseActivity
にはBroadcastReceiver
コードが含まれ、他のすべてのアクティビティはこのBaseActivity
を拡張します。
_open class BaseActivity : AppCompatActivity() {
private lateinit var broadcastReceiver: BroadcastReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
if (p1 != null) {
handleBroadcastActions(p1)
}
}
}
}
private fun handleBroadcastActions(intent: Intent) {
when (intent.action) {
Constants.ACTIVITY_STUFF -> {
onHandleActivity()
}
}
}
protected open fun onHandleActivity() {
startActivity(intentFor<YourActivity>())
}
override fun onResume() {
super.onResume()
registerReceiver(broadcastReceiver, IntentFilter(Constants.ACTIVITY_STUFF))
}
override fun onPause() {
super.onPause()
unregisterReceiver(broadcastReceiver)
}}
_
Kotlinコードを追加しました。あなたが理解することを願って :)
最後に、これをBroadcastReceiver
のonMessageReceived()
からFirebaseMessagingService
と呼ぶことができます。
_override fun onMessageReceived(message: RemoteMessage) {
sendBroadcast(Intent(Constants.ACTIVITY_STUFF))
}
_
デバイスの現在のフォアグラウンドアプリに関する情報を取得する必要があります。これに基づいて、アクティビティを開始するか、通知を送信するかを決定できます。
これを行うには、次のようなものを提案します。
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
// Check if message contains a notification payload.
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
handleNotification(remoteMessage);
}
}
private void handleNotification(RemoteMessage remoteMessage){
Intent intent = new Intent(this, MyActivity.class);
Map<String, String> hmap ;
hmap = remoteMessage.getData();
hmap.get("data_info");
intent.putExtra("data_info", hmap.get("data_info"));
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Context context = getApplicationContext();
//CHECK IF THIS APP IS IN FOREGROUND
ActivityManager am = (ActivityManager)
AppService.this.getSystemService(ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo .topActivity.getPackageName();
if(foregroundTaskPackageName.equals(context.getPackageName()){
//THIS STARTS MAINACTIVITY DIRECTLY IF THE FOREGROUND APP IS THIS APP
startActivity(intent);
}else{
//IF THE FOREGROUND APP ISN'T THIS APP THEN SEND A PENDING INTENT TO OPEN MAIACTIVITY WHEN USER TAP ON NOTIFICATION
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
//CREATE A NOTIFICATION IN THE SYSTEM TRAY
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setContentTitle("TITLE")
.setContentText("SUBMESSAGE")
.setPriority(Notification.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, mBuilder.build());
}
}
通知に表示される通知ID、タイトル、サブメッセージを設定する必要があります。
アプリのマニフェストに追加するには、<uses-permission Android:name="Android.permission.GET_TASKS" />
権限も必要です。
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated.
// IntentFilter filter = new IntentFilter("OPEN_NEW_ACTIVITY");
// registerReceiver(new BroadcastNotification(),filter);
// showNotification(remoteMessage.getNotification().getBody());
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
Log.e("Myname","shdjhfghgh");
}
@Override
public void onCreate() {
super.onCreate();
Intent in= new Intent(this,MainActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(in);
}
}
放送に関するGoogleページ によると:
アプリの外部のコンポーネントにブロードキャストを送信する必要がない場合は、サポートライブラリにあるLocalBroadcastManagerを使用してローカルブロードキャストを送受信します。 LocalBroadcastManagerの方がはるかに効率的で(プロセス間通信は不要)、ブロードキャストを送受信できる他のアプリに関連するセキュリティの問題について考えることを回避できます。ローカルブロードキャストは、システム全体のブロードキャストのオーバーヘッドなしに、アプリの汎用pub/subイベントバスとして使用できます。
したがって、BroadcastReceiverではなくLocalBroadcastManagerを使用することをお勧めします。
FirebaseMessagingServiceクラスでは、FCM(Firebase Cloud Messaging)から通知を受け取り、以下を使用します。
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
mainActivityにメッセージを送信するには:
public class AppFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
try {
String messageFrom = remoteMessage.getFrom();
String messageBody = (remoteMessage.getNotification() != null ? remoteMessage.getNotification().getBody() : null);
Map<String, String> messageData = remoteMessage.getData();
NotificationInfo notificationInfo = new NotificationInfo(messageData.get(message));
notifyMainActivity(notificationInfo);
showNotification(notificationInfo);
}
private void notifyMainActivity(NotificationInfo notificationInfo) {
Intent intent = new Intent();
intent.setAction(Constants.BROADCAST_MESSAGE_NOTIFICATION_RECEIVED);
intent.putExtra(Constants.PARAM_NOTIFICATION_INFO, notificationInfo);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
private void showNotification(NotificationInfo notificationInfo) {
Intent intentNotificationClicked = new Intent(this, MainActivity.class);
intentNotificationClicked.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intentNotificationClicked.putExtra(Constants.PARAM_NOTIFICATION_INFO, notificationInfo);
PendingIntent resultIntentNotificationClicked = PendingIntent.getActivity(this, 0, intentNotificationClicked, PendingIntent.FLAG_ONE_SHOT);
String title = "MY APPLICATION";
String message = notificationInfo.message;
Uri notificationSoundURI = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification_icon)
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setSound(notificationSoundURI)
.setContentIntent(resultIntentNotificationClicked);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
int notificationID = Integer.parseInt(new SimpleDateFormat("HHmmssSSS").format(new Date()));
notificationManager.notify(notificationID, mNotificationBuilder.build());
}
}
そしてMainActivityで、メッセージを受信するBroadcastReceiverを作成します。
public class MainActivity extends AppCompatActivity {
private NotificationBroadcastReceiver mNotificationBroadcastReceiver = null;
private IntentFilter mIntentFilter = null;
@Override
public void onCreate(Bundle savedInstanceState) {
this.mNotificationBroadcastReceiver = new NotificationBroadcastReceiver(this);
this.mIntentFilter = new IntentFilter(Constants.BROADCAST_MESSAGE_NOTIFICATION_RECEIVED);
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(this.mNotificationBroadcastReceiver, this.mIntentFilter);
}
@Override
protected void onPause() {
if (this.mNotificationBroadcastReceiver != null) {
unregisterReceiver(mNotificationBroadcastReceiver);
this.mNotificationBroadcastReceiver = null;
}
super.onPause();
}
private class NotificationBroadcastReceiver extends BroadcastReceiver {
WeakReference<MainActivity> mMainActivity;
public NotificationBroadcastReceiver(MainActivity mainActivity) {
this.mMainActivity = new WeakReference<>(mainActivity);
}
@Override
public void onReceive(Context context, Intent intent) {
MainActivity mainActivity = mMainActivity.get();
if (mainActivity != null) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(Constants.PARAM_NOTIFICATION_INFO)) {
NotificationInfo notificationInfo = (NotificationInfo) extras.getSerializable(Constants.PARAM_NOTIFICATION_INFO);
mainActivity.notificationReceived(notificationInfo);
}
}
}
}
public void notificationReceived(@NonNull final NotificationInfo notificationInfo)
{
//handle the notification in MainActivity
}
}
コードで参照されるクラスの下:
public class Constants {
public static final String NOTIFICATION_BROADCAST_RECEIVER_MESSAGE_RECEIVED = "com.mycompany.myapp.NOTIFICATION_RECEIVED";
public static final String PARAM_NOTIFICATION_INFO = "NotificationContent";
}
public class NotificationInfo implements Serializable {
public String message;
public NotificationInfo() { }
public NotificationInfo(String message) { this.message = message; }
}
それでおしまい!