博客出自:http://blog.csdn.net/liuxian13183,转载注明出处! All Rights Reserved !
学习安卓,不得不知的基础部分,请详细阅读
Android 使用Java语言开发。Android SDK 工具编译代码—以及任意数据并连同相关资源打包进一个Android 包内,它是一个以.apk
为后缀的压缩文件。 一个 .apk
文件中的 所有代码就是一个程序。这个.apk文件就用于在Android设备上安装这个程序。
一旦安装成功,这个Android程序就拥有了自己独立的运行沙盒(沙盒是在受限的安全环境中运行应用程序的一种做法,这种做法是要限制授予应用程序的代码访问权限。):
通过这种方式,Android 系统实现了 最少特权原则。就是说,每一个应用程序,默认地,都只能调用它所需要的工作组件。 这就创造了这样一种非常安全的环境,在这个环境中,一个应用程序不能访问没有被授予其权限的系统部分。
尽管如此,也有很多途径可以让一个应用程序和其它的应用程序共享数据,也可以让一个应用程序去调用系统服务:
以上概括了一个Android程序在系统中的存在方式。接下来将介绍:
组件是一个Android程序至关重要的构建模块。每一个组件都是系统进入你的应用的不同途径。但并不是所有的组件都是用户进入程序的真实入口,其中一些要依赖于其它组件, 但是每一个组件都以自己独有的形式存在,并发挥特殊的作用;每一个组件都是一个唯一的模块,帮助你实现程序的各种行为。
有四种不同的应用程序组件。每一种组件都有其唯一的目的并且有独有的生命周期,这个生命周期定义了附件被创建和销毁的方式。
下面介绍四种类型的应用程序组件:
一个activity作为 Activity
的一个子类被实现。 你也可以通过 Activities开发者指南来了解更多。
一个service作为一个Service
的子类被实现。你可以通过 Services 开发者指南了解更多。
ContactsContract.Data
) 去读写某人的信息。
Content provider在读写程序的私有数据时也很有用。例如,Note Pad 范例程序就使用了一个content provider来保存笔记。
一个content provider是作为ContentProvider
的一个子类被实现的。 并且必须实现一些标准的API集,这样其它的应用程序才能执行事务。更多信息,请查阅 Content Providers开发者指南。
broadcast receiver是BroadcastReceiver
的子类实现,而且每一个广播通过Intent
对象来传递。 更多信息,请阅读 BroadcastReceiver
类。
Android系统设计的一个独特方面是,任何程序都可以启动其它程序的组件。 例如,如果你想让用户使用设备相机捕捉一个相片,有另外一个程序做这件事,那么你的程序将可以调用它, 而不是你自己开发一个拍照的activity。你不必从相机程序中嵌入代码或者连链接代码也不需要。取而代之地,你可以简单地启动相机程序中拍照的activity。 当拍照完成,相片就会返回给你的程序供你使用。从用户的角度,就好像相机就是你程序的一部分。
当系统启动一个组件,它其实就启动了这个程序的进程(如果这个进程还未被启动的话)并实例化这个组件所需要的类。 例如,如果你的程序启动了相机程序里的activity去拍照,这个activity实际上是运行在相机程序的进程里,而不是你自己的进程。 因此,不像其它系统里的程序,Android程序并不是单入口的(例如它没有main方法)。
由于系统把程序运行在一个个独立的进程中,并使用文件权限来限制对其它程序的访问,所以你的程序不能从其它程序中直接激活组件。 尽管如此,Android系统可以做到!激活一个其它程序的组件,你必须向系统发送一个信息,这个信息需要指定你的intent 来启动一个指定的组件。 然后系统就会为你激活这个组件。
四分之三的组件类型—activitie, service, 和 broadcast receiver—是被一个叫做 intent的异步消息激活的。 Intent把不同的独立的组件在运行期绑定在一起(你可以把它们当作从其它组件中请求动作的消息), 无论这些组件属于你的或者其它的程序。
一个intent使用一个Intent
对象来创建, 它用于激活一个指定的或者指定类型的组件。— 一个intent可以分别是显示的或者隐式的。
对于activity和service来说,一个intent定义了将要执行的动作。(例如, 查看或发送什么)并且可以指定动作执行需要的数据URL(启动组件所需要知道的其它数据)。 例如,一个intent可能发送一个请求,让一个activity去显示一张图片或打开一个网页。 某些情况下,你可以启动一个activity来接收一个结果,此时,这个activity也通过一个Intent
来返回结果。 (例如, 你可以发送一个intent让用户获取一个个人联系人,并让这个结果返回给你—返回的intent就包含了一个指向你选择的联系人的URI)。
对broadcast receiver来说, intent只是简单地定义了需要广播的公告(例如,一个指明设备电池电量低的广播就只包含了一个已知的动作字符串:“电量低”)。
另外一个组件类型, content provider, 不是用intent来激活。 相对地,它是由一个 ContentResolver
发起的一个指向它的请求激活的。 这个content resolver掌握了所有content provider的直接事务,所以用这个provider来执行事务的组件不需要直接执行而是调用这个 ContentResolver
对象的方法。 它在content provider和这个组件请求信息之间放置了一个抽象层(为了安全)。
激活各种类型组件有不同的方法:
Intent
给startActivity()
或者startActivityForResult()
(当你想让一个activity为你返回一个结果)。Intent
给startService()
。 或者你可以绑定一个服务通过传递一个Intent
给 bindService()
。Intent
给一些方法像 sendBroadcast()
,sendOrderedBroadcast()
, 或者 sendStickyBroadcast()
。ContentResolver
的query()
方法。 想要了解更多关于intent的信息, 查阅 Intent和Intent Filters 文档。 更多信息关于激活特定的组件包含在下述文档中: Activities, Services, BroadcastReceiver
和 Content Providers.
在Android系统能够启动一个程序组件之前, 系统必须通过读取程序的AndroidManifest.xml
文件 ("配置"文件)来知道这个组件是否存在。 你的程序必须在这个文件中声明它所有的组件。这文件必须放在程序项目的根目录中。
除了声明程序组件外,这个配置文件还做一些其它的工作,例如:
配置文件的主要任务是通知系统,该应用程序都使用了哪些组件。 例如,一个配置文件可以这样声明一个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的用户可见标签的字符串。
你必须像这样声明所有的组件:
<activity>
activity的元素<service>
service的元素<receiver>
broadcast receiver的元素<provider>
content provider的元素 你包含在你程序中但并没有在配置文件中声明的Activitie, service, 和 content provider 是不被系统识别的,因此,也无法运行。但是, broadcast receiver既可以在配置文件中声明,也可以在代码中被动态创建(作为BroadcastReceiver
对象) 并且通过调用 registerReceiver()
注册于系统中。
想要学习更多如何搭建你程序的配置文件, 查阅 AndroidManifest.xml 文件 文档。
如前文 激活组件的讨论中所说, 你可以使用一个Intent
来启动一个activitie, service, 和 broadcast receiver。你可以明确地(使用组件的类名)在intent中声明一个目标组件。 但是, intent最牛逼的地方其实是它的动作(action)概念, 使用action,你可以简单地描述以下你想执行的动作(并且你也可以指定你想把哪些数据放在这个动作上) 并且允许系统去寻找设备上可以执行这个动作的组件并启动它。如果有多个组件可以执行这个动作,那么由用户来决定哪个去执行。
系统识别能够响应intent的组件的方法是比较收到的intent和设备的其它程序的配置文件中的intent filters
你在程序的配置文件中声明组件的时候,你就可以选择性地包含intent过滤器来声明组件的功能,这样它就能响应由其它程序发起的intent。 你可以通过添加一个<intent-filter>
作为你组件的子元素 来为你的组件声明一个intent过滤器。
例如,一个包含编辑新邮件页面的邮件程序可能要在配置文件中声明一个intent过滤器,以此作为入口来响应“发送”intent(为了发送邮件)。 你程序中的一个Activity就要创建一个包含"发送"动作(ACTION_SEND
) 的intent,这样系统在你通过startActivity()
调用了这个intent时就去比较邮件程序的“发送”页面然后启动它。
更多关于创建intent过滤器,查看Intents和Intent Filter 文档。
Android设备多种多样,并不是所有的都提供了相同的特性和能力。 为了避免不满足你程序要求的设备去安装,你有必要清楚地在配置文件中声明设备和软件要求以定义哪些设备是你的程序支持的。 这些声明多数只是参考信息,系统并不去读取他们。但是额外的程序例如google play会为了筛选用户对应用程序的搜索。
例如,如果你的程序需要相机,并且使用了Andriod 2.1介绍的api (API Level 7), 你就应该在配置文件中声明这些要求。这样的话,没有相机且Android版本低于2.1的就不能从Google Play中安装你的程序。
尽管如此,你也可以声明你的程序使用相机,但是不是硬性 要求 。这种情况下,你的程序必须在运行时执行一个校验,判断设备是否有相机功能,并且在没有相机的设备上禁用一切使用相机的特性。
下面有一些当你在设计和开发应用时需要考虑的设备特征:
屏幕尺寸包括: small, normal, large, 和 extra large.
屏幕像素密度包括: low density, medium density, high density, 和 extra high density.
默认地,你的应用程序可以适配所有尺寸和像素密度的屏幕,因为Android系统会对你的ui布局和图像资源做合适的调整。 尽管如此,你应该为特定的屏幕尺寸创建专门的布局,为特定的像素密度提供专门的图像资源。你要使用可选的布局资源,还要用 <supports-screens>
元素在配置文件中精确声明你的程序所支持的屏幕尺寸。
更多信息,请查阅 支持多屏幕 文档。
<uses-configuration>
元素来声明。 尽管如此,很少由程序需要声明一个特定的输入配置。
<uses-feature>
元素 来为你的程序使用到的特性加以声明。
<uses-sdk>
元素来声明。
你为你的应用声明这些需求是很有必要的,因为当你在Google Play上发布应用时,它会根据这些声明来过滤出哪些应用时适用于这些设备的。 因此,你的程序也应该仅仅适用于满足于你程序的需求的设备。
关于google Play如何根据这些(以及其他)要求筛选应用,请查看Google Play上的筛选 文档。
一个Android 应用不仅仅由代码构成,—它也需要由代码分隔的资源文件,例如图片,音频文件,以及任何与程序可见内容相关的东西。例如,你应该定义动画,菜单,风格,颜色以及由XML文件描述的用户交互页面的布局。 使用程序资源使得你修改很多程序特征变得很容易,同时你不必去修改代码。—而且通过提供可选择的资源集合,— 也使你能够为不同的设备配置优化程序(例如不同的语言和屏幕尺寸)。
SDK搭建工具为Android项目使用到的每一个资源定义一个整型的ID,你可以通过这个ID获得代码中的资源或者XML中的其它资源的引用。 例如,如果你的程序包含了一个名叫 logo.png
(保存在 res/drawable/
目录下)的图片文件, SDK工具生成一个叫做R.drawable.logo
的资源ID, 你可以用这个ID引用那个图片并把它添加到你的用户交互中去。
提供源代码分隔的资源的一个重要能力是为不同的设备配置提供可选择的资源。 例如,在XML中定义UI的字符串,你就可以把这些字符串翻译成其它的语言,并在分隔的文件中保存。 然后,根据一个你追加到资源目录名中的语言修饰符(例如res/values-fr/
是法语字符串的值)和用户对语言的设置, Android系统就会提供适当的语言字符串到你的UI中。
Android支持很多不同的修饰符以支持可选的资源。这些修饰符是被加入到资源目录名中的简短字符串。这样定义是为了 定义设备的特定配置,以保证这个目录下的资源可能会被使用到。比如另外一个例子,你可能会因为设备的屏幕方向和尺寸为activity 创建不同的布局。例如,当屏幕是竖着的时候(高),你可能想要上下排列的一组按钮,而当屏幕横着的时候(宽),你就希望这些按钮水平排列。 改变布局的方式取决于屏幕的方向,你可以定义两种不同的布局,然后为每一种布局的目录名加上一个合适的修饰符。然后,系统就会根据当前屏幕 的方向来请求合适的布局。
关于更多你的程序可以导入的不同类型的资源以及怎样为不同的设备配置创建可选的资源,请查阅 应用程序资源开发者指南。