我在智能手机(API 29)上运行此服务,但在另一智能手机(API26)上运行此服务时遇到以下错误。对于该错误,我假设将服务作为ForegroundService运行时,问题出在Channel ID,但我无法找到解决方法……我不知道哪个Channel ID是合适的。有帮助吗?
错误:
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.
这是我的清单:
<?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>
这是我的服务:
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;
}
}
然后将通过以下命令启动和停止服务:
//For starting
Intent intent = new Intent(this, MyService.class);
startService(intent);
... (somewhere else)
//For stopping
Intent intent = new Intent(this, MyService.class);
stopService(intent);
要在Android O及更高版本中启动前台服务,必须先创建频道,然后再创建通知。而且,您还必须在Notification.Builder构造函数中添加相同的频道ID。这是有关如何创建频道的示例:
/**
* 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);
}
看来您缺少Android O及更高版本所需的通知渠道。
文档:https://developer.android.com/training/notify-user/channels
尝试此示例:
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());
}
}
我希望这个回答对您有帮助。谢谢
我在这篇文章中找到了答案:startForeground fail after upgrade to Android 8.1
感谢Rawa遇到同样的问题,并为自己找到解决方案!