I get the following error when running this Service on my smartphone (API 29) but not in another one (API26). For the error I assume that the problem is with the Channel ID when running my service as a ForegroundService, but I coulnd't find out how to solve it... I didn't know which Channel Id would be the appropiate. Any help?
Error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.android.testworkmanager, PID: 22582
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=TestChannelID pri=2 contentView=null vibrate=null sound=null tick defaults=0x0 flags=0x40 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1969)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7520)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
E/MQSEventManagerDelegate: failed to get MQSService.
This is my manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.testworkmanager">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".MyService"
android:enabled="true"
android:exported="false"
android:icon="@drawable/ic_launcher_background"
android:label="MyServiceLabel" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
and this is my service:
package com.example.android.testworkmanager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.core.app.NotificationCompat;
public class MyService extends Service {
private static final int ONGOING_NOTIFICATION_ID = 2;
private String channelID = "TestChannelID";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
Log.v("APP_TEST","Service_startCommand");
Intent notificationIntent = new Intent(this, MyService.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification =
new NotificationCompat.Builder(this, this.channelID)
.setContentTitle("TestNotification")
.setContentText("This is the text to display on notification")
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pendingIntent)
.setTicker("TickerText")
.setPriority(NotificationCompat.PRIORITY_MAX)
.build();
startForeground(ONGOING_NOTIFICATION_ID, notification);
return Service.START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.v("APP_TEST","Service_Create");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.v("APP_TEST","Service_destroy");
}
@Override
public IBinder onBind(Intent intent) {
//TODO for communication return IBinder implementation
return null;
}
}
And the service would be started and stopped with the following commands:
//For starting
Intent intent = new Intent(this, MyService.class);
startService(intent);
... (somewhere else)
//For stopping
Intent intent = new Intent(this, MyService.class);
stopService(intent);
For starting a foreground service in Android O and above, you have to create a channel, before you create a notification. And you also have to put the same channel id in your Notification.Builder constructor. Here is an example on how to create a channel:
/**
* Method that create a channel for notification showed to user, for foreground service
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void createChannel() {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME, //name of the channel
NotificationManager.IMPORTANCE_HIGH); //importance level
// Configure the notification channel.
mChannel.setDescription("Description of your channel");
mChannel.enableLights(true);
// Sets the notification light color for notifications posted to this channel, if the device supports this feature.
mChannel.setShowBadge(true);
assert nm != null;
nm.createNotificationChannel(mChannel);
}
It looks like You are missing a notification channel that is required from Android O and above.
Documentation: https://developer.android.com/training/notify-user/channels
Try this sample:
private String CHANNEL_ID;
private void createNotificationChannel() {
CharSequence channelName = CHANNEL_ID;
String channelDesc = "channelDesc";
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);
channel.setDescription(channelDesc);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
assert notificationManager != null;
NotificationChannel currChannel = notificationManager.getNotificationChannel(CHANNEL_ID);
if (currChannel == null)
notificationManager.createNotificationChannel(channel);
}
}
public void createNotification(String message) {
CHANNEL_ID = UiUtil.getStringSafe(R.string.app_name);
if (message != null ) {
createNotificationChannel();
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(UiUtil.getStringSafe(R.string.app_name))
.setContentText(message)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setAutoCancel(true);
Uri uri =RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mBuilder.setSound(uri);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
int notificationId = (int) (System.currentTimeMillis()/4);
notificationManager.notify(notificationId, mBuilder.build());
}
}
I hope this answered is helpful for you. Thank You
User contributions licensed under CC BY-SA 3.0