之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在Android系统上运行起来?

在Java平台要做到动态运行模块、热插拔可以使用ClassLoader技术进行动态类加载,比如广泛使用的OSGi技术。在Android上当然也可以使用动态加载技术,但是仅仅把类加载进来就足够了吗?ActivityService等组件是有生命周期的,它们统一由系统服务AMS管理;使用ClassLoader可以从插件中创建Activity对象,但是,一个没有生命周期的Activity对象有什么用?所以在Android系统上,仅仅完成动态类加载是不够的;我们需要想办法把我们加载进来的Activity等组件交给系统管理,让AMS赋予组件生命周期;这样才算是一个有血有肉的完善的插件化方案。

接下来的系列文章会讲述 DroidPlugin对于Android四大组件的处理方式,我们且看它如何采用Hook技术坑蒙拐骗把系统玩弄于股掌之中,最终赋予Activity,Service等组件生命周期,完成借尸还魂的。

阅读全文 »

在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式Binder Hook;插件框架通过AOP实现了插件使用和开发的透明性。在讲述DroidPlugin如何实现四大组件的插件化之前,有必要说明一下它对ActivityManagerServiche以及PackageManagerService的Hook方式(以下简称AMS,PMS)。

ActivityManagerService对于FrameWork层的重要性不言而喻,Android的四大组件无一不与它打交道:

  1. startActivity最终调用了AMS的startActivity系列方法,实现了Activity的启动;Activity的生命周期回调,也在AMS中完成;
  2. startService,bindService最终调用到AMS的startService和bindService方法;
  3. 动态广播的注册和接收在AMS中完成(静态广播在PMS中完成)
  4. getContentResolver最终从AMSgetContentProvider获取到ContentProvider

PMS则完成了诸如权限校捡(checkPermission,checkUidPermission),Apk meta信息获取(getApplicationInfo等),四大组件信息获取(query系列方法)等重要功能。

在上文Android插件化原理解析——Hook机制之Binder Hook中讲述了DroidPlugin的Binder Hook机制;我们知道AMSPMS就是以Binder方式提供给应用程序使用的系统服务,理论上我们也可以采用这种方式Hook掉它们。但是由于这两者使用得如此频繁,Framework给他们了一些“特别优待”,这也给了我们相对于Binder Hook更加稳定可靠的hook方式。

阅读全文 »

Android系统通过Binder机制给应用程序提供了一系列的系统服务,诸如ActivityManagerServiceClipboardManagerAudioManager等;这些广泛存在系统服务给应用程序提供了诸如任务管理,音频,视频等异常强大的功能。

插件框架作为各个插件的管理者,为了使得插件能够无缝地使用这些系统服务,自然会对这些系统服务做出一定的改造(Hook),使得插件的开发和使用更加方便,从而大大降低插件的开发和维护成本。比如,Hook住ActivityManagerService可以让插件无缝地使用startActivity方法而不是使用特定的方式(比如that语法)来启动插件或者主程序的任意界面。

我们把这种Hook系统服务的机制称之为Binder Hook,因为本质上这些服务提供者都是存在于系统各个进程的Binder对象。因此,要理解接下来的内容必须了解Android的Binder机制,可以参考我之前的文章Binder学习指南

阅读全文 »

Markdown这种格式的出现大大提升了写作的效率,但是它对于非英文的用户其实并不友好:每当我们需要使用#[-等标志符的时候,需要不断地切换输入法。

首先,切换输入法(就算是按shift键)让我们的思维不连贯;其次,一旦中间有一次切换出错,那么又有撤销的成本;我相信每一个非英文markdown的使用者都有这种困惑;实际想要达到的效果如下:

效果图

阅读全文 »

使用代理机制进行API Hook进而达到方法增强是框架的常用手段,比如J2EE框架Spring通过动态代理优雅地实现了AOP编程,极大地提升了Web开发效率;同样,插件框架也广泛使用了代理机制来增强系统API从而达到插件化的目的。本文将带你了解基于动态代理的Hook机制。

阅读本文之前,可以先clone一份 understand-plugin-framework,参考此项目的dynamic-proxy-hook模块。另外,插件框架原理解析系列文章见索引

代理是什么

为什么需要代理呢?其实这个代理与日常生活中的“代理”,“中介”差不多;比如你想海淘买东西,总不可能亲自飞到国外去购物吧,这时候我们使用第三方海淘服务比如惠惠购物助手等;同样拿购物为例,有时候第三方购物会有折扣比如当初的米折网,这时候我们可以少花点钱;当然有时候这个“代理”比较坑,坑我们的钱,坑我们的货。

从这个例子可以看出来,代理可以实现方法增强,比如常用的日志,缓存等;也可以实现方法拦截,通过代理方法修改原方法的参数和返回值,从而实现某种不可告人的目的~接下来我们用代码解释一下。

阅读全文 »

2015年是Android插件化技术突飞猛进的一年,随着业务的发展各大厂商都碰到了Android Native平台的瓶颈:

  1. 从技术上讲,业务逻辑的复杂导致代码量急剧膨胀,各大厂商陆续出到65535方法数的天花板;同时,运营为王的时代对于模块热更新提出了更高的要求。
  2. 在业务层面上,功能模块的解耦以及维护团队的分离也是大势所趋;各个团队维护着同一个App的不同模块,如果每个模块升级新功能都需要对整个app进行升级,那么发布流程不仅复杂而且效率低下;在讲究小步快跑和持续迭代的移动互联网必将遭到淘汰。

H5和Hybird可以解决这些问题,但是始终比不上native的用户体验;于是,国外的FaceBook推出了react-native;而国内各大厂商几乎都选择纯native的插件化技术。可以说,Android的未来必将是react-native和插件化的天下。

阅读全文 »

虽说现在做网络请求有了Volley全家桶和OkHttp这样好用的库,但是在处理其他后台任务以及与UI交互上,还是需要用到AsyncTask。但是你真的了解AsyncTask吗?

AsyncTask的实现几经修改,因此在不同版本的Android系统上表现各异;我相信,任何一个用户量上千万的产品绝对不会在代码里面使用系统原生的AsynTask,因为它蛋疼的兼容性以及极高的崩溃率实在让人不敢恭维。本文将带你了解AsyncTask背后的原理,并给出一个久经考验的AsyncTask修改版。

阅读全文 »

毫不夸张地说,Binder是Android系统中最重要的特性之一;正如其名“粘合剂”所喻,它是系统间各个组件的桥梁,Android系统的开放式设计也很大程度上得益于这种及其方便的跨进程通信机制。

理解Binder对于理解整个Android系统有着非常重要的作用,Android系统的四大组件,AMS,PMS等系统服务无一不与Binder挂钩;如果对Binder不甚了解,那么就很难了解这些系统机制,从而仅仅浮游与表面,不懂Binder你都不好意思说自己会Android开发;要深入Android,Binder是必须迈出的一步。

现在网上有不少资料介绍Binder,个人觉得最好的两篇如下:

  1. Binder设计与实现
  2. Android进程间通信(IPC)机制Binder简要介绍和学习计划系列

其中, 《Binder设计与实现》以一种宏观的角度解释了Android系统中的Binder机制,文章如行云流水;如果对于Binder有一定的了解再来看着篇文章,有一种打通任督二脉的感觉;每看一次理解就深一层。老罗的系列文章则从系统源码角度深入分析了Binder的实现细节;具有很大的参考意义;每当对于Binder细节有疑惑,看一看他的书就迎刃而解。

但是遗憾的是,Binder机制终究不是三言两语就能解释清楚的,一上来就扒出源码很可能深陷细节无法自拔,老罗的文章那不是一般的长,如果看不懂强行看很容易睡着;勉强看完还是云里雾里;相反如果直接大谈特谈Binder的设计,那么完全就是不知所云;因此上述两篇文章对于初学者并不友好,本文不会深入源码细节,也不会对于Binder的设计高谈阔论;重点如下:

阅读全文 »

我们使用纯文本写代码,有了Markdown又可以使用纯文本写文档,那么对于更直观的信息表达方式——图片,能不能使用纯文本描述呢?

另外,你是否见到过这样的注释:

ASCII art图像

没错,这种逼格极高的ASCII图片注释方式就是我们要讨论的话题。

阅读全文 »

虽然大部分的时候是使用命令行,但是有些时候我们需要在Finder里面编辑某些文件的时候,如果还是拘泥于这样,就必须打开 iTerm (幸好有Profile可以一键打开终端)切换目录,编辑;这时候,类似Windows系统的右键菜单就比较方便了。

如果Mac系统识别出这是一个文本文件,右键菜单的 打开方式 可能还有点用,如果识别不出来,那么手动选择应用程序就比较麻烦了:

其实Mac系统的 AutoMator 是可以完成这个功能的;接下来说一下操作步骤。

阅读全文 »