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

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

问题描述

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

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 消息服务在两台设备之间进行通信.假设它是一个类似 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 推送通知,推送通知的负载中包含驱动程序的信息.我如何在服务和 Activity 之间进行通信,以告诉 Activity 停止显示加载屏幕并使用推送通知有效负载中收到的数据填充 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?这没有意义.无论如何,如果您想与 Activity 通信,您可以使用 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 消息服务和活动之间进行通信?安卓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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