前言

Android Lolipoop以上版本屏蔽了隐式Intent启动Service,以前我们可以这么做:

Intent intent = new Intent("action.of.service");
context.startService(intent);

现在这样行不通了,会报错!根据Google指示,我们最少应该给Intent里面加上Service的包名:

Intent intent = new Intent("action.of.service");
intent.setPackage("packageName.of.service");
context.startService(intent);

好的,这样修改就妥妥的了。

偷懒

我们动动歪脑筋,在手握源码的情况下,为何不直接屏蔽隐式Intent验证机制呢?回到KitKat年代,一片和谐,多么美好。

过程

说干就干。start/stop/bind service时的Intent验证机制位于ContextImpl.java中。
可以看到也就是抛个异常,别的啥也没干嘛。于是我们动手:

    private void validateServiceIntent(Intent service) {if (service.getComponent() == null && service.getPackage() == null) {if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {IllegalArgumentException ex = new IllegalArgumentException("Service Intent must be explicit: " + service);throw ex; <--- 我们轻松将其注释} else {Log.w(TAG, "Implicit intents with startService are not safe: " + service+ " " + Debug.getCallers(2, 3));}}}

之后新编framework.jar替换原来的,重启。

问题

一切并未按预期发展,更改后的系统开机时不断重启,检查log,发现出错的调用堆栈与DevicePolicyManagerService.java和KeyChain.java两个文件有关。

DevicePolicyManagerService

代码接收开机广播,启动一个AsyncTask。

    BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {......if (Intent.ACTION_BOOT_COMPLETED.equals(action)|| KeyChain.ACTION_STORAGE_CHANGED.equals(action)) {new MonitoringCertNotificationTask().execute(intent);}}}

AsyncTask中做了一些工作,其中会调用KeyChain进行绑定Service操作。

        private void manageNotification(UserHandle userHandle) {......// Call out to KeyChain to check for user-added CAsboolean hasCert = false;try {KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle);try {if (!kcs.getService().getUserCaAliases().getList().isEmpty()) {hasCert = true;}} catch (RemoteException e) {Log.e(LOG_TAG, "Could not connect to KeyChain service", e);} finally {kcs.close();}} catch (InterruptedException e) {Thread.currentThread().interrupt();} catch (RuntimeException e) {Log.e(LOG_TAG, "Could not connect to KeyChain service", e);}......}

KeyChain

    public static KeyChainConnection bindAsUser(Context context, UserHandle user)throws InterruptedException {if (context == null) {throw new NullPointerException("context == null");}......Intent intent = new Intent(IKeyChainService.class.getName());ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);intent.setComponent(comp); <---- 出错时,这个ComponentName为空boolean isBound = context.bindServiceAsUser(intent,keyChainServiceConnection,Context.BIND_AUTO_CREATE,user);if (!isBound) {throw new AssertionError("could not bind to KeyChainService");}return new KeyChainConnection(context, keyChainServiceConnection, q.take());}

可以看到KeyChain中视图绑定一个Service,且在出错的调用链上Component为空,实际上是隐式Intent绑定Service。
这是Google自己也有问题啊。。。。。。

分析

1.隐式Intent验证机制生效,系统正常。
2.隐式Intent验证机制被屏蔽,系统System进程报错,定位错误位于以上启动Service代码。
3.绑定Service出错时,KeyChain抛出AssertionError异常。
4.AssertionError异常直接继承与Error类。方法调用者DevicePolicyManagerService并未捕获此异常。
4.因此,导致DevicePolicyManagerService执行出错,又该Service是系统核心服务运行于System_Server进程,则System进程挂掉,重启。
5.如果打开隐式Intent验证机制,则抛出IllegalArgumentException,继承于RuntimeException,被DevicePolicyManagerService捕获,不会导致挂掉。系统继续往下运行。

解决

加一行catch即可,搞定。

        private void manageNotification(UserHandle userHandle) {......// Call out to KeyChain to check for user-added CAsboolean hasCert = false;try {KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle);try {if (!kcs.getService().getUserCaAliases().getList().isEmpty()) {hasCert = true;}} catch (RemoteException e) {Log.e(LOG_TAG, "Could not connect to KeyChain service", e);} finally {kcs.close();}} catch (InterruptedException e) {Thread.currentThread().interrupt();} catch (RuntimeException e) {Log.e(LOG_TAG, "Could not connect to KeyChain service", e);} catch (AssertionError e) { <--- 万恶的异常。Log.e(LOG_TAG, "Could not connect to KeyChain service", e);}......}

存疑

个人认为,根本原因应该是IKeyChainService这个Service没有找到,导致了后续问题。待查到为什么找不到这玩意后再来更新。

转载于:https://www.cnblogs.com/zxfrdas/p/5128994.html

Android Lolipop 屏蔽隐式Intent检查引发的错误相关推荐

  1. Android学习-Kotlin语言入门-变量、函数、语法糖、when、for-in、主构造函数、单例类、函数式API、集合遍历、隐式Intent、Activity生命周期、四种启动模式、标准函数

    探究java语言的运行机制 变量.函数.语法糖 when条件语句 for循环 主构造函数.次构造函数 数据类和单例类 集合的创建与遍历 集合的函数式API 创建菜单 隐式使用Intent Activi ...

  2. android之隐式intent调用

    直接上代码 MainActivity.java 1 package com.example.test1; 2 3 import android.app.Activity; 4 import andro ...

  3. Android Intent常用方法详细介绍,显示Intent,隐式Intent,调用浏览器,拨号,发短信,传递数据

    Intent介绍 Intent是Android程序中各个组件之间进行交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,还可以在不同组件之间传递数据.Intent一般用于启动活动,启动服务以及发 ...

  4. Android Studio App开发入门之在活动之间传递消息(附源码 超详细必看)(包括显示和隐式Intent,向上一个和下一个Activity发送数据)

     运行有问题或需要源码请点赞关注收藏后评论区留言~~ 显示Intent和隐式Intent Intent是各个组件之间的信息沟通的桥梁,既能在Activity之间沟通,又能在Activity与Servi ...

  5. Android编程权威指南(第15章 隐式intent)

    15.1 1.添加按钮用字符串(Strings.xml) <string name="crime_report_subject">CriminalIntent Crim ...

  6. 新手求助,关于添加隐式intent程序崩溃问题

    新手一枚,刚开始学Android开发,最近在学隐式intent,发现加入后不报错但是运行后系统崩溃,有木有大神愿意指导一下,感激不尽. 以下为日志信息: 12-04 14:07:33.871: E/A ...

  7. 使用隐式Intent打开系统浏览器的百度网页

    使用隐式Intent,我们不仅可以启动自己程序内的活动,还可以启动其它程序的活动,这使得Android多个应用程序之间的功能共享成为了可能.比如说你的应用程序中需要展示一个网页,这时你没有必要自己去实 ...

  8. 显式Intent 和隐式 Intent 的区别

    显式 Intent : 在知道目标组件名称的前提下,去调用Intent.setComponent().Intent.setClassName()或Intent.setClass()方法或者在new I ...

  9. 显式Intent与隐式Intent

    1.显式Intent(explicit intent) 显式Intent明确指定了要启动的activity: Intent intent= new Intent(this, Target.class) ...

  10. 显示Intent和隐式Intent

    转载自:https://www.cnblogs.com/liaojie970/p/5827433.html Intent是Android初学者比较难理解的一个东西.我这里以通俗易懂的语言和通俗易懂的代 ...

最新文章

  1. 基于弹性束图匹配的人脸识别
  2. 关于Strut2内置Json插件的使用
  3. 多租户数据中心该如何布线?
  4. 熟读《阿里巴巴java开发手册》(五、 MySQL 数据库)
  5. JAVA——获取classpath文件路径空格转变成了转义字符(%20)的问题解决方案
  6. Visual Studio Code支持JUnit
  7. 专利:结构化大数据通信协议
  8. 模拟便于直接存取的索引文件结构_07016.2.0使用Solr7对结构化csv文件建立全文索引...
  9. [20141121]无法通过powershell读取sql server性能计数器问题
  10. 关于Linux系统启动过程,你应该了解这些
  11. jQuery EasyUI/TopJUI创建日期输入框
  12. adf4351_配置MySQL以进行ADF开发
  13. 游怎么用模拟器多开挂机不封号
  14. 【8001】解决打开idea出现红色感叹号报错信息Cannot find keymap Windows copy?
  15. 打砖块游戏源文件_大家无聊的话不如来玩玩这些小游戏
  16. 关于Python发布三十周年的纪念
  17. vue实现刷新页面随机切换背景图【适用于登陆界面】
  18. 九月份研究生开学之前计划
  19. html 视频录制插件,网页视频录制插件工具(浏览器插件 Recorder)
  20. 亚伟计算机速录测试软件,亚伟中文速录软件

热门文章

  1. linux vim个人配色方案
  2. crontab命令 :Linux下定时执行脚本
  3. enum java 判断相等_聊一聊Java的枚举enum
  4. [PAT B1020] 月饼
  5. 自组织特征映射网络1
  6. 查看AWS中Identity and Access Management(IAM)的Access Key和Secret Access
  7. 翻译:机器学习 数据科学家 top 10 十大算法
  8. 极客大学架构师训练营 微服务架构 Service Mesh 服务网格 RPC 协议实现原理 Dubbo 通讯协议 第19课 听课总结
  9. 极客大学架构师训练营 编程的本质与未来 第三课 听课总结
  10. Python列表和元组:[] ()