Soluciones tecnológicas
Soluciones tecnológicasLa inteligencia artificial generativa pasa a ser parte como un pilar fundamental de la ...
Open Banking, powered by Generative Artificial Intelligence (GenAI), is redefining the ...
Fortaleciendo las capacidades de datos y consultoría de GlobalLogic y ampliando su pres...
La nueva infraestructura es la columna vertebral digital de la planta de Hagerstown, q...
GlobalLogic ofrece una combinación única de experiencia y conocimientos en la intersección entre datos, diseño e ingeniería.
ContáctanosLast 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.
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 .
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 Channels . All 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:
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!