Firebase Cloud Messaging: Accessing UI elements in onMessageReceived()

泄露秘密 提交于 2019-12-24 19:06:05

问题


In my android app, I use firebase cloud messaging to send some data to app.

When the app receives a message through onMessageReceived(), I check whether a MainActivity is currently visible (MainActivity has a static reference to the currently visible MainActivity), and if the activity is visible, I make some modifications to the activity.

Since onMessageReceived() is not called in the main thread, I use a Handler to execute the code in the main thread.

@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
    Handler handler = new Handler(Looper.getMainLooper());
    handler.post(new Runnable() {
        //Access UI
    });
}

Is there anything wrong with this approach? If not, are there any other ways to update the currently visible UI when a cloud message is received?


回答1:


You should avoid writing direct code in the onMessageReceived() for UI changes in a specific activity. You can channel it through Local broadcast receivers.

When you tend to write code directly in the onMessageReceived() your FirebaseMessagingService class will get cluttered. For instance if you have 4 different kind of notification data and each data calls for different activity. Then your code will look something like this :

@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
    if(remoteMessage.getData() != null 
        && remoteMessage.getData().containsKey("notification_type")){
        switch(remoteMessage.getData().containsKey("notification_type")){
            case "type1":
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    //Access UI for some activity
                    .
                    .
                    .
                });
                break;
            case "type2":
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                     //Access UI for some activity
                    .
                    .
                    .
                });
                break;
            case "type3":
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                     //Access UI for some activity
                    .
                    .
                    .

                });
                break;
            case "type4":
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                     //Access UI for some activity
                    .
                    .
                    .

                });
                break;

        }
    }

}

Alternatively, if you use local broadcast then your code will be much more modular and organised. Your code will look something like this:

@Override
public void onMessageReceived(final RemoteMessage remoteMessage) {
    if(remoteMessage.getData() != null 
        && remoteMessage.getData().containsKey("notification_type")){
        Intent intent = new Intent();
        intent.putExtra("body",messageBody); // Put info that you want to send to the activity
        switch(remoteMessage.getData().containsKey("notification_type")){
            case "type1":
                intent.setAction("ACTION_1") // For activity1
                break;
            case "type2":
                intent.setAction("ACTION_2") //For activity2
                break;
            case "type3":
                intent.setAction("ACTION_3") //For activity3
                break;
            case "type4":
                intent.setAction("ACTION_4") //For activity4
                break;
        }
        sendBroadcast(intent);
    }

}

And your activity (eg. activity1) will look something like this: private BroadcastReceiver mReceiver;

@Override
protected void onResume() {
    // TODO Auto-generated method stub
    super.onResume();

    IntentFilter intentFilter = new IntentFilter(
            "ACTION_1"); // Put appropriate action string 

    mReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            //Get message from intent
            String msg_for_me = intent.getStringExtra("some_msg");
            //Do your UI Changes stuff here.

        }
    };
    //registering our receiver
    this.registerReceiver(mReceiver, intentFilter);
}

@Override
protected void onPause() {
    super.onPause();
    this.unregisterReceiver(this.mReceiver);//unregister receiver
}

According to me this will help you code your UI changes inside the activity itself and leads you towards a better code management.

Hope it is useful!



来源:https://stackoverflow.com/questions/48035485/firebase-cloud-messaging-accessing-ui-elements-in-onmessagereceived

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!