I thought I had completed conversion to FCM from GCM for all of my apps because they all passed initial testing. However subsequent beta testing shows they all have the same problem. I'll use the messaging app as an example . . .
The messaging app uses data messages. When messages are received in the listner service they are posted to the conversation thread if the app is running. If the app is not running a notification is posted on the receiving phone and the incoming message is added to the conversation data store.
THE PROBLEM IS after the app is closed myFCMListenerService stops working after an hour or two. The old GcmBroadcastReciver we used when on GCM always kept working forever - days, months.
After it quits working the following happens . . .
- stepping through the code the listener never gets the message.
- NullPointerException occurs by a Context.getPackageName() on a null object
The only getPackageName() methods in the project are in LicenseValidator.java and iabHelper.java. This make no sense whatsoever.
This is the exact error that occurs usually about an hour after the app has been closed and usually around the 6th or so message the fcmlistener receives. It happens exactly when a message is received but step through debugging shows the listener service never got the message that caused the exception.
12-09 18:18:12.323 13569-13591/com.deanblakely.SafeTalk.debug E/AndroidRuntime: FATAL EXCEPTION: Firebase-MyFcmListenerService Process: com.deanblakely.SafeTalk.debug, PID: 13569 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference at android.preference.PreferenceManager.getDefaultSharedPreferencesName(PreferenceManager.java:537) at android.preference.PreferenceManager.getDefaultSharedPreferences(PreferenceManager.java:526) at com.deanblakely.SafeTalk.SPHelper.getSharedPreferences(SPHelper.java:14) at com.deanblakely.SafeTalk.SPHelper.getTempString(SPHelper.java:32) at com.deanblakely.SafeTalk.GlobalStuff.storeMessage(GlobalStuff.java:203) at com.deanblakely.SafeTalk.MyFcmListenerService.handleNow(MyFcmListenerService.java:98) at com.deanblakely.SafeTalk.MyFcmListenerService.onMessageReceived(MyFcmListenerService.java:38) at com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source:402) at com.google.firebase.iid.zzg.run(Unknown Source:26) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:7) at java.lang.Thread.run(Thread.java:764)
The only permissions the app uses are:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="com.android.vending.BILLING" />
The following is the code from our listener service that works perfectly while the app is active and also for an hour or so after the app is closed.
public class MyFcmListenerService extends FirebaseMessagingService {
private static final String TAG = "MyFcmListenerService";
private Map<String, String> data;
@Override
public void onMessageReceived(RemoteMessage message)
{
String from = message.getFrom();
data = message.getData();
String debug = "what is in data?";
if (message.getNotification() != null) //is this a notification?
{
Log.d(TAG, "Message Notification Body: " + message.getNotification().getBody());
}
else
{
if (message.getData().size() > 0)
{
Log.d(TAG, "Message data payload: " + message.getData());
handleNow(message); //out methods that processes the message
}
else
{
Log.d(TAG," Got empty data message");
}
}
}
of course we have the following in our manifest file . . .
<service
android:name=".MyFcmListenerService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>