如何在Firebase Messaging Service和Activity之间进行通信?安卓 [英] How to communicate between Firebase Messaging Service and Activity? Android

查看:130
本文介绍了如何在Firebase Messaging Service和Activity之间进行通信?安卓的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有关如何在服务和活动之间进行通信的问题已经回答了很多次,但我也希望我自己的做事方式能够得到审查,并知道它是否可以接受并且正确地做到了这一点,并且我如何处理它的缺点是什么首先,我将尽可能详细地陈述问题陈述.

I know the question about how to communicate between a service and an activity has been answered many times but I also want my own way of doing this to be reviewed and to know if its an acceptable and the right way to do this and what are the drawbacks of how I handled it. First I will state the problem statement with as much detail as I can.

我必须构建一个使用Firebase Messaging Service在两个设备之间进行通信的应用程序.假设它是一个类似Uber的系统.一个应用程序用于服务提供商(驱动程序),另一个应用程序用于客户(乘客).当乘客要求随其位置旅行时,一定半径范围内的驾驶员将使用Firebase收到带有有效载荷的推送通知. Firebase服务在后台运行.当服务收到推送通知时,将调用onMessageReceived方法.产生一个事件.我不是在这里使用Firebase生成通知,而是在需要使用Firebase推送通知的data字段时实际上在设备之间传输数据.现在,驾驶员应用程序将在Firebase推送通知的有效负载中接收用户想要汽车的坐标.我可以简单地使用附加数据中的数据来开始活动,并向驱动程序显示已收到请求.

I have to build an app where I am using Firebase Messaging Service to communicate between two devices. Let's say its an Uber like system. One app is for the service provider(driver) and one for the customer(passenger). When the passenger requests to travel with their location, the drivers in a certain radius will get a push notification with a payload using Firebase. The Firebase service is running in the background. When the service receives a push notification, onMessageReceived method is invoked. An event is generated. I am not using Firebase here to generate notifications but actually transfer data between devices when I need to using the data field of Firebase push notification. Now the drivers app will receive the coordinates of where the user wants the car in the payload of Firebase push notification. I can simply start an activity with this data in the extras and show the driver that a request is received.

现在,在客户方,在客户提交请求之后,他们将被带到下一个活动,在该活动中,他们会看到一种加载屏幕,告诉他们等待一个驾驶员接受他们的请求.当驱动程序之一接受该用户的请求时,该用户现在将收到Firebase推送通知,在推送通知的有效负载中包含指定的驱动程序信息.同样,其目的不是生成任何通知,而是在设备之间传输数据.

Now on the customer side, after the customer submits the request they are taken to the next activity where they are being shown a kind of loading screen telling them to wait for one of the drivers to accept their request. When one of the drivers accepts this user's request, this user will now receive a Firebase push notification with the designated driver's information in the payload of the push notification. Again the purpose is not to generate any notifications but to transfer data between devices.

现在您已经了解了用例,我将继续解决该问题.

Now that you understand the use case I will move on to the problem.

当用户提交请求并转到下一个等待屏幕时,就会出现问题,在该屏幕上将显示一个加载屏幕,告诉他们在其中一个驾驶员正在等待请求的同时等待.当驱动程序接受请求时,正如我所说,用户将收到Firebase推送通知,在推送通知的有效负载中包含驱动程序的信息.如何在服务和活动之间进行通信,以告诉活动停止显示加载屏幕,并用推送通知的有效负载中接收到的数据填充TextView.

The problem arises when the user submits the request and moves on to the next waiting screen where he is shown a loading screen telling them to wait while there request is waiting to be accepted by one of the drivers. When a driver accepts the request, as I said the user will receive a Firebase push notification with the driver's information in the payload of the push notification. How do I communicate between the service and the Activity, to tell the activity to stop showing the loading screen and fill the TextView's with the data received in the payload of the push notification.

这是我处理此问题的方式.假设我有一个名为AwaitingDriver的活动,该活动具有要由驱动程序数据填充的TextView.但是当前活动正在显示加载屏幕,因为请求尚未被接受.现在,用户会在后台运行的服务中收到推送通知,其中包含驾驶员的信息,该通知未以任何方式连接到活动.这是我的onMessageReceived方法

Here is how I have handled this. Suppose that I have an activity with the name AwaitingDriver, which has TextView's to be filled by the driver's data. But currently the activity is showing a loading screen because the request has not been accepted yet. Now the user receives a push notification with the driver's information in the service running in the background, not connected to the activity in any way. Here is my onMessageReceived method

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage){
        SharedPreferences rideInfoPref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE);
        SharedPreferences.Editor rideInfoPrefEditor = rideInfoPref.edit();
        String msgType = remoteMessage.getData().get("MessageType");
        if (msgType.equals("RequestAccepted")){                
            rideInfoPrefEditor.putBoolean(getString(R.string.is_request_accepted), true);
            rideInfoPrefEditor.putString(getString(R.string.driver_phone), remoteMessage.getData().get("DriverPhone"));
            rideInfoPrefEditor.putString(getString(R.string.driver_lat), remoteMessage.getData().get("DriverLatitude"));
            rideInfoPrefEditor.putString(getString(R.string.driver_lng), remoteMessage.getData().get("DriverLongitude"));

            rideInfoPrefEditor.commit();
            AwaitingDriver.requestAccepted(); // A static method in AwaitingDriver Activity
        }            
    }

在这里,AwaitingDriver.requestAccepted()AwaitingDriver活动的静态方法.在AwaitingDriver活动本身内部,它显示一个进度对话框以告诉客户等待,这是AwaitingDriver.requestAccepted()方法的作用.

Here, AwaitingDriver.requestAccepted() is a static method of AwaitingDriver activity. Inside the AwaitingDriver activity itself, which is showing a progress dialog to tell the customer to wait, here is what the method AwaitingDriver.requestAccepted() is doing.

public static void requestAccepted(){
    try{
        awaitingDriverRequesting.dismiss(); //ProgressDialog for telling user to wait
    }catch (Exception e){
        e.printStackTrace();
    }        
    if (staticActivity != null){
        staticActivity.new TaskFindSetValues().execute();
    }
}

此处staticActivity是在该类内部声明的AwaitingDriver活动类的静态对象.我正在onResumeonPause方法中设置其值.这意味着如果活动在屏幕上显示的最前面,则staticActivity的值将不是null.这是onResumeonPause方法.

Here staticActivity is a static object of AwaitingDriver activity class declared inside this class. I am setting its value in onResume and onPause methods. Meaning if the activity is in the front, showing on the screen, only then will the value of staticActivity be not null. Here are the onResume and onPause methods.

@Override
public void onResume(){
    super.onResume();
    staticActivity = this;
    Boolean accepted = rideInfoPref.getBoolean(getString(R.string.is_request_accepted), false);
    if (accepted){        
       new TaskFindSetValues().execute();            
    }
}
@Override
protected void onPause(){
    super.onPause();
    staticActivity = null;
}

在这里,TaskFindSetValues是在AwaitingDriver活动类中定义的AsyncTask.这是TaskFindSetValues

Here, TaskFindSetValues is an AsyncTask defined inside AwaitingDriver activity class. Here is the code for TaskFindSetValues

public class TaskFindSetValues extends AsyncTask<String, Void, String>{
    String phone;
    String lat;
    String lng;
    @Override
    protected void onPreExecute(){
        SharedPreferences pref = getSharedPreferences(getString(R.string.rideInfoPref), MODE_PRIVATE);            
        phone = pref.getString(getString(R.string.driver_phone), "");
        lat = pref.getString(getString(R.string.driver_lat), "");
        lng = pref.getString(getString(R.string.driver_lng), "");
    }
    @Override
    protected String doInBackground(String... arg0){
        return null;
    }

    @Override
    protected void onPostExecute(String returnValue){            
        awaitingDriverPhone.setText(phone); //setting values to the TextViews
        awaitingDriverLat.setText(lat);
        awaitingDriverLng.setText(lng);
    }
}

请仔细阅读这段代码,并告诉我这样做的弊端,而不是其他解决方案;如果您还可以用同一示例解释建议的方法,我将不胜感激.

Please review this code and tell me about the drawbacks of doing this instead of the other solutions and if you could also explain the suggested way with the same example I'd be really grateful.

推荐答案

为什么要使用AsyncTask?这没有道理.无论如何,如果您想与活动进行通信,可以使用BroadcastReceiver.

Why are you using AsyncTask? It doesn't make sense. Anyway, if you want to communicate with the Activity you can do it with BroadcastReceiver.

public class MyFirebaseMessagingService extends FirebaseMessagingService{
    private LocalBroadcastManager broadcaster;

    @Override
    public void onCreate() {
        broadcaster = LocalBroadcastManager.getInstance(this);
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Intent intent = new Intent("MyData");
        intent.putExtra("phone", remoteMessage.getData().get("DriverPhone"));
        intent.putExtra("lat", remoteMessage.getData().get("DriverLatitude"));
        intent.putExtra("lng", remoteMessage.getData().get("DriverLongitude"));
        broadcaster.sendBroadcast(intent);
    }
}

并在您的活动中

 @Override
    protected void onStart() {
        super.onStart();
        LocalBroadcastManager.getInstance(this).registerReceiver((mMessageReceiver),
                new IntentFilter("MyData")
        );
    }

    @Override
    protected void onStop() {
        super.onStop();
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
    }

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            awaitingDriverRequesting.dismiss();
            awaitingDriverPhone.setText(intent.getExtras().getString("phone")); //setting values to the TextViews
            awaitingDriverLat.setText(intent.getExtras().getDouble("lat"));
            awaitingDriverLng.setText(intent.getExtras().getDouble("lng"));
        }
    };

编辑

根据@xuiqzy LocalBroadcastManager现在已被弃用! Google表示改用LiveData或Reactive Streams.

According to @xuiqzy LocalBroadcastManager is now deprecated! Google says to use LiveData or Reactive Streams instead.

这篇关于如何在Firebase Messaging Service和Activity之间进行通信?安卓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆