Android8.0后台执行限制
为提高设备性能,系统会限制未在前台运行的应用的某些行为。具体而言:
在后台运行的应用对后台服务的访问受到限制
应用无法使用其清单注册大部分隐式广播
默认情况下,这些限制仅适用于针对O的应用。不过用户可以从Settinfs屏幕为任意应用启用这些限制,即使应用并不是以O为目标平台。
Android8.0还对特定函数做出了如下变更:
如果针对Android8.0的应用尝试子不允许创建其后台服务的情况下使用startService()函数,则该函数将引发一个IllegalStateException.
Context.startForegroundService()函数将启动一个前台服务。即使应用在后台运行,系统也允许其调用Context.startForegroundService().不过,应用必须在创建服务后的5秒内调用改服务的startForegroun()函数,否则将报ANR(Application Not Responding)错误。
Android8.0具体行为变更:https://developer.android.com/about/versions/oreo/android-8.0-changes?hl=zh-cn
创建和管理通知渠道
从Android8.0开始,需要为发送的每种不同类型的通知创建一个渠道,如果在Android8.0及以上在未指定通知频道的情况下发送通知,通知不会显示,会记录错误。
创建通知渠道步骤:
通过一个唯一的channel ID ,对用户可见的channel name,通知重要程度importance level构建一个通知渠道。
可选的使用setDescription()指定用户在系统设置页面看到的关于通知的相关描述。
通过createNotificationChannel()注册通知渠道。
//Channel ID 必须保证唯一
private static final String CHANNEL_ID = "com.appname.notification.channel";
/**
*创建通知渠道
*/
private void createNotificationChannel() {
// 在API>=26的时候创建通知渠道
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//设定的通知渠道名称
String channelName = getString(R.string.channel_name);
//设置通知的重要程度
int importance = NotificationManager.IMPORTANCE_LOW;
//构建通知渠道
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);
channel.setDescription(description);
//向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}1234567891011121314151617181920
importance level主要有七种层次:
IMPORTANCE_DEFAULT: 默认notification importance,可以在任何地方显示,有声音。
IMPORTANCE_HIGH:可以在任何地方显示,有声音.
IMPORTANCE_LOW:可以在任何地方显示,没有声音.
IMPORTANCE_MAX:重要程度最高,可以在任何地方显示,有声音,可以在用户当前屏幕上显示通知,可以使用full screen intents.比如来电。
IMPORTANCE_MIN:无声音,不会出现在状态栏中。
IMPORTANCE_NONE:在任何地方都不会显示,被阻塞。
IMPORTANCE_UNSPECIFIED:表示用户没有表示重要性的值。这个值是为了持久的首选项,并且永远不应该与实际的通知相关联。
如何选择重要性可以参考:
https://material.io/design/platform-guidance/android-notifications.html#behavior
开启前台服务
public class MonitorService extends Service {
/*
* @param intent
* @param flags
* @param startId
* @return
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//处理任务
return START_STICKY;
}
@SuppressLint("CommitPrefEdits")
@Override
public void onCreate() {
super.onCreate();
Log.d("foreground", "onCreate");
//如果API在26以上即版本为O则调用startForefround()方法启动服务
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
setForegroundService();
}
}
/**
*通过通知启动服务
*/
@TargetApi(Build.VERSION_CODES.N)
public void setForegroundService()
{
//设定的通知渠道名称
String channelName = getString(R.string.channel_name);
//设置通知的重要程度
int importance = NotificationManager.IMPORTANCE_LOW;
//构建通知渠道
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, channelName, importance);
channel.setDescription(description);
//在创建的通知渠道上发送通知
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setSmallIcon(R.drawable.ic_logo) //设置通知图标
.setContentTitle(notificationTitle)//设置通知标题
.setContentText(notificationContent)//设置通知内容
.setAutoCancel(true) //用户触摸时,自动关闭
.setOngoing(true);//设置处于运行状态
//向系统注册通知渠道,注册后不能改变重要性以及其他通知行为
NotificationManager notificationManager = getSystemService( Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
//将服务置于启动状态 NOTIFICATION_ID指的是创建的通知的ID
startForeground(NOTIFICATION_ID,builder.build());
}
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
在Application或需要开启服务的地方调用
// Android 8.0使用startForegroundService在前台启动新服务
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(mMonitorService);
}
else{
context.startService(mMonitorService);
}12345678
---------------------
本文来自 Root_Q 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Haienzi/article/details/81268022?utm_source=copy