Android官方文档阅读之旅——Application Fundamentals

Android官方文档阅读之旅——Application Fundamentals

原文地址:http://developer.android.com/guide/components/fundamentals.html

前言

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.

Android应用程序由Java编写。SDK(Software Development Kit 软件开发工具包)工具将会把你的源代码同任何数据及资源文件进行编译并打包到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.
    • By default, the system assigns 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.
    • Each process has its own virtual machine (VM), so an app’s code runs in isolation from 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 recover memory for other apps.

只要应用被安装,那么每个应用就会在各自的安全沙盒中运行:

  • Android是一个多用户的Linux操作系统,每个应用视为不同的用户
  • 默认情况下,系统会为每个应用分配一个唯一的Linux用户ID(这个ID仅由系统自己使用,应用是无法感知的)。它同时为一个应用中的所有文件进行访问授权,这样一来,只有持有此用户ID的程序可以对这些文件进行访问。
  • 每个进程都有其自己虚拟机实例,这样一个程序的代码就不能跑在其他应用程序的运行空间中了
  • 默认下,每个应用都跑在它自己的Linux进程里。在任何一个此应用的组件需要运行时,Android都会启动这个组件所在进程并在不需要它继续运行时关闭这个进程,这样的关闭也发生在系统必须为其他应用回收内存时。

In this way, the Android system implements the principle of least privilege. 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. To conserve 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).
  • 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.

然而,这里仍然有很多方法让不同应用进行数据共享以及让一个应用获得系统的服务:

  • 完全可以让不同的两个应用间共享同一个Linux用户ID,这样,它们就能访问对方的文件。为了节约系统资源,具有同用户ID的应用可以被安排在同一个Linux进程运行并且共享同一个虚拟机实例(前提是这些应用也必须被同一个证书签名)
  • 一个应用可以为访问诸如用户通讯录、短信、可移除存储(SD卡,即Secure Digital Memory Card 安全数字存储卡)、摄像头、蓝牙等资源申请权限。所有的这些权限必须在安装时由用户进行批准。

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.
  • 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.

每个Activity表示了一个用于用户界面的单独窗口。例如,一个邮件应用就可以包含一个用于展示新邮件列表的Activity,一个写邮件的Activity以及一个读邮件的Activity。虽然Activity们相互协作并在邮件应用中打造了一种有整体感,但是每个Activity都是独立存在的。同样的,如果邮件应用许可,那么其他的应用也可以启动这些Activity中的任何一个。举个例子,一个拍照应用可以启动邮件应用中用于写邮件的Activity,这样可以方便用户共享他们的照片。

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

每个界面都是一个Activity的实例,你可以在开发者指南Activity篇中了解更多。

Service

A 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.

一个Service是一个用于在后台执行长时间任务或者为远程进程服务的功能组件。它对用户并不可见。例如,一个Service可以在用户使用其他应用时在后台播放音乐,或者通过网络在后台获取数据而并不阻塞前台Activity用户界面。其他组件,如Activity,可以让Service运行或被绑定以和其进行交互。

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

每个服务都是一个Service类的实例,你可以在开发者文档Service篇中了解更多。

Content providers

A 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 Provider(内容提供者,以下简称CP)管理着应用的共享数据集。你可以在文件系统中存储数据,如在SQLite数据库、网络或者其他任何你应用可以访问到的永久存储介质。通过CP,其他应用可以查询甚至改动这些数据(如果CP授权它可以这么做的话)。例如,安卓系统自身就提供了一个管理联系人信息的CP。同样的,任何持有对应权限的应用可以查询CP的特定部分(如 ContactsContract.Data,一个存储用户联系人详细信息的地方)以读写特定联系人信息。

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.

CP 对于处理应用私有数据也是十分有用的。例如,一个记事本样例程序就是用了CP去存储它的笔记。

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.

每个CP都是ContentProvider类的一个实例,且它必须实现一系列标准API(Application Programming Interface 应用程序编程接口)以让其他应用可以执行事务。更多信息请查阅开发文档内容提供者部分。

Broadcast receivers

A 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.

broadcast receiver(广播接收器,以下简称“BR”)是一个用于响应系统级广播通知的组件。很多广播都由系统发出。例如,锁屏、电池电量低、截屏都会发出广播。应用自己也可以发送广播,如当数据已经下载且可被其他应用访问时。虽然广播接收器并不对用户可见,或者更一般情况下,虽然BR只是一个启动其他组件的一个媒介并且被设计为做尽可能少的工作,但是它们却能创建一个状态栏通知提示用户收到了广播消息。例如BR可以启动一个Service并让它根据事件执行具体的操作。

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.

广播接收器是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.

Android系统设计的一个特别之处就在于一个应用可以打开另一个应用的组件。例如,如果你想让用户通过摄像头捕捉照片,那么很有可能的是一个应用已经实现了这个功能,而你的应用可以直接调用它而非自己再去开发一个Activity。你无须参与那个摄像应用的研发,相反,你可以很容易地启动这个Activity来捕捉图像。捕捉完成后,这张照片会被返回到你的APP中。这一切对于用户看来就好像都是你软件的一部分一样。

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).

当系统打开一个组件时,它就会启动对应应用所在的进程(如果这个进程还没运行的话),并且初始化这个组件需要的类。例如,如果你的APP打开了摄像软件并用其捕捉了一张图像,那么那个对应的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.

由于系统将各个应用在各自独立的进程中运行,并分配相应的文件访问权限以隔离其他应用的运行空间,你的应用不可能直接从其他应用那里激活它组件。但是对于Android系统而言你却可以这么做。因此,为了能激活另一个应用中的组件,你必须向系统传递一个消息。这个消息指明了你期望打开特定组件的意图。系统将会为你激活这个组件。

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都会在运行时绑定双方各自的组件(你可以将这些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定义了想要激活的具体组件或者具体组件的类型,且一个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发送想要展示一张图片或者打开一个网页的请求。在某些情况下,你也可为能返回一个结果而打开一个Activity,此时被打开的Activity会返回一个intent作为结果(例如,你可以发布一个intent让用户选择一个自己的联系人并把联系人信息返回给你。这个返回的intent将包含一个指向此联系人详细信息的URI地址)。

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”).

就广播接受者而言,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).

另一个类型的组件,内容提供者CP,并非由intent激活。确切的说是由ContentResolver以其为目标发送请求时被触发的。这个内容解析者CR处理所有直接与CP有关的的事务,这样发起事务的组件自己就不必和CP直接打交道了,它只要调用CR对象的方法就好了。这样的实现方式在CP和请求信息的组件间建立了一个抽象层(为了更加安全)。

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() or startActivityForResult() (when you want the activity to return a result).
  • You can start a service (or give new instructions to an ongoing service) by passing an Intent to startService(). Or you can bind to the service by passing an Intent to bindService().
  • You can initiate a broadcast by passing an Intent to methods like sendBroadcast(), sendOrderedBroadcast(), or sendStickyBroadcast().
  • You can perform a query to a content provider by calling query() on a ContentResolver.

激活四大组件组件有各自的方法:

  • 你可以通过调用startActivity()(用于启动新的Activity或者向指定的Activity传入一些新的任务) 和 startActivityForResult()(用于需要这个Activity返回一个结果) 并向它传入一个intent对象来启动一个Activity。
  • 你可以通过调用startService()并向其传入一个intent从而启动一个Service(或者对正在运行的Service发布新的指令)。或者你也可以通过调用bindService()并传入intent对象来绑定一个Service
  • 你可以通过调用像sendBroadcast(),sendOrderedBroadcast()或者sendStickyBroadcast()方法并向其传入intent来初始化一条广播
  • 你可以通过调用ContentResolver的query()方法来向内容提供者执行一次查询操作。

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的更多信息,请参见文档Intent和Intent 过滤器部分。对于启动特定组件的更多信息也会在以下章节中继续介绍: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:

  • 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.
  • 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.
  • And more

清单文件除了声明组件外还做了很多的事情,如:

  • 确定任何应用所需的用户权限,如网络访问权限或者通讯录读取权限。
  • 确定应用需要的最小API级别,这取决于应用自己使用了哪些API
  • 确定应用所需的设备软硬件特性,如摄像头,蓝牙服务或者多点触控屏幕
  • 确定应用需要的链接的API库(Android框架之外的),如谷歌地图库
  • 其他

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:

清单文件的首要任务就是告知系统此应用的有哪些具体组件。例如,清单文件可以像这样定义一个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
  • <service> elements for services
  • <receiver> elements for broadcast receivers
  • <provider> elements for content providers

你必须像这样定义四大组件:

  • <activity> 标签用于定义activity
  • <service> 标签用于定义service
  • <receiver> 标签用于定义receiver
  • <provider> 标签用于定义provider

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 Providers 如果仅仅在代码中写入而不在清单文件中定义的话,那么对系统而言它们就是不可见的,也永远不可能被运行。然而,广播接收器却既可以在清单文件中注册或者在代码中进行动态的注册(注册为BroadcastReceiver类的实例)。代码中向系统动态注册广播接收器需要调用registerReceiver()方法。

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

关于清单文件的更多内容,请参考文档AndroidManifest.xml部分。

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.

如上所述,对于激活组件,你可以利用一个Intent来打开Activity,Service和Broadcast Receivers,并可在此期间,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.

系统识别可以执行此intent的组件的方法是,在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 element as a child of the component’s declaration element.

当你在你的应用清单文件中声明一个Activity时,你也可以同时声明一个intent过滤器。这个过滤器定义了此Activity的功能,这样它就可以对来自其他应用的intent进行响应。通过为组件添加<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的邮件APP,那么就可像这样为响应“ send 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.

关于更多关于意图过滤器的内容,请参见文档Intents 和 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.

Android设备多种多样,而它们并非都提供同一种功能特性。为了防止不满足你应用软硬件需求的手机安装它,那么在明确它可以支持哪些设备就显得尤为必要了,为此你需要在清单文件中写明应用的软硬件需求。绝大多数这样的声明都是信息性的,系统并不读取它们。但是如GooglePlay这样的外部服务(应用商店)会读取它们,以便于用户在搜索应用时为器其提供筛选。

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:

例如,如果你的应用需要摄像头并且使用Android 2.1系统(第7级的API)所提供的API,那么你应该像这样在清单文件中写明这些需求。

<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的手机就不能在GooglePlay应用商店中安装它。

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.

不过你也可以声明你的应用需要摄像头,但不是必须的。在此情况下,你必须将required属性设置为假,并且在设备运行时动态检测摄像头是否存在,视设备情况决定是否关闭一些应用中与摄像头有关的特性。

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

关于如何管理应用功能以适应不同设备的更多内容,请参加文档设备兼容性部分。

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).

APP不仅仅包含代码,它需要独立于代码之外的资源文件,如图片、声音和任何与应用视觉展示的相关的内容。例如,你应该定义动画、菜单、样式、颜色和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构建工具都会为其分配一个唯一的整数ID。你可以在XML资源文件或代码中使用这些ID以引用对应的资源。例如,如果你的应用包含了一个名为logo.png的图片文件(保存在 res/drawable/ directory 目录下),那么SDK工具就会生成一个对应的名为R.drawable.logo的资源ID。你可用此ID来引用这个图片资源并将其插入到你的UI界面中。

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界面文案,你就可以将文案翻译成不同语言并独立保存。然后,Android系统会根据你加在资源文件夹名称中的语言标识符(如 res/values-fr 表示存储法文文案)以及用户的语言设置选择合适的文案进行展示。

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.

Android 支持多种可替换资源的文件标识符。这些标识符是一种你追加在资源目录名称中的一个短字符串。这样的追加是为了指明这些资源应该在哪些机型中使用。另一个例子,你也应该根据设备屏幕方向和大小为你的Activity设置不同的布局。比如,屏幕在竖直状态下(高屏),你也许需要一个包含垂直button的布局,但是当屏幕处于水平状态(宽屏)时,按键就应该被调整为水平态。为了根据屏幕方向适配布局,你可以定义两套布局文件,并对两布局文件目录使用适当的标识符。那么系统就会根据当前屏幕方向自动采用对应的布局。

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.

更多关于可包含在你应用中的多种资源的信息,以及如何为不同设备创建可替换资源,请参阅“提供资源”部分。


更多

CONTINUE READING ABOUT 拓展阅读

Intents and Intent Filters 意图和意图过滤器

Information about how to use the Intent APIs to activate app components, such as activities and services, and how to make your app components available for use by other apps.

关于如何使用Intent API激活如Activity或Service等应用组件以及如何让你的应用组件可以被其他应用调用。

Activities

Information about how to create an instance of the Activity class, which provides a distinct screen in your application with a user interface.

关于如何创建一个Activity实例,此实例会在你应用的UI中提供一个独立的窗口。

Providing Resources 提供资源

Information about how Android apps are structured to separate app resources from the app code, including how you can provide alternative resources for specific device configurations.

YOU MIGHT ALSO BE INTERESTED IN: 你也许感兴趣的

Device Compatibility 设备兼容性

Information about Android works on different types of devices and an introduction to how you can optimize your app for each device or restrict your app’s availability to different devices.

关于Android是如何在不同类型设备中运行,以及介绍针对具体机型如何优化你的应用或者如何根据具体机型限定应用的功能。

System Permissions 系统权限

Information about how Android restricts app access to certain APIs with a permission system that requires the user’s consent for your app to use those APIs.

关于Android如何通过权限系统控制应用使用某些API,其中这些权限由用户审批是否分配给应用。


由于笔者水平有限,内容仅供参考,如有翻译不当之处,欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值