Empecemos a generar impacto en conjunto.

GlobalLogic ofrece una combinación única de experiencia y conocimientos en la intersección entre datos, diseño e ingeniería.

Contáctanos
AgileCross-Industry
This is a quick tip to update our FCM stuff in our app targeting API 26 (Oreo).

Last week, I had to update the current app (changing the targetSdkVersion to 26 ) to support Android Oreo (8.0) . Everything works great (in previous versions) but in Oreo that was not the happy case. The notifications were not working as expected: the app was crashing when a push notification was received by device. This was the exception in logcat:

Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.google.firebase.iid.FirebaseInstanceIdInternalReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.firebase.INSTANCE_ID_EVENT pkg=PACKAGE cmp=COMPONENT }: app is in background uid UidRecord{c5e5e69 u0a325 RCVR bg:+1m25s411ms idle procs:1 seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3397)
at android.app.ActivityThread.-wrap18(Unknown Source)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1780)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)

Well, I’ll be honest and I should confess that I spent one day researching information about this problem. In addition, the project has a gradle file with a lot of dependencies to be used in every module. This distribution helps to keep all dependencies in one place and then make a reference to them from the specific  build.gradle  file.

Research the problem

After doing a quick investigation about the problem, the main cause was: “ Not allowed to start service ”. This message is thrown from Android system when you try to  start a service  when the app is in the background or it is not running. That was the  starting point . All posts were referenced to  Background Execution Limits : the best solution is to create a notification receiver in the middle to execute the service as it matches.  First mistake : that was not I have in my code. Using  Firebase Messaging Cloud , there was not place where a service was starting. SW? Are there other solutions?

Well, the  main problem was the FCM version I had : it was pointing to  8.4.0  which  it does not support Oreo .

Update FCM to at least 11.2.0

After playing around on this, I figured out the FCM version  11.4.0  supports Android Oreo. Actually, Oreo support was introduced in  11.2.0 . You can use whatever you want.

dependencies {
compile 'com.google.firebase:firebase-core:11.4.0'
compile 'com.google.firebase:firebase-messaging:11.4.0'
}

The  official documentation  suggests use  11.8.0  instead. Again,  you can choose whatever you want .

“Nice, so that’s all, right?”  Well, not really. Oreo introduced a new concept for notifications named  Notification ChannelsAll notifications must be assigned to a channel or it will not appear . So, if we have our app targeting  API 26  and we should display a notification for any reason, we  must  assign it to a channel. Otherwise, you will get a warning toast message like this one:

Assign Notification to a channel

The first step is  create a channel id . The best place to create one is in  strings.xml  file.

<string name="default_notification_channel_id" translatable="false">fcm_default_channel</string>

Then, you must add a  meta-data  in manifest file to enable it:

<application>
...
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>
</application>

Perfect, our last step is the assignment on code side. In the same place where you are calling to  notify  method to display the notification, you should add the  channel assignment :

...
// Since android Oreo notification channel is needed.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId = context.getString(R.string.default_notification_channel_id);
NotificationChannel channel = new NotificationChannel(channelId, title, NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(body);
mNotificationManager.createNotificationChannel(channel);
builder.setChannelId(channelId);
}
mNotificationManager.notify(1, notification);
...

And that’s it! Now the app should work on devices with Oreo.

You can check the following repo to make sure you are doing it in a right way:

firebase/quickstart-android
quickstart-android – Firebase Quickstart Samples for Android github.com

Please, feel free to comment, suggest or ask anything you want. Happy coding!

Read the article in Medium