zoukankan      html  css  js  c++  java
  • Android开发-API指南-应用程序开发基础

    Application Fundamentals

    英文原文:http://developer.android.com/guide/components/fundamentals.html
    采集(更新)日期:2015-05-11
    搬迁自原博客:http://blog.sina.com.cn/s/blog_48d491300101h41p.html

    Android 应用程序是用 Java 语言编写的。Android SDK 工具软件会把代码—连同数据、资源文件—一起编译并放入 APK 中: Android 包中,这是个后缀为.apk的打包文件。 APK 文件包含了 Android 应用程序所需的全部内容,同时也是在 Android 设备上安装该应用所用到的安装文件。

    安装完成后,每个 Android 应用程序就独立运行于各自的安全沙盒(sandbox)中:

    • Android 操作系统是一个多用户的 Linux 系统,其中的每个应用程序都是一个独立的用户。
    • 默认情况下,系统将给每个应用程序赋予一个唯一的 Linux 用户 ID(该 ID 仅供系统使用,对于应用程序是不可见的)。 系统将对应用程序中的所有文件分配权限,只有赋予该应用程序的用户 ID 才能访问这些文件。
    • 每个进程都拥有自己的虚拟机(VM),因此不同应用程序的代码是相互独立运行的。
    • 默认情况下,每个应用程序运行于自己的 Linux 进程中。 每当需要运行应用程序的某个组件时,Android 就会启动进程,并在不再需要时或必须为其他应用程序腾出内存时关闭进程。

    这样,Android 系统实现了最小权限原则。也就是说,每个应用程序默认只访问必要的组件。 这就建立了一种非常安全的环境,使得应用程序无法访问未授权的系统内容。

    不过,应用程序还是有很多方法与其他应用程序共享数据或访问系统服务的:

    • 可以让两个应用程序共享同一个 Linux 用户 ID,这样它们就可以相互访问文件了。 为了节省系统开销,用户 ID 相同的应用程序还可以运行于同一个 Linux 进程中,并且共享同一个 VM(这些应用程序必须由同一个证书签名)。
    • 应用程序可以申请访问设备数据的权限,诸如用户通讯录、短信、可挂载存储(SD卡)、摄像头、蓝牙等等。 应用程序的全部权限都必须在安装时经过用户授权。

    上面简述了 Android 应用程序是如何在系统中运行的。本文剩余部分将介绍:

    • 建立应用程序所需的主要组件。
    • 用于声明组件和所需硬件的 Manifest 文件。
    • 与代码分离的资源,以便应用程序可以根据硬件配置优化运行方式。

    应用程序组件

    组件(Component)是搭建 Android 应用程序的基础模块。 每个组件都是一个独立的入口,系统可以通过它们进入应用程序。 不是每个组件都是可供用户使用的入口,有些组件是相互依存的,但每个组件都运行为一个实体并发挥各自的作用—每个组件都是唯一的应用程序模块,为应用程序的整体表现出力。

    应用程序组件分为四种类型。每类组件实现不同的目标,拥有各自从创建到消亡的生命周期。

    下面介绍这四种类型的应用程序组件:

    Activity
    Activity代表一个包含了用户界面的屏幕(窗口)。 比如,一个 Email 应用程序可能会包含一个显示未读邮件列表的 Activity、一个撰写邮件的 Activity 及一个阅读邮件的 Activity。 虽然该 Email 应用程序由多个 Activity 一起构成了完整的用户体验,但是每个 Activity 都是相互独立的。 因此,另一个应用程序可以启动其中任意一个 Activity(如果该 Email 应用程序允许的话)。 例如,为了能让用户分享照片,某个拍照应用可以启动该 Email 应用程序的 Activity 来撰写一封新邮件。

    Activity 实现为Activity对象的一个子类, 更多内容请参阅开发指南中的Activity

    服务
    Service 是一种后台运行的组件,用于执行运行时间较长的操作,或是为远程进程提供服务。服务不提供用户界面。 例如:当用户使用其他应用程序时,服务可以在后台播放音乐,或者可以通过网络下载数据,这些都不需要用 Activity 与用户进行交互。 Activity 之类的其他组件可以启动并运行服务,也可以与之绑定以便交互。

    服务是作为 Service 对象的子类来实现的,你可以在开发指南的 Services 中了解更多内容。

    Content Provider
    Content Provider 管理着某个可共享的应用程序数据集。 数据可以存放在文件系统、SQLite 数据库、Web,或其他任何应用程序可访问的持久性存储中。 其他应用程序可以通过 Content Provider 查询甚至修改数据(如果 Content Provider 允许的话)。 例如,Android 系统就提供了一个管理用户通讯录信息的 Content Provider。 因此,任何拥有相应权限的应用程序都可以查询该 Content Provider 里的数据(比如 ContactsContract.Data), 以便读写某个联系人的信息。

    对于读写应用程序的私有数据而言,Content Provider 也很有用。 比如,例程 Note Pad 就使用了一个 Content Provider 来保存笔记。

    Content Provider 实例化为 ContentProvider 的子类,且必须实现一组标准的 API,以便其他应用程序能提交事务。 详情请参阅开发指南的 Content Providers 部分。

    广播接收器
    广播接收器 是一种响应系统级广播的组件。 很多广播都来源于系统 — 比如屏幕已关闭、电池电量低、拍了一张照片等。 应用程序也可以发起广播 — 比如通知另一个程序所需数据已经下载到本地设备并已可用。 尽管广播接收器不显示用户界面,但在广播事件发生时它可以 创建一条状态栏通知来通知用户。 不过,更多时候广播接收器仅仅是充当其他组件的“入口”,只完成很少量的工作。 比如,它可以初始化一个服务以便完成某个事件对应的任务。

    广播接收器实例化为 BroadcastReceiver 对象的子类,每条被分发的广播都是一个 Intent 对象。详见 BroadcastReceiver类。

    Android 系统有一条独特的设计,就是任何应用程序都能启动其他应用程序的组件。 例如,假设需要使用摄像头拍照,而其他应用程序已经实现了这一功能,则可以直接使用,而不需要再自行开发一个 Activity 来完成拍照功能。 这不需要包含摄像头应用的代码,甚至都不需要链接代码,只要启动摄像头应用中的拍照 Activity 即可。 拍摄完成后,照片甚至都会直接返回给调用方应用以便使用。 对于用户而言,摄像头应用就像是调用方应用中的一部分一样。

    当启动一个组件时,系统会启动相关应用程序的进程(如果该程序还未运行的话),并且实例化组件所需的类。 例如,当启动了摄像头应用中的拍照 Activity 时,该 Activity 运行于摄像头应用的进程中,而不是在调用方应用的进程中。 因此,与其他大多数系统不同,Android 应用程序不存在一个单一的入口点(比如没有main()函数)。

    因为系统把每个应用程序都放入相互独立的进程中运行,文件权限就限制了对其他应用的访问,所以不可能直接启动其他应用的组件。 但是 Android 系统可以启动其他应用程序的组件。因此,如果要激活其他应用的组件,必须向系统发送一条消息,其中指定了要激活某个组件的 Intent。 然后,系统就会启动该组件。

    启动组件

    在四种类型的组件中,有三种 — Activity、服务和广播接收器 — 都是由名为 Intent 的异步消息启动的。 在运行时, Intent 与某个组件相互绑定(可以将它们视为其他组件发出的执行某个操作的请求消息),这与组件属于哪个应用没有关系。

    Intent 是用 Intent 对象创建的,定义了一个激活某个或某组件(分别对应显式或隐式的 Intent )的消息 。

    对于 Activity 和服务而言,Intent 定义了所要执行的操作(比如:“查看”或“发送”),并可以指定数据的 URI(被启动的组件可能会需要知道) 例如,某 Intent 可能会发送一个请求,要让某个 Activity 显示一张图片或者打开一个网页。 有时需要启动一个 Activity 并接收其结果,这时 Activity 还需要在 Intent 中返回结果(例如,发送一个 Intent 让用户选取某个联系人并返回数据 — 返回的 Intent 包含了一个指向选中联系人数据的 URI)。

    对于广播接收器而言,Intent 只是简单地定义了要广播的消息 (例如,一条表示电量不足的广播可以仅包含一个“电量不足”字符串。

    剩下的一类组件 Content Provider,不是由 Intent 启动的。而是由 ContentResolver 发出的请求来激活的。 Content Resolver 负责处理 Content Provider 所有的事务,因此需要执行事务的组件不需要去调用 ContentResolver 对象的方法。这样就在 Content Provider 和请求数据的组件之间建立一个抽象层(出于安全考虑)。

    每种组件都有各自的激活方法:

    关于 Intent 的更多信息,请参阅文档 Intents 和 Intent 过滤器。 关于激活组件的更多信息,在以下文档中也有涉及: Activity服务BroadcastReceiverContent Provider

    Manifest 文件

    在启动一个应用程序组件之前,Android 系统必须知道组件是否存在,这是通过读取应用程序的 AndroidManifest.xml 文件(“Manifest”文件)来实现的。 该文件必须位于项目的根目录,应用程序必须在该文件中声明所有的组件。

    除了声明应用程序组件之外,Manifest 文件还有其他一些用途,比如:

    • 标记应用程序所需的用户权限,如访问 Internet 或 读写用户通讯录
    • 声明应用程序需要的最低版本 API Level ,应用程序依赖于该版本的 API。
    • 声明应用程序的的硬件和软件需求,诸如:摄像头、蓝牙服务和多点触屏。
    • 应用程序需要链接的 API 库(Android 系统 API 之外的库),如: 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>
    

    <application> 元素中,android:icon 属性指向了一个标识该应用程序的图标资源,。

    <activity> 元素中, android:name 属性设定了 Activity 子类的完全限定(fully qualified)类名, android:label 属性设定了一个用作 Activity 标题的字符串。

    必须按照以下规则声明应用程序的全部组件:

    如果你的代码中用到了某些 Activity、服务和 Content Provider,但没有在 Manifest 文件中声明,那么系统是无视这些组件的,因此它们也就无法生效。 不过,广播接收器既可以在 Manifest 文件中声明,也可以用代码动态创建( 创建为 BroadcastReceiver 对象)并用 registerReceiver() 进行注册。

    关于构建 Manifest 文件的更多信息,请参阅文档 AndroidManifest.xml 文件

    声明组件的兼容性

    正如 启动组件 部分所述,可以用一个 Intent 来启动Activity、服务和广播接收器。可以在 Intent 中使用显式命名的目标组件(用组件的类名)启动 Intent。 不过,Intent 真正的强大之处在于 隐式 Intent 的理念。 隐式 Intent 只要说明需执行的操作类型即可(还可附带操作所需的数据),系统籍此在设备上查找可执行此操作的组件并启动之。 如果同时有多个组件都可以执行此操作,则由用户选用一个。

    通过将接收到的 Intent 和其他应用程序的 Manifest 文件中的 Intent 过滤器 进行比较,系统识别出可以响应该 Intent 的组件。

    当在应用程序的 Manifest 文件中声明 Activity 时,可以包含 Intent 过滤器,用于声明该 Activity 可以响应来自其他应用程序的 Intent。 通过在组件声明节点下添加一个子节点 <intent-filter> ,可以为该组件声明一个 Intent 过滤器。

    例如,假设建立了一个 Email 应用程序,其中包含一个撰写新邮件的 Activity,这时就可以声明一个响应”send“ 类型 Intent(用于发送新邮件)的 Intent 过滤器如下:

    <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 类型的 Action,并传给 startActivity(), 系统就可以启动上述 Activity,用户就可以起草并发送一封 Email 了。

    关于创建 Intent 过滤器的更多信息,请参阅文档 Intent 和 Intent 过滤器

    声明应用程序需求

    Android 支持多种设备,这些设备并不是全都提供相同的硬件配置和功能。 为了防止在不提供必需配置的设备上安装应用程序,明确定义一个配置文件是非常重要的,以便列出 App 支持的设备类型,这通过在 Manifest 文件中声明软硬件需求即可。 绝大部分声明仅仅是通告性质的,系统不会去读取它们。 但为了能让用户在搜索应用时根据设备型号进行过滤,类似 Google Play 之类的外部服务将会读取这些信息。

    例如,如果应用程序需要用到摄像头和 Android 2.1 以上的 API( API Level 7), 就可以在 Manifest 文件中进行如下声明:

    <manifest ... >
        <uses-feature android:name="android.hardware.camera.any"
                      android:required="true" />
        <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
        ...
    </manifest>
    

    这样,具备摄像头的设备和低于2.1版本的 Android 就无法通过 Google Play 安装该应用了。

    当然,还可以声明为:应用程序会用到摄像头但不是必需的。这时,应用程序必须将 required 设为 "false" ,并且在运行时自行检测是否存在摄像头,以便适时禁用与之有关的功能。

    关于如何让应用程序保持与各种设备的兼容性,文档 设备兼容性 中给出了更为详细的信息。

    应用程序资源

    Android 应用程序并不仅仅由源代码构成 — 还需要用到资源文件,如图片、音频文件和其他所有的可视化内容,这些都是与源代码相分离的。 例如,用 XML 文件定义动画、菜单、颜色、Activity 用户界面的 Layout。 通过资源文件,不必修改源代码就可以方便地改变应用程序的各种配置 — 通过替代资源 — 以便根据各种设备参数(比如不同的语言和屏幕尺寸)优化应用程序。

    SDK 编译工具会为 Android 项目中的每个资源都定义一个唯一的整数型 ID,以便在源代码或 XML 格式的其他资源中引用该资源。 例如,假设应用程序中包含一个名为 logo.png 的图片文件(保存在 res/drawable/ 目录中), SDK 编译工具将会创建一个名为 R.drawable.logo 的唯一 ID,通过此 ID 可以引用该图片并把它放用户界面中去。

    把资源文件从源代码中分离出来的重点之一,就是为不同的设备参数分别给出替代资源。 例如,通过定义 XML 格式的 UI 字符串,可以把这些文字翻译为其他国家的语言并保存到单独的文件中。 然后,根据资源目录名后面跟随的语言标识符(如法语字符串就是 res/values-fr/),以及用户的语言设置, Android 系统将会把相应语言的字符串应用到用户界面中。

    Android 为替代资源提供了很多不同种类的的 标识符。 这些标识符也就是一个短字符串,各种设备配置对应的资源目录的名称中包含了这个字符串。 再举个例子,根据设备的屏幕方向和尺寸,通常需要为 Activity 创建多种不同的布局文件(Layout)。 比如,当设备屏幕是纵向放置时(高度较大),可能需要让按钮纵向排列。 而当屏幕横向放置时(宽度较大),按钮就应该是横向放置了。 为了能根据屏幕方向来改变布局,可以定义两个 Layout,并用适当的标识符为 Layout 目录命名。 这样,系统就能根据当前设备方向自动选用合适的 Layout。

    关于应用程序可用的各种资源,以及如何为各种设备配置创建替代资源,更多信息请参阅 提供资源

    后续阅读:

    Intent 和 Intent 过滤器
    有关用 Intent API 激活诸如 Activity 和服务之类的应用程序组件、让组件可被其他应用程序使用等内容。
    Activity
    有关创建 Activity 类的实例等内容。Activity 在应用程序中提供某个包含用户界面的窗口。
    提供资源
    有关资源和源代码分离的 Android 应用程序架构,包括为某种设备配置提供替代资源等内容。

    还可能感兴趣:

    设备兼容性
    有关在各种型号设备上运行 Android 的信息,以及为每种设备优化程序或者限制功能。
    系统权限
    Android 通过一套授权系统对应用程序访问某些 API 进行的限制,用户由此授权系统同意应用程序使用这些 API。
  • 相关阅读:
    《30天自制操作系统》06_day_学习笔记
    《30天自制操作系统》05_day_学习笔记
    《30天自制操作系统》04_day_学习笔记
    ugui Event.current.mousePosition获取的坐标原点在左上角
    场景中GameObject无法用代码隐藏问题(setActive为false)
    让camera实现类似cs第一人称视角旋转和位移
    itunesconnect如何提交被决绝过了的相同版本号
    mac下安装libpng环境
    golang实现模拟键盘按键
    cocos2d3.x在android下屏蔽多点触控
  • 原文地址:https://www.cnblogs.com/popapa/p/android_fundamentals.html
Copyright © 2011-2022 走看看