Android应用程序开发笔记之Fundamentals
在Android系统上安装了一个应用程序之后,该应用程序就会有一个它自己的安全沙箱:
- Android操作系统是一个多用户的Linux系统,每个应用程序就是其中的一个用户
- 每个进程一个虚拟机(VM),所以应用程序间的代码运行是相互独立的。
- 默认地,系统分配每个应用程序一个唯一的用户ID(用户ID只对系统可见,对应用程序来说是不可见的)。系统会对应用程序的文件设置权限,只有拥有该应用程序的用户ID才可以访问这些文件。
- 默认地,每个应用程序运行在它自己的Linux进程。系统在需要用到应用程序组件时开启进程,在不再需要用到应用程序或需要为其他应用程序回收系统资源时结束进程。
- 两个应用程序可以共用相同的Linux用户ID,那么它们就可以互相访问各自的文件。为了节省系统资源,带相同用户ID的应用程序也可以运行在相同的Linux进程和相同的VM(应用程序间必须签名相同)
- 应用程序可以请求权限访问设备的数据,像联系人,SMS短信,SD card,摄像头,蓝牙等等。所有权限必须在安装的时候授与应用程序。
应用组件
Activities:一个activity描绘了一个单独的用户界面。例如:一个email的应用程序会有一个activity显示email列表,一个activity编辑email,一个activity查看email的内容。虽然这些activity结合起来形成非常好的用户体验,但每个activity是独立的个体。所以,其他的应用程序可以运行这些activities中的一个(如果email应用程序允许的话)。例如,一个camera应用程序可以启动email应用程序的activity来编辑一封带刚刚照的照片的新的email。
Services:service是运行在后台来完成一个长期运行的操作或为完成远程进程的工作。service没有用户界面。例如:service可以在后台播放音乐的时候,用户可能在使用其他的应用程序,或者service通过网络获取数据的过程中不会妨碍用户与activity的交互。其他的像activity的组件,可以开启或绑定service。
service是通过继承Service来实现的。
激活组件
有以下方法来激活组件:
- activity可以通过传递一个Intent给startActivity()方法来激活(或传达新任务给activity),或startActivityForResult(Intent intent,int requestCode)来激活一个有返回结果的activity。
- service可以通过传递一个Intent给startService()方法来激活(或传递新的信息给一个正在运行的service),或者通过bindService()方法绑定service。
- 创建广播事件可以通过传递一个intent给sendBroadcast()、sendOrderedBroadcast()或sendStickyBroadcast()方法。
- 调用ContentResolver的query()方法来完成数据查询。
Manifest文件
android系统在激活一个应用组件之前,必须通过读取应用程序AndroidManifest.xml文件来获知该应用程序是否包含有该应用组件。你的应用程序必须在应用根目录下包含有AndroidManifest.xml文件,并声明所有需要用到的应用组件。
manifest文件除了声明组件外,还有以下用途:
- 鉴别应用程序请求的用户权限,像网络访问权限或读写访问用户联系人。
- 声明应用程序使用的最低的API版本
- 声明需要使用的或应用程序必须用到的硬件和软件特征,像摄像头,蓝牙服务,多触点触摸屏。
- 应用程序需要用的到API库(非Android framework APIs),像Google Maps library.
声明应用组件
manifest文件的主要任务是告诉系统应用程序有些什么应用组件。例如,manifest文件可以如下声明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>
- activity:<activity>
- service:<service>
- broadcast receivers:<receiver>
- content provider:<provider>
声明组件的功能
像上面所说的,在activity组件中,你可以通过Intent来激活activity,service和broadcast receiver。Intent可以明确地指定全限定类名的应用组件。然而,真正强大的intent依赖与intent的action(以后称为:动作)的概念。你可以简单地指定你想要完成的动作(还可以指定完成该动作所需的数据)并要求系统去找能完成该动作的应用组件并激活它。如果会有多个应用组件可以完成该动作,那么会让用户选择一个来运行。
应用程序通过对比接收到的intent与各应用程序在manifest文件中声明的intent filters来确定哪些组件可以响应这个动作。
当你在manifest中声明应用组件的时候,你也可以通过intent filter 来声明组件的功能。你可以在manifest的应用组件元素下添加<intent-filter>元素来声明intent filter。
例如,email应用程序中的编辑email的activity可以声明intent filter来响应带"send"动作的intent。那么你的应用程序可以创建一个带"send"动作的intent,来激活email程序的activity。
声明应用程序的要求
android系统可以支持很多不同的硬件设备,但这些设备未必有相同的功能或特征。为了防止你的应用程序安装在一个缺少设备特征功能的环境下,你可以在manifest中明确地声明设备和软件要求。这些声明只是一些文字信息,系统也不会读取他们,但一些额外的service,像Android Market,会读取他们,为用户过滤掉一些不适合他们设备的应用程序。
例如,如果你的应用程序需要用到摄像头和基于Android 2.1 API,你可以声明这些要求在你的manifest文件。这样的话,一台没有摄像头的,android版本低于2.1的机器将不能从Android Market安装你的应用程序。
然而,你也可以声明你的应用程序需要用到摄像头,但不是必须的。在这种情况下,你的应用程序必须在运行时检查机器是否带有摄像头,如果机器不带摄像头,那么禁用摄像头那部分的功能。
在你设计开发你的应用程序的时候,你需要考虑一下下面的一些重要的设备参数:
- 屏幕大小和分辨率:Android定义了屏幕大小与分辨率这两个参数来将设备归类。为了简化所有不同类型的屏幕配置,Android系统把它们概括成几个组。屏幕大小分为:small,normal,large和extra large。屏幕分辨率分为:low density,medium density,high density和extra high density。默认地,你的应用程序兼容所有的屏幕大小与分辨率,因为android系统会自动地调整你的UI层和图片资源。然而,你需要为某些屏幕大小提供特定的层和为某些分辨率提供特定的图片,并在manifest中通过<supports-screens>元素声明你的应用程序支持多大的屏幕。
- 输入配置:不同的设备提供了不同类型的用户输入机制,像物理键盘,追踪球或five-way navigation pad。如果你的应用程序要求一个特殊类型的输入硬件,那么你需要在你的manifest中用<uses-configuration>元素声明。不过,很少应用程序要求一个特定的输入配置。
- 设备特征:有些机器可能会没有一些软硬件的特征,像摄像头,光感应,蓝牙,某个版本的OpenGL或屏幕的准确度。因此你需要在manifest中使用<uses-feature>元素声明设备特征。
- 平台版本:在manifest中通过<uses-sdk>元素声明最低的API版本。
应用程序的资源
android应用程序并不只有代码,还有其他的资源,像图片,声音文件等。例如,你需要定义动画,菜单,样式,颜色值,布局。使用应用程序资源可以在不修改源码的情况下轻松地更改应用程序的许多特征。