'FirebaseMessagingService singleton? Controlling the instance

I'm having a problem with use the FirebaseMessagingService. The FirebaseMessagingService works fine. I receive the messages and the notifications. But I need send the message to Activity opened, and invoke a method in activity.

I tried create a listener, but when receive a message, is created a new instance and the listener be null. I understand that FirebaseMessagingService is instanciated when have a message to receive. So I thought in singleton and listener together, don't work, the listener keep null.

Someone have a idea how I can send a message to activity opened?



Solution 1:[1]

I don't think any listeners are needed for this. Once you get message in onMessageReceived(), just broadcast it using LocalBroadcastmanager. and receive that broadcast in your activity.

Below is the code snippet to achieve what you want:

MyFirebaseMessagingService.java

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    Intent intent = new Intent(**Action**);
    intent.putExtra("Some Payload", message.getBody());
    mLocalBroadcastManager.sendBroadcast(intent);
}

MainActivity.java

private LocalBroadcastManager mLocalBroadcastManager;
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

    }
};

@Override
protected void onStart() {
    super.onStart();
    registerBroadcastReceiver();
}

@Override
protected void onStop() {
    super.onStop();
    unregisterBroadcastReceiver();
}

private void registerBroadcastReceiver() {
    mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(**Action**);
    mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);
}

private void unregisterBroadcastReceiver() {
    mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);
}

Solution 2:[2]

Be care full though not to exceed limitations of data sizes that can be passed using intents refer here https://code.google.com/p/android/issues/detail?id=5878

I understood your question with out any code. Here is pretty much a turn key solution for you that should work. I use this method a lot to pass data between services and activities.

The first thing you need to to is convert the data you want to pass to something that can be passed through an intent.

Strings are easy to work with so convert to string and put in an intent. On the activity side using onCreate and onNewItent you can receive this data no problem. Then convert it back how ever you wish. See code below for an example.

Working with broadcast receivers has the possibilities of giving you data leaks if the receiver is not unRegistered. It will happen if you app crashes and the unRegister is not told to shutdown.

In your FirebaseMessagingService class

import android.os.AsyncTask;
    import com.google.firebase.messaging.FirebaseMessagingService;
    import com.google.firebase.messaging.RemoteMessage;
    import org.json.JSONException;
    import org.json.JSONObject;
    import java.util.Map;

    /**
     * Created by acopp
     * Date: 12/31/2016.
     * Time: 1:41 PM

     * You have permission to use this file for any reason that is not for evil doing
     */

    public class FBMService extends FirebaseMessagingService {
        static String TAG = "FBMService";
        static String FBMServiceAction = "FBMService.Action";

        @Override
        public void onMessageReceived(RemoteMessage remoteMessage) {
            MainActivity.passIntent(this,FBMServiceAction,getString(remoteMessage));
        }
        String getString(RemoteMessage message){
            Map<String, String> messageData = message.getData();
            JSONObject j = new JSONObject();
            for (String key : messageData.keySet()) {
                String value = messageData.get(key);
                try {
                    j.put(key, value);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
            return j.toString();
        }

    }

Activity Class

//In your activity class

    import android.app.Activity;
    import android.content.Context;
    import android.content.Intent;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.util.Log;
    import org.json.JSONException;
    import org.json.JSONObject;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;

    /**
     * Created by acopp
     * Date: 12/31/2016.
     * Time: 1:41 PM
     * You have permission to use this file for any reason that is not for evil doing
     */

    public class MainActivity extends Activity {
        private String TAG = "MainActivity";

        //Call this from FBMService to start your activity or if your activity is start to receive a new intent
        static void passIntent(Context context, String action, String messageDataString) {
            Intent intent = new Intent(context, MainActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.putExtra("action", action);
            intent.putExtra("message", messageDataString);
            context.startActivity(intent);
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.d(TAG, "onCreate");
            intentHandler(getIntent());
        }
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            Log.d(TAG, "onNewIntent");
            intentHandler(intent);
        }
        //Use an intent handler to manage onNewIntent and onCreate the same way
        void intentHandler(Intent intent) {
            if (intent.hasExtra("action")) {
                String action = intent.getStringExtra("action");
                if(action.equals(FBMService.FBMServiceAction)){
                    if (intent.hasExtra("message")) {
                        String messageDataString = intent.getStringExtra("message");
                        new iterEat().execute(messageDataString);
                    }
                }
            }
        }
        //Convert your string to a HashMap in the background off the main thread
        class iterEat extends AsyncTask<String,Void,Map<String, String> > {
            @Override
            protected Map<String, String> doInBackground(String... rm) {
                String messageDataString = rm[0];
                try{
                    return fromString(messageDataString);
                }catch (NullPointerException e){
                    return null;
                }
            }
            @Override
            protected void onPostExecute(Map<String, String>  s) {
                //Your data is pooped out here
                Map<String, String> messageData = s;//PLOP
            }
        }

        Map<String, String> fromString(String jsonString) throws NullPointerException{
            try {
                Map<String, String> messageData = new HashMap<>();
                JSONObject j = new JSONObject(jsonString);
                Iterator<String> i = j.keys();
                while(i.hasNext()){
                    String key = i.next();
                    String value = j.getString(key);
                    messageData.put(key,value);
                }
                return messageData;

            } catch (JSONException e) {
                throw new NullPointerException("Didn't work");
            }
        }
    }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Xevion
Solution 2 Thunderstick