赞
踩
前几天接触的一个闹钟APP项目,闹钟触发从后台启动一个activity,执行之后的响铃操作,但是却失效了,闹钟并没有按时响铃。最后发现是系统拦截了从后台启动的Activity。
一、AndroidQ从后台启动Activity的限制
Android 10 (API 级别 29) 及更高版本对后台应用可启动 Activity进行限制。Android10中, 当App的Activity不在前台时,其启动Activity会被系统拦截,导致无法启动。
二、后台弹出界面、锁屏显示权限(小米等部分国产手机)
小米手机有个特殊的权限,“后台弹出界面(允许应用在后台弹出界面)”,默认是拒绝的,如下图所示.
华为手机没有这个权限,目前vivo/oppo/小米手机有这个“后台弹出界面”权限.
其他原因,有待更新,暂时没有遇见
一、针对Android10的问题
方案1
官方给予的折中方案是使用全屏Intent(full-screen intent), 既创建通知栏通知时, 加入full-screen intent 设置。示例代码如下(基于官方文档修改):
Intent fullScreenIntent = new Intent(this, CallActivity.class); PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.notification_icon) .setContentTitle("Incoming call") .setContentText("(919) 555-1234") //以下为关键的3行 .setPriority(NotificationCompat.PRIORITY_HIGH) .setCategory(NotificationCompat.CATEGORY_CALL) .setFullScreenIntent(fullScreenPendingIntent, true); NotificationManager notifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notifyManager.notify(notifyId, builder.build());
注意:在Target SDk为29及以上时,需要在AndroidManifest上增加USE_FULL_SCREEN_INTENT申明
//AndroidManifest中
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
方案2
向用户申请 SYSTEM_ALERT_WINDOW权限,系统就不会拦截该程序后台启动的Activity。
示例代码如下:
//AndroidManifest中
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
//检查是否已经授予权限
if (!Settings.canDrawOverlays(this)) {
//若未授权则请求权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 0);
}
其中,Settings.canDrawOverlays(this)方法是在API level 23也就是Android M中新加入的用于检查当前是否拥有出现在“出现在其他应用上”权限的方法。在6.0以前的系统版本,悬浮窗权限是默认开启的,直接使用即可。
应用检查后台启动权限的方法如下:
public static boolean canBackgroundStart(Context context) {
AppOpsManager ops = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
try {
int op = 10021; // >= 23
// ops.checkOpNoThrow(op, uid, packageName)
Method method = ops.getClass().getMethod("checkOpNoThrow", new Class[]
{int.class, int.class, String.class}
);
Integer result = (Integer) method.invoke(ops, op, Process.myUid(), context.getPackageName());
return result == AppOpsManager.MODE_ALLOWED;
} catch (Exception e) {
Log.e(TAG, "not support", e);
}
return false;
}
该方法是申请“后台弹出页面”权限白名单时小米官方给出的检查后台启动权限的方法。或跳转到权限设置页面,请求用户打开相应权限。
欢迎阅读另一篇,跳转手机权限管理页面
小白初来乍到,多多指教
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。