应用程序基本原理

Android应用程序是由Java编程语言写成的。Android的SDK工具编译的Java代码,包括:所有数据、资源文件一起放到一个扩展名为.apk文件里。一个完整的.apk文件被看成是一个应用程序,并能安装到android设备上的应用程序安装文件。

一旦安装到设备中,每一个Android应用都生存在她自己的安全沙箱里:

  • Android操作系统是一个多用户的Linux系统,每一个应用是一个不同的用户。
  • 默认地,系统分配给每一个应用程序一个唯一的Linux用户ID。(ID仅被系统使用,程序自己并不知道这个ID)。在一个应用里,系统为所有文件设置许可而只有通过用户ID才能访问这些文件。
  • 每个进程有它自己的虚拟机(VM),所以某个应用在运行时,和其他应用是隔离的。
  • 默认地,每一个应用都运行在它自己的Linux进程中。当需要执行任何应用代码的时候,Android就会启动进程;而当该应用不再需要或系统需要为其他应用请求系统资源的时候,Android就关闭该进程。

通过这种方法,android系统实现了最小权限原则。默认情况下,每个应用程序只有在某个组件需要工作时才能被访问到。这样就创建了一个安全的环境,即应用程序是不能访问那些系统中没有获得权限的部分。

然而还是有方法使应用能共享数据和使应用能访问系统服务:

  • 可以使两个应用程序分享同一个linux用户id,这种情况下他们能互相访问文件,为了节省系统资源,同一个用户id的应用可以在同一个linux进程中运行,分享同一个虚拟机(应用也必需有相同的签字证书)
  • 应用能请求访问设备数据的权限,例如:联系人,sms信息,存储卡(sd卡),照相机,蓝牙等等。所有应用的权限必需在安装时通过用户许可。

以上基本的说明了一个android应用是怎么存在系统里的。文档还介绍了:

  • 应用中的核心框架组件。
  • mainifest.xml文件,用来声明应用中使用的组件和对设备的特殊要求
  • 资源文件,是从应用程序代码中分离出来的,其能使你的应用能在多样化的设备配置下完美有效的展示出来

应用程序组件

应用程序组件是构建Android应用程序的必要模块。每个组件是一个不同的切入点,通过它系统能进入你的应用程序。对于用户来说不是所有的组件都是真实的切入点,有些组件还彼此相互依赖。但是每个组件作为实体单独的存在着并扮演一个特殊的角色———— 每一个组件都是独特的构造模块,一起来定义你应用程序所有的行为。

有四种不同类型的应用程序组件。每种类型服务于不同的目的,并且有不同的生命周期来定义组件的创建和销毁。

四种类型的应用程序组件:

Activities

  • 一个 activity 描绘一个用户界面。例如,一个邮件应用可能有一个显示新邮件列表的activity,一个组建邮件的activity,一个阅读邮件的activity。虽然这些activity在一个邮件应用程序中协同合作来形成一个完整的用户体验,但每一个activity和其它的activity是相互独立的。就像这样,一个其他的应用程序可以启动以上任何一种activity(如果邮件应用程序同意的话)。例如,一个照相应用程序可以启动邮件应用中的activity来组成新的邮件,这样能使用户分享图片。
  • 一个activity是一个Activity对象的子类,你可以在开发指南 Activity中学到更多。

Services

  • 一个service是一个组件,运行在后台来执行长时间操作或执行远程操作。service不提供用户界面。例如,一个service可以使用户在其他应用里时,同时在后台播放音乐,或可以在不阻塞用户在activity界面中交互时从网络中取得数据。另一种组件,比如说一个activity可以启动一个service并运行起来或和activity绑定以便交互。
  • 一个service是一个Service对象的子类,你可以在开发指南Service中学到更多。

Content providers

  • content provider管理一个分享式的应用数据集合。你可以存储数据在文件系统,SQLLite数据库,网络上,或你的应用可以访问到的任何本地持久化存储容器里。通过content provider,其他应用可以查询或甚至更新数据(如果content provider允许)。例如,android系统提供一个content provider来管理用户的联系人信息,这样,任何拥有适当权限的应用可以查询content provider中部分内容(如 ContactsContract.Data)来读取和写入一个特定人的信息
  • content provider也可以读和写那些仅对你的应用可见并不提供共享的数据。例如,记事本例子应用使用content provider来保存笔记。
  • 一个content provider是ContentProvider对象的一个子类,必须实现一个标准的API集合使其他应用来处理事务。要获得更多信息,请阅读Content Providers开发指南。

Broadcast receivers
  • broadcast receiver是一个组件来响应系统范围内的广播通告。许多的广播来自于系统,例如,一个广播通告了:屏幕关闭,电量不足或拍了一张照片。应用也可以发布广播,例如,让其他应用知道一些数据被下载到设备中并可以使用,虽然broadcastreceiver没有一个用户界面,但他们可以创建一个状态栏通知来告知用户一个广播事情在发生。非常普遍的,一个broadcastreceiver对于其他组件来说,仅仅是一个通道并用来去做极少数量的工作。例如,它可能用来开启一个服务(service)来执行基于事件的一些工作。
  • broadcast receiver实例是BroadcastReceiver对象的一个子类,并且每一个广播做为Intent对象来传递。要获得更多信息,请阅读BroadcastReceiver类。

android系统一个特性就是任何应用都可以调用其他应用的组件。例如,如果你想让用户使用设备的摄像头来拍张照片,也许另一个应用可以这么做而你的应用可以调用它,而不是开发一个你自己的activity来完成拍照功能。你不需要合并或甚至从拍照应用中调用代码。取而代之,你可以简单的启动一个activity在照相机应用中来拍照。当结束时,照片传回到你的到你的应用以便你可以使用它。对于用户来说,它看起来就像照相应用就是你的应用的一部分。

当系统启动一个组件,它就为应用开启一个进程(如果组件没用运行时)并实例化组件所需要的类。例如,如果你的应用启动一个拍照应用中的activity来拍了张照,这个activity在进程中运行,这个进程属于拍照应用而不是你的应用进程中。因此,不像其他大多数系统中的应用一样,android应用没有一个单独的切入点。(如没有main()方法)

因为系统运行每一个应用在单独的进程中,并带有文件权限来限制访问其他应用。你的应用不能直接激活其他应用中的组件。android系统却可以。因此为了激活其他应用中的组件,你必须向系统中传递一个消息来指定你的intent去启动特殊的组件。系统会为你激活这个组件。

Activating Components

四种组件中的三种:activities, services, 和broadcast receivers被称为intent的异步消息激活。在运行时,intent把一个个组件相互绑定起来(你可以把他们想成是消息,来请求来自其他组件的一个动作)不管这个组件是属于你的应用或其他的。

Intent对象创建一个intent,定义一种消息来激活特定的组件或特殊类型的组件。intent可以是明确的或隐式的。

对于activity和service,intent定义了处理事件的动作(如,观看或发送某些东西),可以指定要演示的数据的地址(组件在启动时要先知道其他的一些事情)。例如,intent可以传递一个请求,需要activity来显示图片或打开一个网页。在一些情况,你可以启动一个activity来收到一个回复,同样的情况,activity可以把返回的结果放到intent对象里(例如,你可以发布一个intent让用户挑选一个人员联系表,然后返回给你,这个返回的intent中包括指向选择的联系人的地址).

对于broadcastreceviver,intent仅仅定义了广播着的通告(例如,一个广播指示设备的电量偏低,他仅包括一个显示“电量不足”的通知字符串)

其他的组件类型,content provider,不被intent激活。然而,它被一个来自ContentResolver的请求作为目标激活。content resolver处理所有有content provider直接提供的事务,以使组件处理事务时不需要contentprovider而调用ContentResolver对象中的方法。这样在content provider和组件请求信息时通过一个抽象层来提供安全。

对于每种组件来说,激活的方法是不同的:

  • 你可以启动一个新的activity(或让其做一些新的任务)通过想startActivity()或startActivityForResult() (当你activity返 回结果时)方法传递一个intent对象。

  • 你可以启动一个服务(或发新的指令给不间断服务)通过向 startService()方法中传递Intent对象或你可以通过想 bindService()方法中传递一个Intent来绑定服务。

  • 你可以发布一个广播,通过向 sendBroadcast(), sendOrderedBroadcast()或sendStickyBroadcast()方法中传递一个intent对象。

  • 你可以处理一个查询通过在ContentResolver对象中调用query()方法。

关于使用intent的更多信息,阅读Intents and Intent Filters文档。更多关于激活特定组件的信息在以下文档中提供:Activities,Services,BroadcastReceiver 和Content Providers.

The Manifest File

安卓系统启动应用程序组件之前,系统必须预读应用程序中的AndroidManifest.xml文件来知道有哪些组件。你的应用程序中所有的组件必须声明在这个文件中,此文件放在应用程序的根目录下。

在manifest文件里,同时也申明应用程序组件的附带属性和内容,如:

  • 确认应用程序所需要的所有用户许可,如:网络连接,用户联系人的阅读权限。

  • 声明了程序需要的最低API版本,根据程序所使用的API来确定。

  • 声明程序所需要和使用的软硬件,如:摄像头,蓝牙,多点触摸

  • 程序所需要连接的其他的API库(除了安卓核心API),如,谷歌地图API库

  • 等等

Declaring components

Mainfest文件的基本任务就是声明了程序所涉及的组件。例如,mainfest可以像下面那样声明一个activity:

<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:icon="@drawable/app_icon.png" ... >
<activity android:name="com.example.project.ExampleActivity"
android:label="@string/example_label" ... >
</activity>
...
</application>
</manifest>

在<application>元素里,android:icon属性用一个图标来标识那个程序。

在<activity>里,android:name属性指明Acitvuty子类的全称,android:label属性显示了一个用户可见的activity标题栏中的标题。

你必须使用下面的元素声明所有程序的组件:

  • <activity>元素声明activity组件

  • <service>元素声明services组件

  • <receiver>元素声明broadcast receiver组件

  • <provider>元素声明content providers组件

Activity,services和content provider三种组件如果没有在mainfest文件中声明,那么系统是识别不了,因此也运行不了。然而,broadcastreceiver不仅可以在mainfest文件中声明,而且可以在代码中动态创建(像BroadcastReceiver对象)并通过调用registerReceiver()方法来注册。

如需要了解更多关于构建mainfest文件的信息,可以参阅AndroidManifest.xml文档。

Declaring component capabilities

就像在激活组件段落中讨论的,你可以使用Intent来启动activity,service,broadcast receiver。你可以使用明确的目标组件名称(使用组件类名)作为Intent的参数来激活他们。Intent真正的作用体现在intent对象里。在intent类中,你简单的描述你想要处理的动作并且允许设备里的系统能发现并运行起来。如果通过intent对象描述了许多组件可以运行,用户选择一个来使用。

系统识别组件的方法是通过intent过滤器,intent过滤器写在manifest文件里。

当在你的mainfest文件中声明组件时,你可以随意的包括阐述组件能力的intent过滤器,这样可以回复来自其他应用的intent。你可以给你的组件添加intent过滤器,通过在各自组件的元素下使用<intent-filter>元素下来实现。

例如,一个邮件程序用来组建一个新的邮件程序可能会在它的mainfest文件里写上intent过滤器,来发送intent。在你的程序里,一个action可以创建一个发送intent消息的action,当你调用startActivity()方法中的intent时,系统会匹配邮件应用中的发送action,并启动它。

要获得更多关于intent过滤器的信息,查阅Intent and Intent Fileters文档。

Declaring application requirements

使用安卓系统的设备有很多种,不是所有的设备都有相同特性和能力。为了阻止你的应用安装在那些缺少你的程序所需要的属性的设备中时,重要的是,你清晰的定义你的应用所支持的各种设备大概的样子,可以通过在你的mainfest文件里说明设备和软件所需要的东西。大多数这些描述只是信息,系统不会解析他们,但是在其他的服务中,如安卓市场,会阅读他们,在用户在他们自己的设备中查找应用时,会过滤掉那些不能在设备中运行的应用。

例如,如果你的应用需要摄像头和使用的安卓2.1版本的API,你需要在mainfest文件中说明所需要的这些。这样,设备没有摄像头和安卓API版本比2.1还低,那么就不能从安卓市场中安装了。

然而,你也可以说明你的应用需要摄像头,但是并不需要它。在这种情况下,你的应用必须在启动时检查,如果有摄像头则用如果没有则不用。

有一些重要的设备特性需要你在设计和开发你的应用时需要考虑的:

  • Screen size and density
    为了通过屏幕的种类来区分设备,安卓为每个设备定义了两种特性:屏幕尺寸(屏幕的物理大小)和屏幕的像素(在屏幕里的物理像素或每英寸点数)。为了简化所有不同种类屏幕的配置,安卓系统把他们做了分组

    屏幕的尺寸:small,normal,larger,extra large

    尺寸像素:low density, medium density, high density, extra high density.

    默认的,你的应用是匹配所有的屏幕的尺寸和像素的,因为安卓系统会根据你的界面布局和图像进行适当的调整。然而,你必须为确切的屏幕尺寸创建专门布局,为确切的屏幕像素确定专门的图片,使用备用的布局资源文件,并在你的mainfest文件中,使用<supports-screens>元素准确的说明你的应用所支持的屏幕大小。

    更多的信息,查阅SupportingMultiple Screens 文档。

  • Input configurations

    许多设备提供不同类型的用户输入机制,例如键盘,滚动球,或五方向的导航键。如果你的应用需要一个特殊的输入机制,你需要在你的mainfest文件中的<uses-configuration>元素中说明。然而,一个应用很少会需要一个输入配置语句。

  • Device features
    在一个具体的安卓设备中,会存在或不存在很多软硬件功能,例如:摄像头,光传感器,蓝牙,某个版本的OpenGL或触摸屏。你永远不能假设所有的安卓设备上会有哪些功能(除了标准的安卓类库),因此你需要使用<uses-feature>元素来说明你的应用所需要的功能。
  • Platform Version
    不同的安卓设备上运行的经常是不同的安卓版本,如,安卓1.6、2.3。后来的版本中添加的API库在以前的版本中是不支持的。为了指明哪个API可用,每个平台版本有一个API等级。(如,1.0版本的API等级为1,2.3版本的API等级为9)。如果你使用1.0以后的版本,你应该在<uses-sdk>元素中说明程序需要的最小API等级。

重要的是,你要说明你的应用所需要那些支持,因为,当你在安卓市场中介绍你的应用时,安卓市场会通过这些描述来匹配哪些设备适合你的应用。这样以来,你的应用就只能在匹配你的程序的需求的设备里运行了。

更多的关于安卓市场怎么匹配你的应用需求的信息,参阅Market Filters文档。

Application Resources

一个安卓应用不仅仅是由代码组成的,它需要其他的一些资源,如:图片,音频文件和任何与显示外观等有关系的文件。例如,你需要定义动画,菜单,样式,颜色和界面的布局,使用XML文件形式。使用应用程序资源文件,可以很容易的修改你应用的一些属性而不需要修改代码,通过可替换的资源文件集合,使你能随意的匹配各种样式的设备(就像不同的语言和屏幕尺寸)。

在你安卓项目中所包括的各种资源文件,SDK构建工具定义唯一的ID,这样你就可以在你的程序代码中引用他们。例如,如果你的应用里有个命名为logo.png的图片文件(保存在 res/drawable/ 目录下),SDK工具就会生成一个叫做R.drawable.logo的资源ID,这样你可以引用这个图片并把他加入你的用户界面里。

重要的一点就是,你需要为不同设备配置在你的程序资源里面提供各种样式的文件。例如,在XML文件中定义UI名称,你可以把这个UI名称翻译成其他语言并保存在其他文件里。这样,基于语言名称,你就可以根据你的语言设置来加载不同的语言。(如res/values-fr下的法语)。

安卓系统为可相互替换的资源文件提供了许多不同的修饰符。这些修饰符是短词,把他们包括在目录名称里,以便对不同的设备配置匹配不同的文件。另一个例子,你经常会为你不同activity基于设备的屏幕方向和大小提供不同布局。例如,当设备的屏幕是高度方向的,你可能使按钮垂直排列。但当屏幕是长度方向的,你可以定义两种布局,并根据名称来选择哪个。系统自定义提供适当的布局来匹配对应的设备。

更多的关于你的应用中可以包括的不同种的资源和如何创建根据设备配置来选择的资源文件,参阅Application Resources帮助文档。

更多相关文章

  1. CrossWalk - Android 动态加载so库文件
  2. Android经典应用程序开发
  3. Android应用程序的生命周期
  4. Android 四大组件 简介
  5. android 4.04的应用程序启动过程及与Zygote的交互(基于静态源码分
  6. Android 应用程序不能全屏显示
  7. Unexpected namespace prefix "xmlns" found for tag LinearLayo

随机推荐

  1. XML(3)XDocument与XmlDocument递归读取xml
  2. 第17天 Android(安卓)Touch事件学习 4 获
  3. XML(2)通过XmlDocument与XDocument方式写入
  4. Linux Deploy:在Android上部署Linux
  5. 走近XML(1)
  6. android 处理生命周期事件
  7. XML卷之实战锦囊(5):结构树图
  8. Android(安卓)Wifi模块学习
  9. Android(安卓)机器人遇见龙
  10. android pull 解析xml方式