Android应用程序主要是用Java语言来书写的。而android提供了一个名为aapt的工具来将编译完的java二进制文件(.class)和需要的数据和资源打包成一个apk包。用户可以在android设备上安装这个apk包。一个apk包就被认为是一个应用程序。

从很多角度来看,每一个android应用程序都是存活在一个独立的环境中的:

1)每一个应用程序默认是运行在它自己的linux进程中的。

2)每一个进程都有一个独立的虚拟器(VM),所以每一个应用程序相对于其它的应用程序是运行在一个孤岛环境中的。

3)每一个应用程序默认都会被分配一个唯一的linux用户id号。又因为有权限的作用,所以应用程序的资源只是对最终用户和它自身是可见的。当然,也有方法将应用程序的资源暴露给其它的应用程序来使用。

也可能为两个应用程序分享同一个用户id号,在这种情况下,它们就能相互访问彼此的资源。并且处于节省系统资源的目的,被分配相同的用户的id的多个应用程序可以运行在同一个linux进程中,共用同一个VM。

1.应用程序的组件(Application Components

Android的特色之一就是你的应用程序可以使用其它的应用程序的元素(需要提供元素的应用程序允许)。而你的应用程序并不需要包含或链接到提供元素的应用程序,只需要在需要的时候启动其它应用程序的相应元素。
为了支持这种特性,当某个应用的元素被其它应用使用的时候,系统需要启动这个应用程序的进程,并且初始化相应元素的Java对象。所以android应用程序的入口不像其它一些系统上的应用程序只有一个main入口,android应用程序有四种可以被系统在适当时候初始化和运行的核心组件:

1)Activity

一个Activity就代表了一个可视化用户界面,程序中所有的Activity的基类都是android.app.Activity 每一个Activity都被分配了一个默认的窗口用于绘制。一般情况下,这个窗口会填满整个屏幕,但是它也可以小于屏幕的大小,浮动在其它窗口的上面。Activity也可以使用其它的窗口――比如显示在某个Activity正中的弹出对话框,或当用户做了某项操作后,显示的一个重要信息。

可视内容是由View层次树来表示的。android.view.View是它们的基类。每一个view对象都控制了一个位于窗口范围内的矩形区域。父view对象包含和组织它的子view对象的布局。位于叶子节点的view对象会在它自身控制的矩形区域内进行绘制,并且对发生在这个区域中的用户行为进行响应。因此,view是Activity与用户发生交互的地方。
将view层次树的根节点传入Activity.setContentView()方法,就可以将view层次树的内容绘制在对应的Activity的窗口中。

2)Service

Service组件与用户界面没有直接关系,它是在后台运行的。所有的service的基类都是android.app.Service

我们可以连接到(绑定)一个正在运行的service(若这个service还没有运行,则启动这个service)。一旦连接后,我们就可以利用这个service暴露出来的接口来与这个service来进行交互。

和其它组件一样。service运行在应用程序进程的主线程中。所以为了避免阻塞其它组件的运行,service经常会开启另一个线程来完成一些耗时的工作。

3)Broadcast receiver

Broadcast receiver组件用于接收广播消息,以及对广播消息作出反应。有许多广播消息是由系统发出的,但应用程序也可以发出广播消息。

所有的broadcast receiver都是从android.content.BroadcastReceiver继承下来的。在接收到一个广播消息后,你可以启动一个activity或者显示一个通知来引起用户注意。

4)Content provider

content provider可以让你的应用程序的资源暴露给其它的应用程序使用。所有的content provider都是继承于android.content.ContentProvider。想使用你的应用程序资源的其它应用程序不会直接使用到你的应用程序中的content provider,而是会通过一个android.content.ContentResolver对象来与你的应用程序中的content provider进行交互。可见ContentResolver与content provider的搭配使用可以解决进程间通信的问题。

当发生了一个需要被一个特定的组件来处理的请求的时候,android系统会确保拥有该组件的应用程序进程正在运行,并且会确保该组件的对应的对象是存在的。

2.激活组件:意图

当ContentResolver发出请求,对应的目标content provider组件会被激活。而其余三种组件则是被一种称为”意图”的异步消息来激活的。一个意图消息就是一个携带了信息的android.content.Intent对象。对于activity和service组件,意图命名了请求的活动,指定了被操作数据的URI,和一些其它信息。对于broadcast receiver组件,意图命名了被广播的活动。

激活不同的组件需要调用不同的方法:

2.1 激活activity,需要将一个Intent对象传入Context.startActivity()方法 或者 Activity.startActivityForResult()方法。被激活的activity可以调用Activity.getIntent()方法来获取用于激活这个activity的Intent对象。若向一个已经处于激活状态的activity传递了Intent对象,则android系统会调用这个Activity的onNewIntent()方法,并且这个Intent对象传入。

若需要从被激活的activity返回结果,则需要调用Activity.startActivityForResult()方法来激活那个activity,并重写之前的那个activity的Activity.onActivityResult()方法。

2.2 将一个Intent对象传入Context.startService()方法,可以激活一个service组件(或者给一个正在运行的service组件传递新的指令)。Android系统会调用这个service的Service.onStart()方法,并将Intent对象传入。

类似的,可以将一个Intent对象传入Context.bindService()方法来与一个正在运行的service组件建立连接。Android系统会调用这个service组件的Service.onBind()方法,并将Intent对象传入(若目标service组件还没有运行,则bindService()方法可以选择性地启动目标service组件)。

2.3 将一个Intent对象传入Context.sendBroadcast()Context.sendOrderedBroadcast(),或Context.sendStickyBroadcast()方法及其变体方法中,应用程序就可以发起一个通知消息。Android系统会将这个Intent对象投递给所有感兴趣的broadcast receiver,并调用这些broadcast receiver的BroadcastReceiver.onReceive()方法中。

3.关闭组件

如上所说,我们知道不需要自己显式地去关闭content provider和broadcast receiver组件。

我们可以调用Activity.finish()方法来关闭这个activity本身。当然,我们也可以调用Activity.finishActivity(int)来关闭自己(此activity是被其它的activity调用Activity.startActivityForResult()方法来激活的)。

对于service组件,我们可以调用Service.stopSelf()方法来关闭自身,我们也可以调用Context.stopService(Intent)来关闭service组件。

另外,在组件不再被使用或Android系统在可用内存值较低的情况下,Android系统也可能关闭组件。

4.manifest文件

应用程序需要将自己的组件在manifest文件中声明,这样android系统才能知道组件的存在(Activity,Service和Content provider必须在此文件中声明;Broadcast receiver除了可以在此文件中声明,也可以通过调用Context.registerReceiver()方法在程序中动态注册)。在应用程序中,manifest文件的名字总是AndroidManifest.xml,除了声明组件,这个文件还有一些别的作用,比如说说明应用程序链接的额外的库(既除了android默认链接的库),说明程序的权限。

Activity<activity . . .></activity>

Service<service . . .></service>

Content provider<provider . . .></provider>

Broadcast receiver<receiver . . .></receiver>

5.意图塞选器

Intent对象可以显式说明目标组件的名字,android就可以通过检查manifest文件中声明的组件名字,找到对应的组件,并激活它。但Intent对象也可以不指明目标组件的名字,这样的话android系统就需要将这个Intent对象与manifest文件中声明的组件的intent filters(意图塞选器)来比较,并找到一个最合适的组件,然后激活这个组件。所以intent filter的作用就是告知android系统此组件能够处理的intent对象的类型。intent filter也在manifest文件声明(一个组件可以没有,也可以有任意多个intent-filter):

                             <intent-filter . . .>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

下面这个intent-filter说明某个组件可以处理特定的数据类型

                             <          intent-filter           . . .          >          
< action android:name ="com.example.project.BOUNCE" />
< data android:mimeType ="image/jpeg" />
< category android:name ="android.intent.category.DEFAULT" />
</ intent-filter >

对于在代码中动态注册的broadcast receiver组件,可以声明android.content.IntentFilter对象来表示一个intent-filter。

更多相关文章

  1. Android(安卓)虚拟机Dalvik、Android各种java包功能、Android相
  2. android架构
  3. Android应用开发以及设计思想深度剖析(2)
  4. Android系列开发博客资源汇总
  5. android架构
  6. Android开发之活动与任务
  7. Android(安卓)UI开发专题(一) 之界面设计
  8. Android智能指针SP WP使用方法介绍
  9. AndroidUI设计之 布局管理器 - 详细解析布局实现

随机推荐

  1. 64位ubuntu11.10使用git下载android源码
  2. Android与JS之间的互相调用交互(一)
  3. Android下生成core dump的方法
  4. android permission权限与安全机制解析(下
  5. android修炼大法
  6. android repo/git server 建立过程(1)
  7. 实现自己的Camera
  8. 在Android中引入Java8的lambda表达式
  9. Android4.0:统一标准强行安装默认主题Holo
  10. 硬件访问服务4之Android硬件访问服务框架