Android API Guides - Application Fundamentalsn

来源:互联网 发布:matlab产生随机数组 编辑:程序博客网 时间:2024/06/05 20:42


Application Fundamentals 基础知识

Android apps are written in the Java programming language. The Android SDK tools compile your code—along with any data and resource files—into an APK: an Android package, which is an archive file with an .apk suffix. One APK file contains all the contents of an Android app and is the file that Android-powered devices use to install the app.

安卓应用的开发语言是JAVA。安卓 SDK tools 会将源码(包括应用所需的数据和资源文件)编译进一个APK(即Android PacKage 安卓包,一种后缀名为.apk的库文件)中。一个 APK 文件就包含了这个安卓应用的所有东西,同时也是安卓设备安装这个应用所需的安装文件。

Once installed on a device, each Android app lives in its own security sandbox:

每个被安装的安卓应用都只在只属于自己的安全的沙盒环境中:

  • The Android operating system is a multi-user Linux system in which each app is a different user.
  • 安卓操作系统是个多用户的 Linux 操作系统,每个安卓应用都是一个独立的用户
  • By default, the system s each app a unique Linux user ID (the ID is used only by the system and is unknown to the app). The system sets permissions for all the files in an app so that only the user ID assigned to that app can access them.
  • 默认的,系统为每个应用分配一个唯一的 Linux 用户ID(这个ID只被系统使用,对应用是不可知的)。系统没应用中的所有文件都设置了权限,因此只有这个应用对应的用户ID才有权限这些文件。
  • Each process has its own virtual machine (VM), so an app's code runs  other apps.
  • 每个进程都有它们各自的虚拟机,因而每个安卓应用中的代码都可以在独立于其他应用的环境中运行。
  • By default, every app runs in its own Linux process. Android starts the process when any of the app's components need to be executed, then shuts down the process when it's no longer needed or when the system must recovermemory for other apps.
  • 默认情况下,每个应用都运行在自己的 Linux 进程中。当安卓应用的某个组件需要被执行的时候,安卓系统就会启动它并在它不再被需要或者当系统需要为其他应用获得更多内存的时候终止它。

In this way, the Android system implements . That is, each app, by default, has access only to the components that it requires to do its work and no more. This creates a very secure environment in which an app cannot access parts of the system for which it is not given permission.

安卓系统用这种方法实现了“最小权限原则”,即每个应用默认情况下,只能获得它运行时需要的组件的使用权。这就创造了一个非常安全的环境,因为每个应用由于权限的约束,都无法访问系统的其他部分。

However, there are ways for an app to share data with other apps and for an app to access system services:

当然,安卓应用也有一些方法来与其他应用共享数据,或者获取系统服务:

  • It's possible to arrange for two apps to share the same Linux user ID, in which case they are able to access each other's files. Toconserve system resources, apps with the same user ID can also arrange to run in the same Linux process and share the same VM (the apps must also be signed with the same certificate).
  • 让两个应用共享同一个 Linux 用户ID是完全可能的,这可以让它们能够共享彼此的文件。为了保证系统安全,拥有相同用户ID的应用也会被安排运行在同一个 Linux 进程下,并且共享一个相同的虚拟机(前提是这些应用都有相同的授权)。
  • An app can request permission to access device data such as the user's contacts, SMS messages, the mountable storage (SD card), camera, Bluetooth, and more. All app permissions must be granted by the user at install time.
  • 应用也可以申请获取设备的相关数据或功能(比如联系人,短信,SD卡,摄像头,蓝牙等)。所有的这些授权都必须在应用被安装时经过用户的许可。

That covers the basics regarding how an Android app exists within the system. The rest of this document introduces you to:

上述基本解释了一个安卓应用是如何存在于系统之中的,接下来的部分主要讲述了:

  • The core framework components that define your app.
  • 定义应用程序的核心框架组件
  • The manifest file in which you declare components and required device features for your app.
  • 声明应用程序拥有哪些组件并申请设备功能的声明文件“the manifest file”
  • Resources that are separate from the app code and allow your app to gracefully optimize its behavior for a variety of device configurations.
  • 存放在独立于应用程序代码位置的能让你优雅地适配各种各样设备的资源文件

App Components 应用程序组件



App components are the essential building blocks of an Android app. Each component is a different point through which the system can enter your app. Not all components are actual entry points for the user and some depend on each other, but each one exists as its own entity and plays a specific role—each one is a unique building block that helps define your app's overall behavior.

所谓的应用程序组件指的就是一个安卓应用的基础的组成模块。每个组件都是系统运行你的应用程序的入口。尽管并非所有组件都是用户启动应用的入口,并且组件之间还存在依赖关系,但是每个组件都有它相应的实体存在。当不同组件组合在一起共同决定你的应用的整体特性时,每个组件都是一个与众不同的组成模块,各自扮演着一个独特的角色。

There are four different types of app components. Each type serves a distinct purpose and has a distinct lifecycle that defines how the component is created and destroyed.

安卓应用组件一共有四种类型,每种类型的组件都为不同的目的而服务,并都有各自不同的声明周期(即何时被创建,何时被销毁)。

Here are the four types of app components:

以下即四种不同类型的组件简介

Activities 活动

An activity represents a single screen with a user interface. For example, an email app might have one activity that shows a list of new emails, another activity to compose an email, and another activity for reading emails. Although the activities work together to form a cohesive user experience in the email app, each one is independent of the others. As such, a different app can start any one of these activities (if the email app allows it). For example, a camera app can start the activity in the email app that composes new mail, in order for the user to share a picture.

An activity is implemented as a subclass of Activity and you can learn more about it in the Activities developer guide.

一个 Activity 在用户界面中就代表着一个屏幕的展现形式。举个栗子,一个邮件应用应该拥有一个 Activity 来显示一个含有所有新邮件的列表,一个写邮件的 Activity和一个阅读邮件的 Activity。尽管邮件应用的整体使用感受好与否是由各个 Activity 相互协作而决定的,但是每个 Activity 却也是独立存在的。因此只要这个邮件应用允许,它就可以从上述三个 Activity 中的任意一个之中直接启动。让我们来继续举栗子,一个拍照应用可以直接启动邮件应用中的“写邮件” Activity 来分享一个照片。

每个 Activity 都是 Activity 类的子类实现。你可以在 Activities 开发指导部分获得更多的相关信息。

Services 服务
service is a component that runs in the background to perform long-running operations or to perform work for remote processes. A service does not provide a user interface. For example, a service might play music in the background while the user is in a different app, or it might fetch data over the network without blocking user interaction with an activity. Another component, such as an activity, can start the service and let it run or bind to it in order to interact with it.

A service is implemented as a subclass of Service and you can learn more about it in the Services developer guide.

service 是一个用来在后台执行长时间操作或远程进程(remote processes)的组件。它并不提供用户界面。还是来举个栗子,当用户在使用另一个应用时,service可以在后台播放音乐(长时间操作)或者它可以在后台静默地下载网络资源而不需要打断用户与 Activity 之间的交互(远程进程)。其他组件,比如 Activity 可以启动 Service 来让它运行,或者为了与它交互而与之绑定(比如音乐软件的播放界面与实际执行音乐播放操作的 Service 进行绑定)。

一个 Service 即 Service 类的一个子类实现,你可以点击  Services 获取更多信息。(不会翻墙就别点了,打不开的。)

Content providers 数据供应者

content provider manages a shared set of app data. You can store the data in the file system, an SQLite database, on the web, or any other persistent storage location your app can access.Through the content provider, other apps can query or even modify the data (if the content provider allows it). For example, the Android system provides a content provider that manages the user's contact information. As such, any app with the proper permissions can query part of the content provider (such as ContactsContract.Data) to read and write information about a particular person.

Content providers are also useful for reading and writing data that is private to your app and not shared. For example, the Note Pad sample app uses a content provider to save notes.

A content provider is implemented as a subclass of ContentProvider and must implement a standard set of APIs that enable other apps to perform transactions. For more information, see the Content Providers developer guide.

Content Provider 管理着应用程序中部分被共享的数据。你可以将这些数据存储在任何你的应用拥有使用权的文件系统中,SQLite数据库里,Web上或者其他可持久存储的地方。通过 Content Provider,其他应用能够读取甚至是修改这些数据(前提是 Content Provider 允许你修改)。举个栗子(第几个栗子来着?)安卓系统自身就提供一个 Content Provider 来管理用户的联系人信息。因此任何有相应权限的应用都可以查询到 Content Provider 中的部门内容(比如ContactsContract.Data)并能够读写某个指定的联系人信息。

Content Provider 在读写非共享的数据时也很有帮助,譬如说这个  Note Pad (记事本)小程序就使用了一个 Content Provider 来保存数据。

Content Provider 是 ContentProvider 的子类实现,并且你必须实现一个标准的 API 集合来使得其他应用能够执行相应的事务操作。详情请看下回分解,哦不,请看 Content Providers 开发人员指导。

Broadcast receivers 广播接收器
broadcast receiver is a component that responds to system-wide broadcast announcements. Many broadcasts originate from the system—for example, a broadcast announcing that the screen has turned off, the battery is low, or a picture was captured. Apps can also initiate broadcasts—for example, to let other apps know that some data has been downloaded to the device and is available for them to use. Although broadcast receivers don't display a user interface, they may create a status bar notification to alert the user when a broadcast event occurs. More commonly, though, a broadcast receiver is just a "gateway" to other components and is intended to do a very minimal amount of work. For instance, it might initiate a service to perform some work based on the event.

A broadcast receiver is implemented as a subclass of BroadcastReceiver and each broadcast is delivered as an Intent object. For more information, see the BroadcastReceiver class.

broadcast receiver 是一个用来响应全系统的广播通知的组件。很多广播都来源自系统自身——譬如当屏幕被关闭、电池电量过低或者拍完一张照时,系统会进行相应的广播通知。应用程序也可以进行广播,比如说通知其他应用某个网络资源(视频啦,歌曲啦)已经下载完成并可以使用了。尽管 broadcast receiver 自身并没有对应的用户界面(不像 Activity 那样),但当一个广播被发出时,它可能会创建一个状态通知栏(create a status bar notification)来通知用户这个广播的信息。通常情况下, broadcast receiver 仅仅是一个与其他组件交互的一个“网关”并只干最少量的活儿。比如当一个事件发生时,broadcast receiver 所做的事情仅仅是启动一个 service,而处理这一事件的绝大部分工作量都交由这个 service 来完成。

每个 broadcast receiver 都是 BroadcastReceiver 类的子类实现,并且每个广播通知都是通过一个 Intent 对象的实例来进行传递的。详情请看 BroadcastReceiver 类。

A unique aspect of the Android system design is that any app can start another app’s component. For example, if you want the user to capture a photo with the device camera, there's probably another app that does that and your app can use it, instead of developing an activity to capture a photo yourself. You don't need to incorporate or even link to the code from the camera app. Instead, you can simply start the activity in the camera app that captures a photo. When complete, the photo is even returned to your app so you can use it. To the user, it seems as if the camera is actually a part of your app.

安卓系统的设计有一个独到之处就是任何一个应用程序都可以启动其他应用程序的组件。举举举个大栗子(大栗子没小栗子好吃),如果你想要用户用摄像头拍张照时,很可能是其他应用来干了这事儿然后把拍到的照片给你来使用,而不是你自己来开发一个 activity 来自己调用摄像头来拍照。你的应用不需要内置一个摄像程序,甚至也不需要与一个摄像程序来进行对接。你所要做的仅仅是启动相机应用的 activity 来拍张照。照片被拍摄完毕之后就会传到你的应用中供你使用。而对于用户来说,这就好好像拍照功能是你应用内置的一部分功能一样。

When the system starts a component, it starts the process for that app (if it's not already running) and instantiates the classes needed for the component. For example, if your app starts the activity in the camera app that captures a photo, that activity runs in the process that belongs to the camera app, not in your app's process. Therefore, unlike apps on most other systems, Android apps don't have a single entry point (there's no main()function, for example).

当系统启动一个组件时,如果这个组件所在的应用当前并不是运行状态,系统就会初始化这个组件所需要的类然后启动这个应用的进程。举例来说,当你的应用程序启动了一个摄相机应用的 activity 来拍摄一张照片时,这个 activity 就会运行在这个摄相机所在的进程中,而不是运行在调用这个 activity 的应用程序进程之中。也因此,安卓应用不像其他系统的应用那样,仅有一个单一的进入点(比如main方法之类的)。

Because the system runs each app in a separate process with file permissions that restrict access to other apps, your app cannot directly activate a component from another app. The Android system, however, can. So, to activate a component in another app, you must deliver a message to the system that specifies your intent to start a particular component. The system then activates the component for you.

因为安卓系统将每个应用分别运行在一个独立的进程中并使用文件系统权限来限制访问其他应用,所以你的应用程序并不能直接调用其他应用的组件。但是安卓系统它自己可以激活任何应用的组件,所以你需要告诉系统“我想启动一个怎样怎样的组件”,然后系统就会为你激活这个组件。

Activating Components 激活组件

Three of the four component types—activities, services, and broadcast receivers—are activated by an asynchronous message called an intent. Intents bind individual components to each other at runtime (you can think of them as the messengers that request an action from other components), whether the component belongs to your app or another.

Activity,Service 和 Broadcast Receiver 都是通过一个叫做 intent 的异步消息来激活的。Intent 在程序运行时将独立的组件互相结合在一起(你可以把它想象成一个组件请求另一个组件来执行某个操作的通信员),无论这些组件是隶属你的应用还是属于别人的应用。

An intent is created with an Intent object, which defines a message to activate either a specific component or a specific type of component—an intent can be either explicit or implicit, respectively.

一个 intent 实例化自一个名叫 Intent 的类,它定义个要激活某个指定的组件,或者某个指定类型的组件(即一个intent既可以是明确的,也可以是含糊的)的激活信息。

For activities and services, an intent defines the action to perform (for example, to "view" or "send" something) and may specify the URI of the data to act on (among other things that the component being started might need to know). For example, an intent might convey a request for an activity to show an image or to open a web page. In some cases, you can start an activity to receive a result, in which case, the activity also returns the result in an Intent (for example, you can issue an intent to let the user pick a personal contact and have it returned to you—the return intent includes a URI pointing to the chosen contact).

对 activity 和 service 而言,一个 intent 往往定义了要执行的操作(比如查看或者发送某事物)并且可能指定了要被查看或者被发送的数据的 URI(含有组件启动所需要知道的其他消息)。比如,一个intent可能请求一个activity来展现一张图片或者打开一个web页面(此时intent中除了声明“我要打开一张图片”,也同时含有要被打开的图片的URI信息)。有时候,你可以启动一个 activity 然后获得这个activity的执行结果,此时,activity 也会将执行结果通过一个 Intent 来返回(比如你可以发起一个 intent 来让用户选择一个联系人,然后你就会接收到一个含有被用户选中的联系人的URI信息的 Intent)。

For broadcast receivers, the intent simply defines the announcement being broadcast (for example, a broadcast to indicate the device battery is low includes only a known action string that indicates "battery is low").

对 broadcast receiver 而言,intent 仅仅简单定义了被广播的通知信息(比如,一个低电量的广播通知仅包含一个显示“电量不足”的字符串)。

The other component type, content provider, is not activated by intents. Rather, it is activated when targeted by a request from a ContentResolver. The content resolver handles all direct transactions with the content provider so that the component that's performing transactions with the provider doesn't need to and instead calls methods on the ContentResolver object. This leaves a layer of abstraction between the content provider and the component requesting information (for security).

content provider 并不是被 intent 激活的。当一个来自于 ContentResolver 的请求指向它时,它才会被激活。content resolver 处理所有与 content provider 相关的直接性的事务(direct transaction,这个不知道怎么翻译好,暂且就翻译成直接性的事务吧),这样的组件与content provider就不需要进行事务操作,而是调用 ContentResolver 对象上的方法。这样就在 content provider  和需要信息的组件之间假设一个抽象层,这么设计是出于安全考虑。

There are separate methods for activating each type of component:

下面介绍了几种激活各个类型组件的方法

  • You can start an activity (or give it something new to do) by passing an Intent to startActivity() orstartActivityForResult() (when you want the activity to return a result).
  • 你可以通过传递一个 Intent 到 startActivity() 方法或者 startActivityForResult()  方法 (如果你需要这个activity返回一个结果的话)中来启动一个activity(或者让它执行一个新的操作)
  • You can start a service (or give new instructions to an ongoing service) by passing an Intent tostartService(). Or you can bind to the service by passing an Intent to bindService().
  • 你可以通过传递一个  Intent 到 startService() 方法中来启动一个 service (或者给一个持续运行的service发送一个新命令,比如给一个在后台播放音乐的service发送切歌命令)。或者你也可以传递一个 Intent 到 bindService()方法中,来将方法调用者于与这个service绑定在一起。(比如播放歌曲的用户界面,往往是一个activity可以和一个在后台播放音乐的service绑定到一起)。
  • You can initiate a broadcast by passing an Intent to methods like sendBroadcast()sendOrderedBroadcast(), orsendStickyBroadcast().
  • 你可以通过传递一个 Intent 到类似 sendBroadcast()sendOrderedBroadcast(), orsendStickyBroadcast()的方法中来发起一个广播。
  • You can perform a query to a content provider by calling query() on a ContentResolver.
  • 你可以调用某个 ContentResolver 实例的 query() 方法来对一个 content provider 进行一次查询操作。

For more information about using intents, see the Intents and Intent Filters document. More information about activating specific components is also provided in the following documents: Activities, Services,BroadcastReceiver and Content Providers.

有关 intent 的使用请查阅 Intents and Intent Filters 章节。更多关于激活指定的组件的信息,请参阅Activities, Services,BroadcastReceiver 和 Content Providers 中的内容。

The Manifest File 清单文件


Before the Android system can start an app component, the system must know that the component exists by reading the app's AndroidManifest.xml file (the "manifest" file). Your app must declare all its components in this file, which must be at the root of the app project directory.

在安卓系统启动一个应用程序的组件之前,系统必须先读取这个应用程序的  AndroidManifest.xml 文件(即“清单”文件)来了解究竟这个应用中有哪些个组件。你的应用必须在这个文件中声明它的组件,并且这个文件必须放在这个安卓应用项目的根目录下。

The manifest does a number of things in addition to declaring the app's components, such as:

这个 manifest 做了许多事情来说明这个应用的每一个组成部分:

  • Identify any user permissions the app requires, such as Internet access or read-access to the user's contacts.
  • 列举这个应用所需要的所有用户权限,比如联系人信息的读取权限。
  • Declare the minimum API Level required by the app, based on which APIs the app uses.
  • 根据这个应用使用的 API 来声明这个应用所需的最低级别的 API 等级(API Level)。
  • Declare hardware and software features used or required by the app, such as a camera, bluetooth services, or a multitouch screen.
  • 声明这个应用所使用到的或者所必须的软硬件特性,比如相机功能,蓝牙服务,或者必须要有一个多点触摸屏。
  • API libraries the app needs to be linked against (other than the Android framework APIs), such as the Google Maps library.
  • 声明这个应用所需要的区别于安卓框架API的其他API类库,比如 Google Maps library。
  • And more
  • 其他事情

Declaring components 声明组件

The primary task of the manifest is to inform the system about the app's components. For example, a manifest file can declare an activity as follows:

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>

In the <application> element, the android:icon attribute points to resources for an icon that identifies the app.

在  <application> 标签中, android:icon 属性指向了一个图标资源,来确定了这个应用的图标。

In the <activity> element, the android:name attribute specifies the fully qualified class name of the Activity subclass and the android:label attributes specifies a string to use as the user-visible label for the activity.

在 <activity> 标签中, android:name 属性指明了一个  Activity 子类的全名,而 android:label 属性则指明了这个 activity 标签的字符串格式的内容。

You must declare all app components this way:

你必须用下面这种形式来声明所有的应用组件:

  • <activity> elements for activities
  • 使用 <activity> 标签来声明所有的 activity
  • <service> elements for service
  • 使用 <service> 标签来声明所有的 activity
  • <receiver> elements for broadcast receivers
  • 使用 <receiver> 标签来声明所有的 activity
  • <provider> elements for content providers
  • 使用 <provider> 标签来声明所有的 activity

Activities, services, and content providers that you include in your source but do not declare in the manifest are not visible to the system and, consequently, can never run. However, broadcast receivers can be either declared in the manifest or created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling registerReceiver().

你源码中的任何activity,service和content provider ,如果没有在 manifest 中声明,那么对系统而言就是不可见的,也就永远都不会被运行。而 broadcast receiver 既可以在 manifest 中声明,可以在代码中(作为一个 BroadcastReceiver 类的实例)通过调用  registerReceiver() 动态注册到系统中。

For more about how to structure the manifest file for your app, see The AndroidManifest.xml File documentation.

有关如何构建应用程序的 manifest 文件,请参阅 The AndroidManifest.xml File 中的相关内容

Declaring component capabilities 声明组件的功能

As discussed above, in Activating Components, you can use an Intent to start activities, services, and broadcast receivers. You can do so by explicitly naming the target component (using the component class name) in the intent. However, the real power of intents lies in the concept of implicit intents. An implicit intent simply describes the type of action to perform (and, optionally, the data upon which you’d like to perform the action) and allows the system to find a component on the device that can perform the action and start it. If there are multiple components that can perform the action described by the intent, then the user selects which one to use.

就上之前在 Activating Components 这一节中所描述的那样,你可以使用一个  Intent  来激活 activity ,service 或者是 broadcast receiver。你可以通过在 intent 中显式地写明被激活组件的名字(即该组件的类名)。但其实 intent 威力的真正所在是隐式 intent 的使用。一个隐式 intent 只简单声明了需要执行的操作的类型(以及执行这个操作所要用到的数据,而这个不是必须的)然后让系统去在设备上搜寻能够执行这个操作的组件并激活它。如果存在多个组件都能够执行这个 intent 中声明的操作,那么系统就会让用户来选择一个组件来执行这个操作。

The way the system identifies the components that can respond to an intent is by comparing the intent received to the intent filters provided in the manifest file of other apps on the device.

系统通过将设备上的其他应用在 manifest 文件中声明的 intent filter 和接收到的 intent 进行比对来判断组件是否能够响应这个 intent。

When you declare an activity in your app's manifest, you can optionally include intent filters that declare the capabilities of the activity so it can respond to intents from other apps. You can declare an intent filter for your component by adding an <intent-filter> element as a child of the component's declaration element.

当你在 manifest 文件中声明一个 activity 时,你可以有选择性地在 activity 中声明你的 activity 能够处理哪些其他应用传来的 intent。这类声明通过在你的 manifest 文件中的组件标签下添加 <intent-filter> 来确定。

For example, if you've built an email app with an activity for composing a new email, you can declare an intent filter to respond to "send" intents (in order to send a new email) like this:

居里,距离,举例!如果你正在开发一款电子邮箱的应用,然后有个写电子邮件的 activity,你就可以像下面这样来声明你的 activity 能够处理含有“发送”动作的 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>

Then, if another app creates an intent with the ACTION_SEND action and pass it to startActivity(), the system may start your activity so the user can draft and send an email.

一旦声明好了之后,如果有其他应用创建了一个要执行 ACTION_SEND 动作的 intent 并作为 startActivity() 方法的参数来调用,那么系统就会启动你的 activity ,用户就可以撰写并发送邮件了。

For more about creating intent filters, see the Intents and Intent Filters document.

有关如何设置组件对 intent 的接收设置,请参见 Intents and Intent Filters 文档。

Declaring app requirements 声明应用程序正常运行所需的条件

There are a variety of devices powered by Android and not all of them provide the same features and capabilities. In order to prevent your app from being installed on devices that lack features needed by your app, it's important that you clearly define a profile for the types of devices your app supports by declaring device and software requirements in your manifest file. Most of these declarations are informational only and the system does not read them, but external services such as Google Play do read them in order to provide filtering for users when they search for apps from their device.

搭载安卓系统的设备种类繁多,也因此它们并非都具备相同的设备功能,比如有的有摄像头有的没有。为了防止你的应用程序被安装在缺少该应用程序正常运行所必要的功能的设备上,你就必须在manifest文件中明确地声明你的应用需要哪些软硬件功能,这样才能确定什么类型的设备才能够完美地支持你的应用程序。对于安卓系统而言这些声明信息并没有什么作用,系统并不会去读取这些信息,这些信息是用来给外部服务来读取的,比如 Google Play 就会读取这些信息来过滤持有什么样的设备的用户才能检索到你的应用程序。

For example, if your app requires a camera and uses APIs introduced in Android 2.1 (API Level 7), you should declare these as requirements in your manifest file like this:

举例来说,如果你的设备声明了必须要有摄像头支持,并使用了安卓2.1之后才有的 API,那就该像下面这样来写明你的 manifest 文件

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

Now, devices that do not have a camera and have an Android version lower than 2.1 cannot install your app from Google Play.

而一旦你这么做了之后,那些没有摄像头,或者安卓版本低于2.1的设备就不会通过 Google Play 安装上你的应用程序。

However, you can also declare that your app uses the camera, but does not require it. In that case, your app must set the required attribute to "false" and check at runtime whether the device has a camera and disable any camera features as appropriate.

然后,你也可以声明你的应用程序需要一个摄像头,但它并非是必须的。这种情况下,你的 manifest 中 required 属性就得改成 "false" ,然后在程序的运行过程中判断当前设备是否具有摄像头功能,并且如果当前设备没有摄像头的时候就禁用掉应用程序中依赖摄像头的功能。

More information about how you can manage your app's compatibility with different devices is provided in the Device Compatibility document.

有关如何构建 manifest 文件来声明何种类型的设备才能安装你的应用,请移步 Device Compatibility 章节。

App Resources 应用程序资源文件


An Android app is composed of more than just code—it requires resources that are separate from the source code, such as images, audio files, and anything relating to the visual presentation of the app. For example, you should define animations, menus, styles, colors, and the layout of activity user interfaces with XML files. Using app resources makes it easy to update various characteristics of your app without modifying code and—by providing sets of alternative resources—enables you to optimize your app for a variety of device configurations (such as different languages and screen sizes).

一个安卓应用程序所包含的不仅仅是代码,它还包括一些独立于代码之外的资源文件,比如图片,音频文件以及其他一些和视觉呈现相关的东西,比如定义了动画元素,菜单,样式,activity的布局等等信息的XML文件。通过提供各种可替换的资源文件,你就能够很轻松地优化应用在各种设备环境下的用户体验,而不需要对代码进行改动。

For every resource that you include in your Android project, the SDK build tools define a unique integer ID, which you can use to reference the resource from your app code or from other resources defined in XML. For example, if your app contains an image file named logo.png (saved in the res/drawable/ directory), the SDK tools generate a resource ID named R.drawable.logo, which you can use to reference the image and insert it in your user interface.

SDK 构建工具(SDK build tools)为会应用中的每一个资源都指定一个唯一的整数ID,你可以在代码中或者在XML资源文件中使用这些ID来引用对应的资源。比如,如果你的应用中有一个名叫logo.png的图片(保存在 res/drawable/ 目录下),那么SDK 工具就会生成一个名叫 R.drawable.logo的资源ID,你就可以使用它来引用到这张图片将其插入到你的用户界面中。

One of the most important aspects of providing resources separate from your source code is the ability for you to provide alternative resources for different device configurations. For example, by defining UI strings in XML, you can translate the strings into other languages and save those strings in separate files. Then, based on a language qualifier that you append to the resource directory's name (such as res/values-fr/ for French string values) and the user's language setting, the Android system applies the appropriate language strings to your UI.

之所以将资源文件独立于源代码,是为了方便开发人员更方便地对各种不同的硬件环境进行优化(只要提供相应的可替换的资源文件即可)。比如,当你在独立存放的XML文件中定义UI界面上使用到的文字资源,而不是在源代码中硬编码时,那么你就很轻松地让应用程序支持国际化,只要多提供几个其他语言的XML资源即可。此时你需要在保存该XML资源的目录名上加上语言修饰符(比如法语的文字资源文件就应该保存在res/values-fr/ 文件夹下),那么当用户改变系统的语言设定的时候,安卓系统就会自动获取相对应的语言资源并替换到你的UI界面上重塑应用的视觉效果。(这块见仁见智吧,小应用不用考虑过多的设备兼容性或者仅需要支持汉语用户的时候这些设计就感觉很多余,并且拖慢应用的开发效率,虽然这的确是一种非常棒的设计思想,也很符合安卓系统的设计初衷,但是否在开发过程中一定按照这种理念来开发,这个感觉还是得看项目的需求,是否时间紧迫,是否一定要支持多种屏幕大小,是否一定要支持多国语言等等。)

Android supports many different qualifiers for your alternative resources. The qualifier is a short string that you include in the name of your resource directories in order to define the device configuration for which those resources should be used. As another example, you should often create different layouts for your activities, depending on the device's screen orientation and size. For example, when the device screen is in portrait orientation (tall), you might want a layout with buttons to be vertical, but when the screen is in landscape orientation (wide), the buttons should be aligned horizontally. To change the layout depending on the orientation, you can define two different layouts and apply the appropriate qualifier to each layout's directory name. Then, the system automatically applies the appropriate layout depending on the current device orientation.

安卓针对可替换的资源文件有许多种类的修饰方式。而这些修饰方式简单说就是在存放资源的目录名后加上相应的修饰符,这样当应用程序运行在不同的环境下时,系统就会根据当前的运行环境来根据目录名来选择合适的资源。再举个栗子,你总是应该为你的activity定义不同的布局文件以应对各种各样的显示环境,例如如果当前设备的屏幕方向是垂直的(tall),你可能就需要将按钮竖着排列,当屏幕方法是水平时(wide),按钮就应该水平排列。要针对不同的屏幕方向来改变界面的显示方式,那就必须要定义两个不用的布局文件并存放在带有相应修饰符的路劲下以供系统自动识别并调用。

For more about the different kinds of resources you can include in your application and how to create alternative resources for different device configurations, read Providing Resources.

更对有关如果为不同的设备环境创建相应的可替换资源的信息请自己去看 Providing Resources 里的东西。


0 0
原创粉丝点击