Android的每次平台更新,都一直在努力收紧应用权限。8.0也不例外,这次是限制应用后台启动service的权限。相关的问题现象,可参考http://blog.csdn.net/chenshengfa/article/details/71407704。

        不过本文除了吐槽下新的后台限制对8.0平台适配带来的影响外,主要是说说本人在开发中发现的一些可规避的方法。先声明一下,由于应用权限问题,本文并不适合普通应用开发,仅做研究参考。

        虽然Android官方在限制了后台service启动的同时,也给出了替代方案。但毕竟有些功能,是其他方案无法替代或即便替代了也无法达到以往的效果的。比如监听网络变化、监听亮灭屏等这些需求。真是一去不复返的坑,对于一些习惯了耍流氓的我们,真真是不方便了啊。以下,是方案正文。

1.      对于所有应用可以使用的解决方法。

1). 平台区分,8.0以下,爱咋咋地,以前怎样还怎样。

2). 8.0以上,统一一个常驻service,转为前台。方法为:将startService改成startForegroundService,并在对应的service创建的时候,使用startForeground注册自己的notification。

3). 对,这个方法是带notification的,也就是说,如果想用常驻service,就得让用户知道。

2.      对于系统应用,可以使用的方法(需要有system权限)。

可能有人说,我都系统应用了,哪儿要这么麻烦,我已经是特殊员工啦,Android禁止我干嘛。对哦,你要是有7大姑8大姨的也想享受权限怎么搞?我所负责的应用,就有这么一款,处在灰色地带的,一部分有system权限,另一部分小弟却在局子外边混。

首先,我们看一下源码中的启动部分

ActiveServices.java -> startServiceLocked(),里边有这么一段

if(!r.startRequested && !fgRequired) {    // Before going further -- if this app isnot allowed to start services in the    // background, then at this point we aren'tgoing to let it period.    final int allowed =mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,            r.appInfo.targetSdkVersion,callingPid, false, false);    if (allowed !=ActivityManager.APP_START_MODE_NORMAL) {        Slog.w(TAG, "Background start notallowed: service "                + service + " to " +r.name.flattenToShortString()                + " from pid=" +callingPid + " uid=" + callingUid                + " pkg=" +callingPackage);        if (allowed ==ActivityManager.APP_START_MODE_DELAYED) {            // In this case we are silentlydisabling the app, to disrupt as            // little as possible existing apps.            return null;        }        // This app knows it is in the newmodel where this operation is not        // allowed, so tell it what hashappened.        UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);        return new ComponentName("?","app is in background uid " + uidRec);    }}


不难发现,如果service不是fgRequired前台唤醒,那就得走这段了,获取service所持有的应用MODE是否为APP_START_MODE_NORMAL。也就是说,一旦应用为APP_START_MODE_NORMAL,就可以开开心心的启动后台service了。进入ActivityManagerService.java ->getAppStartModeLocked()查看定义,核心基本上就是这个了

final intstartMode = (alwaysRestrict)        ? appRestrictedInBackgroundLocked(uid,packageName, packageTargetSdk)        :appServicesRestrictedInBackgroundLocked(uid, packageName,               packageTargetSdk);


直接看appServicesRestrictedInBackgroundLocked()

intappServicesRestrictedInBackgroundLocked(int uid, String packageName, intpackageTargetSdk) {    // Persistent app?    if (mPackageManagerInt.isPackagePersistent(packageName)){        if (DEBUG_BACKGROUND_CHECK) {            Slog.i(TAG, "App " + uid+ "/" + packageName                    + " is persistent; notrestricted in background");        }        return ActivityManager.APP_START_MODE_NORMAL;    }     // Non-persistent but backgroundwhitelisted?    if (uidOnBackgroundWhitelist(uid)) {        if (DEBUG_BACKGROUND_CHECK) {            Slog.i(TAG, "App " + uid+ "/" + packageName                    + " on backgroundwhitelist; not restricted in background");        }        returnActivityManager.APP_START_MODE_NORMAL;    }     // Is this app on the battery whitelist?    if (isOnDeviceIdleWhitelistLocked(uid)) {        if (DEBUG_BACKGROUND_CHECK) {            Slog.i(TAG, "App " + uid+ "/" + packageName                    + " on idle whitelist;not restricted in background");        }        returnActivityManager.APP_START_MODE_NORMAL;    }     // None of the service-policy criteriaapply, so we apply the common criteria    return appRestrictedInBackgroundLocked(uid,packageName, packageTargetSdk);}


然后就是各种判断了,作为有system权限的应用,就可以给其他应用开后门啦。

 

其中的isOnDeviceIdleWhitelistLocked,用户可用通过进入设置->应用详情->管理电池应用,此处可以通过开关进行改变这个值,或者设置->电池->右上方的菜单,电池优化中,修改应用列表即可。

 

如上,收尾。

更多相关文章

  1. 如何在后台运行Linux命令?
  2. Root你的设备
  3. Android用SQLite存储数据详解
  4. Android(安卓)截图功能源码的分析
  5. Activity详解一 配置、启动和关闭activity
  6. Android:这是一份全面 & 详细的Webview使用攻略
  7. Android的事件类型及事件处理机制
  8. Android(安卓)View事件分发机制
  9. Android编程研究(二)——Message和message Handler

随机推荐

  1. 使用Jenkins自动打包android
  2. 关于实现S5PV210同时跑wince 和android双
  3. 关于Android(安卓)O不能正常推送通知问题
  4. Android短信发送流程(原)
  5. Android系统权限和root权限的获取以及应
  6. Android(安卓)4.2上调试RT3070 WiFi模块
  7. android socket 编程实例
  8. React Native 实现热部署、差异化增量热
  9. Android(安卓)蓝牙4.0 Ble 连接Ble模块
  10. Android艺术探索学习笔记:第2章 IPC机制