升级我的手机到8.1开发者预览后,我的后台服务不再正常启动。
在我的长时间运行的服务中,我实现了一个start前台方法来启动正在进行的通知,该通知在创建时被调用。
@TargetApi(Build.VERSION_CODES.O)
private fun startForeground() {
// Safe call, handled by compat lib.
val notificationBuilder = NotificationCompat.Builder(this, DEFAULT_CHANNEL_ID)
val notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.build()
startForeground(101, notification)
}
错误信息:
11-28 11:47:53.349 24704-24704/$PACKAGE_NAMEE/AndroidRuntime: FATAL EXCEPTION: main
Process: $PACKAGE_NAME, PID: 24704
android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=My channel pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x42 color=0x00000000 vis=PRIVATE)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
无效的服务通知通道,显然我的旧通道DEFAULT_CHANNEL_ID不再适合API 27我假设。合适的渠道是什么?我试着看了一下文件
在我的例子中,这是因为我们试图在没有指定NotificationChannel的情况下发布通知:
public static final String NOTIFICATION_CHANNEL_ID_SERVICE = "com.mypackage.service";
public static final String NOTIFICATION_CHANNEL_ID_TASK = "com.mypackage.download_info";
public void initChannel(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_SERVICE, "App Service", NotificationManager.IMPORTANCE_DEFAULT));
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_INFO, "Download Info", NotificationManager.IMPORTANCE_DEFAULT));
}
}
放置上述代码的最佳位置是Application类中的onCreate()方法,因此我们只需要声明一次:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
initChannel();
}
}
在我们设置好这些之后,我们可以使用通知和我们刚刚指定的channelId:
Intent i = new Intent(this, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pi = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID_INFO);
.setContentIntent(pi)
.setWhen(System.currentTimeMillis())
.setContentTitle("VirtualBox.exe")
.setContentText("Download completed")
.setSmallIcon(R.mipmap.ic_launcher);
然后,我们可以使用它来发布通知:
int notifId = 45;
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.notify(notifId, builder.build());
如果你想使用它作为前台服务的通知:
startForeground(notifId, builder.build());
Java解决方案(Android 9.0, API 28)
在你的Service类中,添加这个:
@Override
public void onCreate(){
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startMyOwnForeground();
else
startForeground(1, new Notification());
}
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "com.example.simpleapp";
String channelName = "My Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.drawable.icon_1)
.setContentTitle("App is running in background")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
更新:android 9.0馅饼(api 28)
将此权限添加到您的AndroidManifest.xml文件中:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
这对我很管用。在我的服务类中,我为android 8.1创建了通知通道,如下所示:
public class Service extends Service {
public static final String NOTIFICATION_CHANNEL_ID_SERVICE = "com.package.MyService";
public static final String NOTIFICATION_CHANNEL_ID_INFO = "com.package.download_info";
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_SERVICE, "App Service", NotificationManager.IMPORTANCE_DEFAULT));
nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID_INFO, "Download Info", NotificationManager.IMPORTANCE_DEFAULT));
} else {
Notification notification = new Notification();
startForeground(1, notification);
}
}
}
注意:创建要为Build.VERSION创建通知的通道。SDK_INT >= Build.VERSION_CODES.O