¿Cómo comunicarse entre el servicio de mensajería de Firebase y la actividad? Androide

Sé que la pregunta sobre cómo comunicarse entre un servicio y una actividad ha sido contestada muchas veces pero también quiero que mi propia manera de hacer esto sea revisada y saber si es una manera aceptable y correcta de hacer esto y cuáles son los Inconvenientes de cómo lo manejé. Primero declararé la declaración del problema con el mayor detalle posible.

Tengo que construir una aplicación donde estoy utilizando Firebase Messaging Service para comunicarse entre dos dispositivos. Digamos que es un sistema similar a Uber. Una aplicación es para el proveedor de servicios (conductor) y otra para el cliente (pasajero). Cuando el pasajero solicita viajar con su ubicación, los conductores en un cierto radio recibirán una notificación push con una carga útil usando Firebase. El servicio Firebase se ejecuta en segundo plano. Cuando el servicio recibe una notificación push, se onMessageReceived método onMessageReceived . Se genera un evento. No utilizo Firebase aquí para generar notificaciones, pero en realidad transfiero datos entre dispositivos cuando necesito usar el campo de data de la notificación push de Firebase. Ahora la aplicación de controladores recibirá las coordenadas de donde el usuario quiere que el coche en la carga útil de Firebase push notificación. Simplemente puedo iniciar una actividad con estos datos en los extras y mostrar al conductor que se recibe una solicitud.

Ahora en el lado del cliente, después de que el cliente envía la solicitud que se llevan a la siguiente actividad donde se les está mostrando una especie de pantalla de carga diciéndoles a esperar a uno de los conductores a aceptar su solicitud. Cuando uno de los controladores acepta la solicitud de este usuario, este usuario recibirá ahora una notificación push de Firebase con la información del conductor designado en la carga útil de la notificación push. Una vez más el propósito no es generar notificaciones sino transferir datos entre dispositivos.

Ahora que entiendes el caso de uso, pasaré al problema.

El problema surge cuando el usuario envía la solicitud y pasa a la siguiente pantalla de espera en la que se muestra una pantalla de carga diciéndoles que esperar mientras que la solicitud está a la espera de ser aceptado por uno de los conductores. Cuando un conductor acepta la solicitud, como ya he dicho, el usuario recibirá una notificación push de Firebase con la información del conductor en la carga útil de la notificación push. ¿Cómo puedo comunicar entre el servicio y la actividad, para decirle a la actividad que deje de mostrar la pantalla de carga y llenar los TextView con los datos recibidos en la carga útil de la notificación push.

Aquí es cómo he manejado esto. Supongamos que tengo una actividad con el nombre AwaitingDriver , que tiene TextView para ser llenado por los datos del conductor. Pero actualmente la actividad muestra una pantalla de carga porque la solicitud aún no ha sido aceptada. Ahora el usuario recibe una notificación push con la información del controlador en el servicio ejecutándose en segundo plano, no conectada a la actividad de ninguna manera. Aquí está mi método onMessageReceived

  @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 } } 

Aquí, AwaitingDriver.requestAccepted() es un método estático de la actividad AwaitingDriver . Dentro de la actividad de AwaitingDriver en sí, que está mostrando un diálogo de progreso para decirle al cliente que espere, aquí está lo que está haciendo el método AwaitingDriver.requestAccepted() .

 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(); } } 

Aquí staticActivity es un objeto estático de la clase de actividad AwaitingDriver declarada dentro de esta clase. Estoy estableciendo su valor en los métodos onResume y onPause . Lo que significa que si la actividad está en el frente, mostrando en la pantalla, sólo entonces el valor de staticActivity no será null . Estos son los métodos onResume y onPause .

 @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; } 

Aquí, TaskFindSetValues es un AsyncTask definido dentro de la clase de actividad AwaitingDriver . Aquí está el código de 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); } } 

Por favor revisa este código y cuéntame los inconvenientes de hacer esto en lugar de las otras soluciones y si también pudieras explicar la forma sugerida con el mismo ejemplo estaría muy agradecido.

¿Por qué utiliza AsyncTask? No tiene sentido. De todos modos, si quieres comunicarte con la Actividad puedes hacerlo con 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); } } 

Y en su actividad

  @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")); } }; 

En el método onMessageReceived podría enviar una aplicación en emisión, transfiriendo los detalles del controlador. El método aceptado por la petición sería entonces reemplazado por el método receiver onReceive de broadcast receiver. De esta manera no hay necesidad de escribir en las preferencias compartidas o usar un aSyncTask que básicamente no hace nada como el método doinbackground acaba de devolver null. Sólo está utilizando los métodos onPreExecute y onPostExecute, que se ejecutan en el subproceso principal.

¿Por qué no simplemente crear una intención dentro del método onMessageReceived, reiniciar la actividad y pasar los datos del controlador en el extra?

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.