android系统的一项革命性的创新就是将所有应用程序的每个功能模块都变成系统的一个功能,可以供任意合法的应用程序使用。这个特性打破了以往的应用程序的边界,实现了彻底的组件化编程,写应用程序就跟搭积木一样,只需要将各个功能模块重新排列组合一下,这曾是无数老程序员的梦想。
为了让应用开发人员更好地适应组件化编程,android一方面要求程序员将应用划分为独立的功能模块并按统一的接口实现各个模块,另一方面模糊了进程等传统应用开发中阻碍模块共享的概念。
但事实上,进程依然存在,而且非常重要,它是实现安全机制的基础。通常情况下,每个apk对应一个进程,在系统中拥有特定的用户ID。linux本身的权限管理基于用户ID,android实现的安全机制也基于进程ID和用户ID。为了安全,应用的私有资源外人不得访问,包括文件、数据库、程序资源等静态实体,也包括内存、组件等动态实体。
那为何我们写的很多组件能被其它应用使用呢?当然也有很多组件不能被其它应用使用,这正是我写这篇文章的起因。如上所述,android的应用程序同样局限于进程内,为了供其它应用使用,它需要定义好外界使用的接口,并通知外界。android系统定义了四种基本组件,为它们定义了统一的接口,并通过manifest向系统注册,其它应用通过系统服务来查询并调用系统中注册的功能模块。
android提供的公用功能模块很多,但也免不了有更多的私有模块,不宜供其它应用使用,都开放出来既没效率也不安全。所以在注册功能模块时,我们需要告知系统该功能能否供其它应用使用。这可以通过组件的android:exported属性来实现,示例如下:
<activity android:name=".InkExample"
android:label="@string/app_name" android:exported="true">
但很多组件其实可以很容易地通过其它属性推测它是否需要供其它应用使用,默认情况下android系统就会自行推测。具体规则如下:
public static final int exported
Flag indicating whether the given application component is available to other applications. If false, it can only be accessed by applications with its same user id (which usually means only by code in its own package). If true, it can be invoked by external entities, though which ones can do so may be controlled through permissions. The default value is false for activity, receiver, and service components that do not specify any intent filters; it is true for activity, receiver, and service components that do have intent filters (implying they expect to be invoked by others who do not know their particular component name) and for all content providers.