Android API 学习日记----《应用程序的基本原理》

Application Fundamentals


Android的应用程序是用java语言来编写的。Android的工具包的工具编写你的代码和任何数据和资源文件一起组成一个APK文件:一个以.apk为后缀的存档文件组成安卓包。一个APK文件包含所有的安卓应用程序的所有内容并且这个文件是安卓设备用来安装应用程序的文件。


一旦安装在设备上,每个应用程序都活动在自己的安全沙箱内:

  • 这个Android操作系统是一个众多用户的linux系统,每个应用程序相当于不同的用户。
  • 默认情况下,这个系统会单独给每一个应用程序分配一个linux用户ID(只有系统能使用这个ID并且程序是不知道的,”the ID is used only by the system and is unknown to the app“有歧义的一句,看到的大神若有更好解释清指出,万分感谢)。系统会为一个应用程序中的所有文件都设置权限所以只有被分配ID的应用程序才可以访问它们。
  • 每个进程有它自己的虚拟机(VM),所以一个应用程序的代码运行是跟其他应用程序分离的。
  • 默认情况下,每一个应用程序在自己的linux进程中运行。当执行任何应用程序的组件时Android开始这个进程,然而当他不再被需要或者当系统需要在内存不充足的情况下为其他应用程序分配内存时关闭这个进程。

在这方式里,Android系统实现了最少权限的原则。也就是说,每个应用程序,默认的,这个组件只需要做它的工作而没有更多的访问。这就创建了应用程序没有相应的权限就不能不能访问系统部分的安全环境。

然而,一个应用程序之间分享数据及一个应用程序访问系统服务还是有办法的:
  • 他可能为两个应用程序分享安排相同的ID,在这个前提下,他们就能够访问对方的每个文件。节约系统资源,应用程序有相同的ID也可以安排运行在相同的进程并且共享相同的虚拟机(这些应用程序也必须签订相同的证书,即用相同的证书打包)。、
  • 一个应用程序能访问设备数据的权限例如获取用户的联系人,信息,SD卡(SD),照相机,蓝牙等等。所有的应用程序在安装的时候授权。
这包括一个应用程序如何存在于系统中的有关知识。这个文档的其余部分介绍以下:
  • 定义你的应用程序的核心组件。
  • 在表单文件中声明程序的组件和程序所需要的设备功能。
  • 资源是对立与这个程序的代码并且允许程序根据设备的配置选择相应最合适的资源。


程序组件


一个程序的组件是必要的部分。每个组件不同的点通过这些点系统能进入你的程序。对于用户和一些依赖关系不是所有的组件都是真正的切入点,但是每一个存在自己的实体和扮演各自的角色,他们每一个都是一个单独的部分来帮助你定义程序的所有行为。

这里介绍四个不同类型的组件。每一个类型提供不同的目的并且有一个单独的生命周期用来演示这个组件如何被创建与销毁。

以下是四个类型的组件:
Activities
一个Activity代表了一个单独的用户界面。举例来说,一个邮件程序可能用一个Activity来展示罗列新邮件的,另外一个用来写邮件,另外一个用来读邮件。尽管对于用户的体验来说这些Activities是在一个电子邮件程序中,实际它们每一个又是独立的个体。因此,另外一个应用程序能启动邮件程序的一个Activity(如果这个邮件程序允许它启动)。举例来说,一个照相机程序能够启动邮件程序的Activity构建一个新的邮件,为了让用户分享图片。

创建一个新的Activity必须继承Activity类,你想学习更多关于Activity,请点击Activity的开发导航。
Services
一个Service是一个在后台运行那些需要长时间的操作或者远程工作的进程。一个Service不能提供一个用户界面。例如,当用户在操作别的程序时,一个Service可能在后台播放音乐,或者也可能在不阻断用户其他操作的前提下获取网络上的数据。另一个组件,如一个Activity,可以启动一个Service运行或者绑定一个Service相互作用。

创建一个新的Service必须继承Service类,你想学习更多关于Service,请点击Service的开发导航。
Content providers
一个Content provider 管理一组程序共享的数据。你能在文件系统中存储数据,一个SQLite数据库,在web上,或者其他你的程序可以访问的地方永久存储。尽管其他程序能够查询甚至修改这个content provider(在这个content provider允许其他程序的操作的情况下)。例如,Android系统提供Content provider一个管理用户联系人的功能。因此,任何程序只要有正确的权限就能够查询并且修改一个联系人的信息(用ContactsContract.Date)。

Content provider也能读写程序的私有数据。例如,一个记事本可以用它来保存记录内容。

创建一个Content provider必须继承ContentProvider类而且如果要让其他程序执行就要实现一套API的标准。更多内容,请看ContentProvider开发导航。
Broadcast receivers
一个broadcast receiver是一个相应系统广播通知的组件。许多广播来源于系统例如屏幕关闭的通知,电量低的通知,或者拍摄一张图片的通知。程序也能发起广播例如让程序使用设备下载的数据。尽管广播不能显示在用户界面,当它们发生的时候可能通过状态栏的通知显示给用户。更常见的,虽然,广播相对于其他的组件只有很小的工作量。举个实例,它可能基于事件来启动一个Service执行一些工作。

创建一个broadcast receiver必须继承BroadcastReceiver类而且每一个广播传递一个Intent对象。更多内容,请看BroadcastReceiver类。

Android系统设计的一个独特的方面任何程序都能开始另外一个程序的组件。例如,如果你想用系统的相机拍照,这很有可能是另外一个程序来做这个拍照功能并且你的程序来使用,而不是需要你自己开发一个Activity来获取照片。你不需要合并或者用代码连接到相机程序。相反的,你能简单的启动相机程序的活动来拍照。完成时,照片会返回到你的程序上,因此,你就可以使用它了。对于用户来说,好像你的程序是包含相机部分的。

当系统启动一个组件,程序会启动进程(如果它尚未运行)并且实例化所需要的组件类。例如,如果你的程序调用相机照相,这个活动运行所在的进程是属于相机程序的,并不在你的程序里。因此,大多的程序在其他系统上,Android的程序不止有一个入口点(没有man定义,例如)。

因为在系统中,每个程序都运行在一个单独的线程上并且没有访问其他应用程序的权限,你的程序不能直接启动其他程序的组件。但是在Android系统中你的程序可以的直接激活其他程序的组件,你必须给系统发送一个信息告诉它,你想启动一个特殊的组件。系统就会为你启动这个组件。

启动组件

上面四大组件中的三种Activity、service和broadcast receiver通过一个异步的消息调用一个意图来启动。在运行时,意图和组件相互结合(你能认为它们是组件活动间的信使),不管这个组件是属于你的程序还是其他的程序。

一个意图的创建需要一个Intent对象,它用来定义一个信息启动任一一个特定的组件或一个指定类型的组件--一个意图有显性或者印象的分别。

为了Activities和Services,一个意图定义一个活动来执行(例如,到视图或者发送一些东西)并且可能在它(intent)上指定数据的URI(除了其他事项,这个可能需要知道启动的组件)。例如,一个意图可能传达一个要求一个Activity用来显示一个图片或者开启一个网页。在某些情况下,你能开启一个Activity来接收结果,在这种情况下,这个Activity也返回结果在意图里(例如,你能发送一个意图让用户选择一个联系人并且这个意图返回一个含有被用户选择的联系人的URI给你)。

对于BroadcastReciever,意图简单定义通知(例如设备电量低只需要发送一个“battery is low”字符串即可)。

另外一个content provider不用intent启动。比较之下,它只针对来自ContentProvider的请求。内容解析器处理所有与content provider的直接交互因此组件和提供者执行交互不需要调用ContentProvider对象的方法。在组件与ContentProvider之间有个抽象层来请求信息(安全性)。

这里还有别的方法启动组件:
  • 你启动一个Activity(或者让它做一些新的事情)通过一个意图的startActivity方法或者startActivityForResult()(当你想Activity返回结果)。
  • 你启动一个service(或者给一个正在运行的service新的指令)通过一个意图的startService。或者你通过bindSevice绑定service。
  • 你开始一个broadcast通过Intent的方法如sendBroadcast,sendOrderedBroadcast或者sendStickyBroadcast。
  • 你可以通过contentResolver的query方法执行一个内容查询。
更多使用intent的详情,请看intents and Intent Filters文档。更多启动指定组件的详情也可以看一下文档:  ActivitiesServices, BroadcastReceiver 和 Content Providers

清单文件

在Android系统开始一个程序之前,系统必须查看程序的表单文件确定组件存在(manifest file)。你的程序必须在这个文件里声明它所有的组件,在程序的根目录。

清单文件除了声明组件还有能做其他很多事情,例如:
  • 确定程序要求的所有权限,例如访问网络权限或者读取用户联系人的权限。
  • 声明程序要求的最小的API等级,在这个AOL等级智商的设备才可以使用。
  • 声明程序锁要求的硬件和软件的功能,例如照相机、蓝牙、服务器或者多点触屏。
  • 程序的依赖关系需要跟程序关联(其他android框架的API),例如谷歌地图的库。
  • 更多
声明组件
清单文件的主要部分告知系统关于程序的组件。例如,一个清单文件声明一个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属性指定Activity子类完全合格的类型并且这个android:label属性指定一个字符串作为Activity用来显示的用户标签。

你必须用以下方法声明程序所有的组件:
  • Activities的元素为<activity>
  • services的元素为<service>
  • broadcast receivers的元素为<receiver>
  • content providers的元素为<provider>

你程序中的Activities,services和content providers没有在清单文件中声明的话,系统是看不到的 ,所以不能运行。然而broadcast receivers可以声明在清单文件中也可以在代码里动态创建(像broadcast receiver对象)且系统注册调用registerReciver()方法。

想了解更多程序的清单文件的结构,请看AndroidManifest.xml。

声明组件的规定
在讨论如何启动组件之前,你能用Intent启动activities,services和broadcast receivers。你能在intent明确的命名目标组件(用这个组件的类型名字)。然而,意图真正的实力在于隐藏意图。一个隐藏意图简单的操作活动的类型(并且,可选,数据上,你在活动想执行的活动)并且允许系统上找到且启动一个能执行活动的组件。如果意图有若干能执行活动的组件,那么用户可以选择用哪一个。

系统能识别组件并且响应意图是通过设备上其他应用的清单文件 提供的意图接收器intent filters。


当你在清单文件中声明一个Activity时,可以在它中选择定义意图过滤器来响应其他程序的意图。你能为你的组件声明一个意图过滤器,在组件声明可选元素中添加一个<intent-filter>元素。

例如,如果你创建一个邮件程序来编写新邮件,你能声明一个意图过滤器相应发送意图(发送新邮件的命令)如下:
<manifest ... >
    ...
    <application ... >
        <activity android:name="com.example.project.ComposeEmailActivity">
            <intent-filter>
                <action android:name="android.intent.action.SEND" />
                <data android:type="*/*" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>
</manifest>

那么,如果其他的程序创建一个ACTION_SEND的意图并且通过它的startActivity(),系统会开启你的程序界面让用户来发送邮件。

想了解更过关于意图过滤器的详情,请看Intents and intent Filters文档。

声明程序规定
Android有不同的供电设备并不是它们所有的都提供相同的功能和规定。为了防止不适合的程序安装在你的设备上,明确的定制一个你的程序支持的配置文件是非常重要的,在你的清单文件中要申明设备和软件的要求。大部分的声明仅供参考,系统不读它们,但是外部服务如google play读它们,当用户为自己的设备搜索程序的时候用来过滤。

例如,如果你的程序响应照相机并且用户的手机支持的最低android系统是2.1,你可以再清单文件中这么声明:
<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>
现在,设备没有照相机并且手机系统等级地狱2.1,则不能从Google play 安装你的程序。

然而,也能声明你的程序用照相机,但是不能要求它。在这种情况下,你的程序必须设置required属性为false并且在运行时检查设备是否有照相机并且取消所有的拍照功能比较合适。
 
关于更多如何管理程序的兼容性适应不同的设备情参考Device Compatibility文档。

程序资源

一个程序不仅仅全是代码还有资源,程序资源是与源代码分开的。例如图片,音频文件和任何程序中可见的。例如你用XML文件定义一个动画,菜单,样式,颜色和用户界面的布局。更新程序的各种新特性用资源是容易的,不需要修改代码,并且设置替代资源适配不通风的设备优化你的程序(例如不同语言和屏幕尺寸)。

你的项目包含的每个资源,sdk工具会给它定义一个独一无二的id方便在你的程序代码中引用或者在xml中定义。例如如果你的程序还有一张名叫logo.png的图片(放在res/drawable文档下),sdk工具则会为它创建一个id叫R.drawable.logo.png,你能在用户界面中通过这个id来引用这张图片。

最重要的方面资源与源码是分开的功能可以让你的程序适配不同的设备。例如,在xml中定义字符串,你能用任何语言翻译这个字符串并且在分开的文件保存他们。那么,你可以根据不同语言设定资源目录的名字(例如法语的就是res/values-fr/)和用户语言的设定,系统会设定适当的语言为你的UI。

Android支持许多不同的限定词为你的可选资源。限定词是一个资源目录的名字可以包含的用来设定设备配置的那些短字符串。举另外一个例子,你常常为你的Activity创建不同的布局,定义这个屏幕的方向和尺寸。例如竖屏时你可能希望带很多按钮的布局的是垂直排列的,横屏时,你又想这些按钮是水平排列。去改变屏幕的尺寸,你能定义两个不同布局并且给每个布局目录取适当的名字。那么,系统会根据当前设备的尺寸自动采用合适的布局。

关于程序包含的更多种类的资源、如何为不同的设备创建配置适当的资源,请阅读Providing Resources。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值