1 小序
1.0 简介
- Android操作系统是基于Linux内核的多用户系统,每个应用都是一个不同的用户;
- Andorid文件为*.apk(application package,应用包),包中含有Android应用的所有内容;
- 每个Android应用都处于各自的安全沙箱中;
- 默认情况下,系统为每个应用分配一个唯一的Linux用户ID,系统为应用中的所有文件设置权限,使只有分配相应权限的用户ID才可访问授权文件;
- 每个进程拥有自己的虚拟机(VM),应用程序独立于其他应用而运行;
- 默认情况,每个应用都在自己的Linux进程内运行,Android系统会在需要执行任何应用组件时启动该进程,在不需要该进程或系统必须为其他应用恢复内存时,关闭该进程;
1.2 应用特点
(1) Android系统中,任何应用都可启动其他应用的组件,如用户使用设备相机拍照时,另一个应用也可使用该功能,该应用不会自行产生一个Activity来拍摄照片,无需链接到相机的应用代码,秩序启动拍摄照片的相机应用中的Activity即可,完成拍摄时,系统会将照片返回到应用,对于用户而言,相机是该应用的一部分;
(2) 当系统启动某个组件时,会启动该应用的进程,并实例化该组件所需的类,如应用启动相机应用中的拍摄照片的Activity,此时Activity属于相机应用的进程(非开启应用中的进程)中运行,因此,Android应用没有单个入口点(main()函数);
(3) 由于系统在单独的进程中运行每个应用,且应用的文件权限会限制对其他应用的访问,因此应用无法直接启动其他应用中的组件,但是Android系统可以,如果要启动其他应用中的组件,向系统传递一条消息,说明启动特定组件的Intent,系统随后会启动该组件;
2 文件结构解析
2.1 文件结构
- 总文件结构
└── FirstApp
├── app
│ ├── build.gradle
│ ├── libs
│ ├── proguard-rules.pro
│ └── src
│ ├── androidTest
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── myfirstapp
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── myfirstapp
│ │ │ └── MainActivity.java
│ │ └── res
│ │ ├── drawable
│ │ │ └── ic_launcher_background.xml
│ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout
│ │ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher_round.xml
│ │ │ └── ic_launcher.xml
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── myfirstapp
│ └── ExampleUnitTest.java
├── build.gradle
├── FirstApp.iml
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle
32 directories, 33 files
- Android Studio文件结构
图 Android Studio项目文件结构
2.2 文件解读
序号 | 文件 | 描述 |
1 | app>src>main>java>com.example.myfirstapp>MainActivity | 程序入口,构建和运行应用时,系统会启动Activity的实例并加载布局 |
2 | app>src>main>res>layout>activity_main.xml | xml文件定义Activity界面布局,包含文本"Hello world!"的TextView元素 |
3 | app>src>main>AndroidManifest.xml | 清单文件,描述应用的基本特性并定义每个组件 |
4 | Gradle Scripts>build.gradle | 两个build.gradle文件,一个用于项目MyFirstApp,一个用于app模块,每个模块有自己的build.gradle文件 |
2.2.1 清单文件
- AndoridManifest.xml
Android系统启动应用组件之前,系统必须通过读取应用的清单文件确认组件存在,应用必须在此文件中声明所有组件,该文件必须位于应用项目目录的根目录中. - 作用
(1) 确定应用需要的任何用户权限,如互联网访问权限或对用户联系人的读取权限;
(2) 根据应用使用的API,声明应用所需的最低API级别;
(3) 声明应用使用或需要的硬件和软件功能,如相机,蓝牙服务或多点触摸屏幕;
(4) 声明应用需要链接的API库,如Google地图库; - 文件内容解析
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myfirstapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".DisplayMessageActivity"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
</application>
</manifest>
序号 | 元素 | 描述 |
1 | application->android:icon | 标识应用的图标对应的资源 |
2 | activity->name | 指定Activity子类的完全限定类名 |
3 | activity->label | 指定用作Activity的用户可见标签的字符串 |
- 声明应用需求
Android设备多种多样,并非所有设备都提供相同的特性和功能,避免应用安装在缺少所需硬件设备上,必须通过清单文件中声明设备和软件需求,为该应用支持的设备类型明确定义一个配置文件,其中大多数声明只是为了提供信息,系统不会读取.如应用需要相机功能,使用Android2.1(API7)中引入的API,需在清单文件中声明如下:
<manifest ... >
<uses-feature android:name="android.hardware.camera.any"
android:required="true" />
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
...
</manifest>
2.2.2 应用资源
Android应用并非只有代码,还需要与代码分离的资源,如图像,音频文件以及任何与应用的视图呈现有关的内容,如通过XML文件定义Activity界面的动画,菜单,样式,颜色和布局.借助应用资源,无需修改代码即可轻松更新应用的各种特性,通过提供备用资源集,可针对各种设备配置(如不同语言和屏幕尺寸)优化应用.
Android项目中加入的每一项资源,SDK构建工具均会为其分配唯一的整型ID编号,可利用此ID引用资源,这些资源来自于应用代码或xml中定义的其他资源,如应用包含logo.png的图像文件保存在res/drawable目录中,SDK工具会生成名为R.drawable.logo的资源ID,此ID映射到应用特定的整型数,可利用它来引用该图像,并将其插入应用界面.
3 应用组件
四种应用组件:
- Activity
- 服务
- 广播接收器
- 内容提供程序
3.1 Activity
Activity是与用户交互的入口点,表示拥有界面的单个屏幕.如电子邮件应用可能有一个显示新电子邮件列表的Activity,一个用于撰写电子邮件的Activity和一个用于阅读电子邮件的Activity.这些Activity虽然通过协作在电子邮件应用中形成一种紧密结合的用户体验,但是每个Activity都独立与其他Activity而存在,因此,其他应用可以启动其中任何一个Activity(如果电子邮件应用允许),如相机应用可以启动电子邮件应用内用于撰写新邮件的Activity,以分享图片,Activity有助于完成系统和应用程序之间的重要交互:
- 追踪用户当前关心的内容(屏幕上显示的内容),以确保系统继续运行托管Activity的进程;
- 了解之前使用的进程包含用户可能返回的内容(已停止的Activity),从而更优先保留这些进程;
- 帮助应用处理终止其进程的情况,以便用户可以返回已恢复其先前状态的Activity;
- 提供一种途径,让应用彼此之间的用户流,并让系统协调这用户流(共享);
3.2 服务
服务是一个通用入口点,用于因各种原因使用在后台保持运行状态,她是一种在后台运行的组件,用于执行长时间运行的操作或为远程进程执行作业,服务不提供界面,如当用户使用其他应用时,服务可能会在后台播放音乐或通过网络获取数据,但这不会阻断用于与Activity的交互,Activity等其他组件可以启动服务,使该服务运行或绑定到该服务,以便与其进行交互.
3.3 广播接收器
借助广播接收器组件,系统能够在常规用户流之外向应用传递事件,从而允许应用响应系统范围内的广播通知,由于广播接收器是另一个明确定义的应用入口,因此系统甚至可以向当前未运行的应用传递广播,如应用可通过调度来提醒发布通知,以告知用户即将发生的事件,而且,通过将该提醒传递给应用的广播接收器,应用在提醒响起之前无需继续运行,许多广播均由系统发起,如通知屏幕已关闭,电池电量不足或已拍摄照片的广播,应用也可发起广播,如通知其他应用某些数据已经下载到设备,并且可供其使用,尽管广播接收器不会显示界面,但可以创建状态栏通知,在发生广播事件时提醒用户,但广播接收器更常见的用途只作为通知其他组件的通道,仅执行极少量的工作,广播接收器作为BroadcastReceiver的子类实现,并且每条广播都作为Intent对象传递.
3.4 内容提供程序
内容提供程序管理一组共享的应用数据,可以将这些数据存储在文件系统,数据库,网络中或应用可访问的任何其他持久化存储位置,其他应用可通过内容提供程序查询或修改数据,如Android系统可提供管理用户联系人信息的内容提供程序,因此,任何拥有适当权限的应用均可查询内容提供程序,以读取和写入特定人员的相关信息.
3.5 组件对应的文件清单元素
序号 | 组件 | 元素 |
1 | Activity |
|
2 | 服务 |
|
3 | 广播接收器 |
|
4 | 内容提供程序 |
|
4 组件启动
4.1 描述
Activity,服务和广播接收器通过异步消息Intent启动,Intent会在运行时对各个组件进行相互绑定,Intent是其他组件请求操作的信使.需要使用Intent创建Intent对象,该对象通过定义消息来启动特定组件(显示Intent)或其他特定组件类型(隐式Intent).
(1) Activity和服务,Intent会定义要执行的操作(如查看或发送内容),并且可指定待操作数据的URI,以及正在启动的组件可能要了解的信息,如发送按钮,发送文本消息,另一个Activity获取文本框信息,此时Intent会传达对Activity的请求,执行相应操作.
(2) 广播接收器,Intent只会定义待广播的通知,如指示设备电池电量不足的广播,只包含指示"电池电量不足"的已知操作字符串;
(3) 内容提供程序,不是Intent启动,他会在成为ContentResolver的请求目标时启动,内容解析程序会通过内容提供程序处理所有直接事务,因此通过提供程序执行事务的组件便无需执行事务,而是改为在ContentResolver对象上调用方法,这会在内容提供程序与请求信息的组件间留出一个抽象层(保证安全);
4.2 启动方式
序号 | 组件 | 描述 |
1 | Activity | 向startActivity()或startActivityForResult()传递Intent或为其安排新任务 |
2 | 服务 | Android5.0(API21)及更高版本中,使用JobScheduler类调度操作,对于早期版本Android,通过向startService()传递Intent启动服务,可以通过向bindService()传递Intent绑定到该服务 |
3 | 广播接收器 | 通过向sendBroadcast(),sendOrderedBroadcast()或sendStickyBoradcast()等方法传递Intent发起广播 |
4 | 内容提供程序 | 通过在ContentResolver上调用query()对内容提供程序执行查询 |
更新ing