Android官方文档—引言(应用程序基础知识)

应用程序基础知识

Android应用程序是使用Java语言编写。AndroidSDK开发工具将您的代码以及所有数据,资源文件编译打包到APK(Android安装包,一个带有.apk为后缀的文件)中,一个APK文件包含Android应用的所有内容,是用于安装app到Android设备的文件。

一旦app安装在设备上后,每个Android应用都位于自己的安全沙箱中:

  • Android操作系统是一个多用户Linux系统,其中每个应用程序都是不同的用户。
  • 默认情况下,系统分配个每个app一个特有的用户id(这个id仅仅系统可见,app本身无法感知),系统为app中所有文件设置了权限,因此只有分配了用户id的app才可以访问它们。
  • 每一个进程都有自己的虚拟机(VM),因此app的代码彼此隔离运行。
  • 默认情况下,每个app都在自己的Linux进程中运行,当需要执行任何应用程序的组件时,Android会启动该进程,然后在不再需要时或系统必须恢复其他应用程序的内存时关闭该进程。

这样一来,Android系统实现了最小权限原则,也就是说,每个app只能访问其运行所需的组件,不能访问系统没有给予其权限的部分,因此形成了非常安全的运行环境。

然而,有一种方式可以让某个app与其他app或系统服务共享数据:

  • 可以使给两个app共享同一个Linux用户id,这样他们就可以共享文件。为了节约系统资源,具有相同用户ID的应用程序也可以安排在同一个Linux进程中运行并共享同一个VM(应用程序也必须使用相同的证书进行签名)。
  • app可以通过请求权限去访问设备数据,如用户通讯录、短信、SD卡、相机、蓝牙等等。用户必须明确的准许这些权限,想了解更多,请参阅Working with System Permissions

这涵盖了有关Android应用程序如何在系统中存在的基础知识。本文档的其余部分将向您介绍:

  • 定义应用程序的核心框架组件。
  • 清单文件,用于为应用程序声明组件和所需的设备功能。
  • 与应用程序代码分开的资源,允许您的应用程序优雅地针对各种设备配置优化其行为。

应用程序组件


应用程序组件是Android应用程序的基本组成单位,每个组件都是系统可以通过其进入您的应用程序的不同点。并非所有组件都是用户的实际入口点,有些组件相互依赖,但每个都作为自己的实体存在并扮演特定角色 - 每个角色都是一个独特的单位,可帮助定义应用程序的整体行为。

应用程序有4中不同的组件,每种类型都有不同的用途,并且具有独特的生命周期,用于定义组件的创建和销毁方式。

4种类型的组件:

Activities

activity表示具有用户界面的单个屏幕,例如,一个email应用程序可能有一个activity用于展示收件箱列表,另一个activity用于撰写邮件,还有一个activity用户阅读email,虽然这些activity协同工作以在email应用程序中形成一致的用户体验,但每个活动都独立于其他活动。因此,别的app可以启动它的activity(如果email应用程序允许)。比如,相机app可以启动邮件app让用户撰写邮件分享图片。

activity 是一个继承了Activity的子类,想了解更多,请参阅Activities developer guide。

Services

service是在后台运行以执行长时间运行操作或执行远程进程工作的组件。service不提供用户界面,当用户在其他应用程序时,service还可以在后台播放音乐,或者在不打断用户与activity交互的情况下,从网络中获取数据。另外一个的组件(如activity)可以启动service,让他执行,或绑定到它以与之交互。

service是一个继承了Service的子类,想了解更多,请参阅Services developer guide。

Content providers

content provider 用于管理一组共享的应用程序数据。您可以将数据保存至文件、SQLite数据库、网络、或您的应用可以访问的任何其他持久存储位置。通过content provide,别的app可以用查询甚至修改数据(如果被允许),比如,Android系统提供了用于管理用户通讯录的content provider,因此,具有适当权限的任何应用程序都可以查询部分content provider程序(例如ContactsContract.Data)以读取和写入特定人员的信息。

content provider 为自己的app用于读取或写入数据,也是非常有用的。比如示例程序中记事本app使用content provider保存笔记。

content provider是一个继承了ContentProvider的子类并且必须实现一组标准API,以使其他应用程序能够执行事务。想了解更多,请参阅Content Providers developer guide。

Broadcast receivers

广播接收器是用于响应系统全局通知的组件,很多广播都来源于系统,比如息屏,电量过低,拍照等等,app也可以自己定义广播,比如让其他应用程序知道某些数据已下载到设备并可供他们使用。尽管广播接收器不能提供用户界面,但它可以在状态栏上创建通知用于提醒用户广播事件被执行了,但更常见的是,广播接收器只是其他组件的“网关”,旨在完成非常少量的工作。例如,它可以会启动服务以根据事件执行某些工作。

广播接收器是一个继承了BradcastReceiver的子类,每一个广播接收器都传递了一个Intent对象。想了解更多,请参阅BroadcastReceiver类。

Android系统设计的一个独特方面是任何应用程序都可以启动另一个应用程序的组件。例如,如果你想让用户使用摄像头拍摄一张照片,可能有另一个应用程序可以做到,您的应用程序可以直接使用它,而不是自己开发一个拍照activity。您无需合并甚至链接到相机应用程序中的代码,照片甚至会返回到您的应用,以便您可以使用它。对于用户来说,好像相机应用实际上是您应用的一部分。

当系统启动组件时,它会启动该应用程序的进程(如果它尚未运行),然后实例化组件所需的类,比如如果你的app启动相机app中的拍照activity,则这个activity运行在相机应用的进程中,而不是你的应用进程中,因此,与大多数其他系统上的应用程序不同,Android应用程序没有单个入口点(例如,没有main()函数)。

因为系统对每一个独立运行于进程中的app的文件权限进行了限制,所以您不能直接去激活别的app的组件,然而,Android系统可以做到,要在另一个应用程序中激活组件,您必须向系统发送一条消息,指明您启动特定组件的意图。然后,系统会为您激活组件。

激活组件

四种组件类型中的三种—activities,services和broadcast receiver都是通过名为Intent的异步消息激活,Inten在运行时将单个组件相互绑定起来(您可以将它们视为请求其他组件操作的信使),无论该组件是属于您的应用还是其他应用。

使用Intent对象创建intent,它定义了一个消息来激活特定组件或特定类型的组件 , 一个intent可以分别是显式的或隐式的。

对于activities和services,intent定义要执行的操作(如查看或者发送一些内容)并且可以指定要处理的数据的URI(启动组件可能需要知道的其他事项),比如,一个intent可能为activity传达一个查看图片,或者打开网页的请求,在有些情况下,你可以启动一个activity为了接收其结果,这时,activity也可以将返回结果存入intent中(比如,你可以发起一个intent让用户选择一个个人联系人并将其返回给您,这个返回意图包括指向所选联系人的URI)。

对于广播接收器,意图只是简单的定义广播的通知(例如,指示设备电池电量低的广播仅包括指示“电池电量低”的已知操作字符串)。

另一种组件类型,content provider 不是通过intent激活,而是通过作为ContentResolver请求目标时被激活。ContentResolver处理content provider的所有直接事务,因此只需要调用ContentResolver对象上的方法,达到与content provider组件分离的目的。这在内容提供者和请求信息的组件之间留下了一层抽象(为了安全起见)。

有各种方法可以激活每种类型的组件:

  • 您可以启动一个activity(或者给他一些新东西)通过将Intent传递给startActivity()或者startActtivityForResult()(当您需要从这个activity中获取返回结果时)。
  • 您可以通过将Intent传递给startService()来启动服务(或向正在进行的服务发出新指令)。或者您可以通过将Intent传递给bindService()来绑定到服务。
  • 您可以通过将Intent传递给sendBroadcast(),sendOrderedBroadcast()或sendStickyBroadcast()等方法来启动广播。
  • 您可以通过在ContentResolver上调用query()来对content provider执行查询。

有关使用意图的更多信息,请参阅Intent和Intent Filters文档。以下还提供了有关激活特定组件的更多信息:Activities,Services,BroadcastReceiver和Content Providers。

清单文件


在Android系统启动应用程序组件之前,系统必须通过读取app的AndroidManifest.xml(清单文件)文件得知app中存在哪些组件,您必须在这个文件中声明您app中存在所有的组件,它必须位于app项目目录的根目录下。

除了声明应用程序的组件之外,清单还会执行许多操作,例如:

  • 定义app请求的用户权限,例如Internet访问权限或对用户联系人的读访问权限。
  • 根据应用使用的API,声明应用所需的最低API级别。
  • 声明应用程序使用或要求的硬件和软件功能,例如相机,蓝牙服务或多点触控屏幕。
  • 应用程序需要链接的API库(除Android框架API之外),例如Google Maps库。
  • 更多

声明组件

清单的主要任务是告知系统应用程序中有哪些组件,比如清单文件可以通过以下代码声明一个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属性指向标识应用程序的图标的资源 。

在<actitvity>元素中,android:name属性指定Activity子类的完全类名,android:label属性指定一个字符串,用作activity的对用户可见标签。

你必须用这种方式声明app中所有的组件:

在您的代码中的Activities, services, 和content providers如果未在清单文件中声明,则对系统不可见,因此永远不会运行。但是,广播接收器可以在清单中声明,也可以在代码中动态创建(作为BroadcastReceiver对象),并通过调用registerReceiver()向系统注册。

有关如何为应用程序构建清单文件的更多信息,请参阅AndroidManifest.xml文件文档。

声明组件功能

如上所述,在激活组件时,你可以使用intent来启动activities,services,broadcast receivers。您可以通过在intent中显式命名目标组件(使用组件类名称)来实现。然而,意图的真正强大的地方在于隐式intent的概念,一个隐式的intent只是简单地描述了要执行动作的类型(以及(可选)您要执行操作的数据),允许系统自己在设备中找到可以执行此类动作的组件。如果有多个组件可以执行intent中描述的动作类型,需要通过用户去选择哪一个组件去执行。

系统识别可以响应intent的组件的方式是通过将接收到的意图与设备上其他应用程序的清单文件中提供的intent filters进行比较。

当您在app清单文件中声明一个activity时,您可以选择包含intent filters来声明这个activity的功能,以便它可以响应来自其他应用程序的意图。您可以通过添加<intent-filter>元素作为组件的子元素,用来声明组件的intent filters。

例如,您要创建一个电子邮件app其中有个activity用于撰写邮件,您可以声明一个intent filter 用来响应“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>

 然后,如果另一个app创建了动作为ACTION_SEND的intent传给startActivity(),系统可能启动你所声明的activity,因此用户可以起草并发送电子邮件。

有关创建intent filter的更多信息,请参阅Intent和Intent Filters文档。

声明应用程序要求

Android支持各种各样的设备,并非所有设备都提供相同的功能和特性。为了防止您的app安装在缺少应用所需功能的设备上,通过在清单文件中声明设备和软件要求,明确定义应用支持的设备类型的配置文件非常重要.这些声明中的大部分仅供参考,系统不会读取它们,但Google Play等外部服务会读取它们,以便在用户从其设备搜索应用时为其提供过滤功能。

例如,如果您的应用需要相机并使用Android 2.1(API级别7)中引入的API,则应在清单文件中将这些声明为:

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

这样,没有相机或者Android版本低于2.1的设备无法从Google Play中安装你的app了。

但是,您也可以声明您的应用使用相机,但不需要它。在这种情况下,您的应用必须将所需属性设置为“false”,并在运行时检查设备是否具有摄像头并根据需要禁用任何摄像头功能。

有关如何管理应用程序与不同设备的兼容性的更多信息,请参阅Device Compatibility文档。

应用程序资源


Android应用程序不仅仅是代码,还包括需要与源代码分开的资源文件,例如图像,音频文件以及与应用程序的视觉呈现相关的任何内容。例如你需要定义动画、菜单、样式、颜色以及activity为用户提供交互的布局xml文件。使用应用程序资源可以轻松更新应用程序的各种特征而无需修改代码,并且通过提供多组备用资源,使您能够针对各种设备配置(例如不同的语言和屏幕大小)优化应用程序。

对于您在Android项目中包含的每个资源,SDK构建工具定义唯一的ID,您可以在代码中或者在xml资源文件中使用它 来引用这些资源。例如,如果您的应用包含名为logo.png的图像文件(保存在res / drawable /目录中),SDK工具生成名为R.drawable.logo的资源ID,您可以使用它来引用图像并将其插入用户界面。

提供与源代码分开的资源的最重要方面之一是您能够为不同的设备配置提供备用资源,例如,通过在XML中定义UI字符串,您可以将字符串转换为其他语言,并将这些字符串保存在单独的文件中,然后,根据您附加到资源目录名称的语言限定符(例如res / values-fr /用于法语字符串值)和用户的语言设置,Android系统会将适当的语言字符串应用于您的UI。、

Android为你的备用资源支持许多不同的限定符。限定符是一个短字符串,包含在资源目录的名称中,以便定义应使用这些资源的设备配置。另一个例子,您应该经常为您的activity创建不同的布局,具体取决于设备的屏幕方向和大小,例如,当设备屏幕处于纵向(高)时,您可能希望布局中的按钮是垂直的,但是当屏幕处于横向(宽)时,按钮应水平对齐。要根据方向更改布局,可以定义两个不同的布局,并将相应的限定符应用于每个布局的目录名称。然后,系统根据当前设备方向自动应用适当的布局。

有关可以包含在应用程序中的各种资源以及如何为不同设备配置创建备用资源的更多信息,请参阅Providing Resources

猜你喜欢

转载自blog.csdn.net/weixin_42703445/article/details/82849009