前言
Android是一个开源的,基于Linux的移动设备操作系统,主要用于移动设备,如智能手机和平板电脑。Android是由谷歌及其他公司带领的开放手机联盟开发的。
谷歌在2007年发布了第一个测试版本的 Android 软件开发工具包(SDK),第一个商业版本的 Android 1.0,则发布于2008年9月。
Android 源代码是根据自由和开放源码软件许可证。谷歌发布的大部分代码遵循 Apache 许可证2.0版,Linux 内核的变化遵循 GNU 通用公共许可证版本2。
Android 操作系统是一个软件组件的栈,为广泛的设备和机型而创建,下图所示为 Android 平台的主要组件。
Android软件栈
Android是基于Linux内核的(Linux内核提供了安全性、内存管理、进程管理、网络协议和驱动模型等核心系统服务),Linux内核层为各种硬件提供了驱动程序,如显示驱动、相机驱动、蓝牙驱动、电池管理等等。
Binder(IPC)驱动:
基于OpenBinder框架的一个驱动,用于提供 Android平台的进程间通信功能。,虽然linux内核本身已经提供了这些功能,但Android系统很多服务都需要用到该功能,为了某种原因其实现了自己的一套。
电源管理(Power Management):
一个基于标准Linux电源管理系统的轻量级Android电源管理驱动,针对嵌入式设备做了很多优化,比如电池电量。
USB:
驱动 一个基于标准 Linux USB gadget驱动框架的设备驱动,Android的USB驱动是基于gaeget框 架的。
**硬件抽象层**提供标准界面,向更高级别的 [**Java API 框架**]显示设备硬件功能。HAL 包含多个库模块,其中每个模块都为特定类型的硬件组件实现一个界面,例如相机或蓝牙模块。当框架 API 要求访问设备硬件时,Android 系统将为该硬件组件加载库模块
通过一些c/c++库来为Android提供主要的特性支持,如SQLite提供了数据库的支持,WebKit库提供了浏览器内核的支持等等。
同时在这一层的还有Android运行时库提供了一些核心库,能够允许开发者使用JAVA语言来编写Android应用。还包含了虚拟机Dalvik但之后改为了ART运行环境,使每一个Android应用都有自己的进程,并且都有一个自己的Dalvik虚拟机实例,相较于JAVA的虚拟机Dalvik是专门为移动设备定制的,针对内存和CPU性能都有了优化。
Android的系统运行库包含两部分,一个是系统库,另一个是运行时,Android系统的各个组件都在使用c/c++库,这些功能是通过Android应用框架暴露给开发人员的,系统库是应用程序框架的支撑,是连接应用程序框架层与Linux内核层的重要纽带,在程序运行时中执行其运行时分为核心库和Dalvik虚拟机两部分。
系统自带的库
除了之上的主要系统类库之外,还有Android NDK,即Android原生库。NDK为开发者提供了直接使用Android系统资源,并采用C 或C++语言编写程序的接口。因此,第三方应用程序可以不依赖于Dalvik虚拟机进行开发
。NDK提供了一系列从C或C++生成原生代码所需要的工具,为开发者快速开发 C 或 C++的动态库提供方便,并能自动将生成的动态库和Java 应用程序一起打包成应用程序包文件,即 .apk文件
Android运行时:
核心库:提供了Java语言API中的大多数功能,同时也包含Android的一些核心API.如android.OS、android.net、android.media等。
Dalvik虚拟机:Android程序不同于J2ME程序(是java的一种运行环境),每个Android应用都运行在自己的进程上,享有Dalvik虚拟机为它分配的专有实例,并在该实例中执行。Dalvik虚拟机是一种基于寄存器的Java虚拟机,而不是传统的基于栈的虚拟机,并进行了内存资源使用的优化以及支持多个虚拟机的特点。设计成在一个设备可以高效地运行多个虚拟机。Dalvik虚拟机可执行文件格式是(.dex),dex格式是专为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统
。 大多数虚拟机包括JVM都是基于栈的,而Dalvik虚拟机则是基于寄存器的,所有的类都经由JAVA编译器编译,然后通过SDK中 的 “dx” 工具转化成.dex格式由虚拟机执行。Java编译器将Java源文件转为class文件,class文件又被内置的dx(具有转化为dex格式文件,该格式文件针对最小内存使用做了优化,这种文件在Dalvik虚拟机上注册并运行)。在一些底层功能方面,例如线程和低内存管理等.Dalvik虚拟机是依赖Linux内核的。
Dalvik虚拟机是基于Apache的Java虚拟机,并被改进以适应低内存、低处理器速度的移动设备环境。Dalvik虚拟机依赖于Linux内核,实现进程隔离与线程调度管理、安全和异常管理、垃圾回收等重要功能。但Dalvik虚拟机并非传统意义上的Java虚拟机(JVM)。Dalvik虚拟机不仅不按照Java虚拟机的规范来实现而且两者不兼容。
Android的运行环境,我们学过java的都知道,java程序的运行需要java的核心包的支持,然后通过JVM虚拟机来运行我们的应用程序,这里Android Runtime里的Core Libraries就相当于java的JDK,是运行android应用程序所需要的核心库,Dalvik Virtual Machine就相当于JVM,这时Google专为Android开发的运行android应用程序所需的虚拟机。
对于运行 Android 5.0(API 级别 21)或更高版本的设备,每个应用都在其自己的进程中运行,并且有其自己的 Android Runtime (ART) 实例。ART 编写为通过执行 DEX 文件在低内存设备上运行多个虚拟机,DEX 文件是一种专为 Android 设计的字节码格式,经过优化,使用的内存很少。编译工具链(例如 Jack)将 Java 源代码编译为 DEX 字节码,使其可在 Android 平台上运行。
通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 形成创建 Android 应用所需的构建块,它们可简化核心模块化系统组件和服务的重复使用,包括以下组件和服务:
开发者可以完全访问 Android 系统应用使用的框架 API。
Android 随附一套用于电子邮件、短信、日历、互联网浏览和联系人等的核心应用。平台随附的应用与用户可以选择安装的应用一样,没有特殊状态。因此第三方应用可成为用户的默认网络浏览器、短信 Messenger 甚至默认键盘(有一些例外,例如系统的“设置”应用)。
系统应用可用作用户的应用,以及提供开发者可从其自己的应用访问的主要功能。例如,如果您的应用要发短信,您无需自己构建该功能,可以改为调用已安装的短信应用向您指定的接收者发送消息。
Android应用程序由一些零散的有联系的组件组成,通过一个工程manifest绑定在一起。在manifest中,描述了每一个组件以及组件的作用,其中有6个组件,它们是Android应用程序的基石,其中以下四大组件为常见的组件
Activity就是我们应用程序的界面,主要用来跟我们的用户进行交互的,比如一个文本框,按钮这些就是显示在Activity上的,并且可以接收数据,传递数据到后台,然后再显示出来。
服务是运行在后台,执行长时间操作的组件。举个例子,服务可以是用户在使用不同的程序时在后台播放音乐,或者在活动中通过网络获取数据但不阻塞用户交互。
ContentProvider类似于我们的档案馆,里面存放了我们的各种数据,例如通讯录中的信息等,这个组件就是运行程序对其进行访问,然后得到里面的数据。
Broadcast Receiver不执行任何任务,仅仅是接受并响应广播通知的一类组件。大部分广播通知是由系统产生的,例如改变时区,电池电量低,用户选择了一幅图片或者用户改变了语言首选项。应用程序同样也可以发送广播通知,例如通知其他应用程序某些数据已经被下载到设备上可以使用。
组件名 | 主要功能 |
---|---|
Activities | 负责应用程序中数据的展示,是用户和应用程序之间交互的接口 |
Service | 承担大部分的数据处理工作,为其他组件提供后台服务,监控其他组件的运行状态 |
ContentProvider | 实现消息的异步接收 |
BroadcastReceiver | 为不同的应用程序之间数据共享提供统一的访问接口 |
提到Android 权限管理,业内人士都知道Google 在Android 6.0时提出了运行时权限管理机制,在Android 6.0之前,所申请的权限只需要在AndroidManifest.xml列举就可以,从而容易导致一些安全隐患,因此,在Android 6.0 时,Google 为了更好的保护用户隐私提出了新的权限管理机制
Android中的权限分为系统权限和应用自定义权限,系统权限又分为正常权限和危险权限。使用系统权限需要在manifest文件中注册权限,若是危险权限,还需要在使用时动态申请。
Normal Permissions
Normal Permission一般不涉及用户隐私,是不需要用户进行授权的,比如手机震动,访问网络等。
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
FOREGROUND_SERVICE
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MANAGE_OWN_CALLS
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_COMPANION_RUN_IN_BACKGROUND
REQUEST_COMPANION_USE_DATA_IN_BACKGROUND
REQUEST_DELETE_PACKAGES
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
SET_ALARM
SET_WALLPAPER
SET_WALLPAPER_HINTS
TRANSMIT_IR
USE_FINGERPRINT
VIBRATE
WAKE_LOCK
WRITE_SYNC_SETTINGS
Dangerous Permission
一般是涉及到用户隐私的,需要用户进行授权(动态申请),比如读取SIM卡状态、访问通讯录、SD卡读写等。
权限组 | 权限 |
---|---|
CALENDAR |
READ_CALENDAR WRITE_CALENDAR |
CAMERA |
CAMERA |
CONTACTS |
READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS |
LOCATION |
ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION |
MICROPHONE |
RECORD_AUDIO |
PHONE |
READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
SENSORS |
BODY_SENSORS |
SMS |
SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
STORAGE |
READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
Dangerous Permission一般以Permission group形式存在,只要Permission Group中某一个permission被Granted(授予),则整个Permission group下的权限均被Granted。
想要查看所有dangerous的权限, 也可以用命令:
adb shell pm list permissions -g -d
Signature permission:权限请求者只有使用和[权限声明者]相同的证书来签名的情况下,才可以使用的权限。如果证书匹配,系统会自动赋予这些权限,不需要通知或请求用户。
SignatureOrSystem: 该类权限除了上述的 Signature Permission以外,还包括那些只赋予Android System Image内的应用的权限。Android并不建议app使用这类,因为Signature Permission已经能满足大部分的需求,不管这些app是否是build在System Image里
总结:
protectionLevel | 说明 |
---|---|
normal | 表示权限是低风险的,不会对系统,用户或其他应用程序造成危害 |
dangerous | 表示权限是高风险的,系统将可能要球用户输入相关信息,才会授予此权限 |
signature | 表示只有当应用程序所用数字签名与声明引用权限的应用程序所用签名相同时,才能将权限授予给它 |
signatureOrSystem | 需要签名或者系统级应用(放置在/system/app目录下)才能赋予权限 |
system | 系统级应用(放置在/system/app目录下)才能赋予权限 |
自定义权限 | 应用自行定义的权限 |
> API:
>
> API 级别是一个对 Android 平台版本提供的框架 API 修订版进行唯一标识的整数值
>
> Android 平台提供的框架 API 使用叫做“API 级别”的整数标识符指定。 每个 Android 平台版本恰好支持一个 API 级别,但隐含了对所有早期 API 级别(低至 API 级别 1)的支持。 Android 平台初始版本提供的是 API 级别 1,后续版本的 API 级别递增。
>
> targetSdk:
>
> targetSdkVersion is the main way Android provides forward compatibility
>
> targetSdkVersion 是 Android 系统提供前向兼容的主要手段。这是什么意思呢?随着 Android 系统的升级,某个系统的 API 或者模块的行为可能会发生改变,但是为了保证老 APK 的行为还是和以前兼容。只要 APK 的 targetSdkVersion 不变,即使这个 APK 安装在新 Android 系统上,其行为还是保持老的系统上的行为,这样就保证了系统对老应用的前向兼容性。
>
>
平台版本 | API 级别 | VERSION_CODE | 备注 |
---|---|---|---|
Android 7.0 | 24 | N |
平台亮点 |
Android 6.0 | 23 | M |
平台亮点 |
Android 5.1 | 22 | LOLLIPOP_MR1 |
平台亮点 |
Android 5.0 | 21 | LOLLIPOP |
|
Android 4.4W | 20 | KITKAT_WATCH |
仅限 KitKat for Wearables |
Android 4.4 | 19 | KITKAT |
平台亮点 |
Android 4.3 | 18 | JELLY_BEAN_MR2 |
平台亮点 |
Android 4.2、4.2.2 | 17 | JELLY_BEAN_MR1 |
平台亮点 |
Android 4.1、4.1.1 | 16 | JELLY_BEAN |
平台亮点 |
Android 4.0.3、4.0.4 | 15 | ICE_CREAM_SANDWICH_MR1 |
平台亮点 |
Android 4.0、4.0.1、4.0.2 | 14 | ICE_CREAM_SANDWICH |
|
Android 3.2 | 13 | HONEYCOMB_MR2 |
|
Android 3.1.x | 12 | HONEYCOMB_MR1 |
平台亮点 |
Android 3.0.x | 11 | HONEYCOMB |
平台亮点 |
Android 2.3.4 Android 2.3.3 | 10 | GINGERBREAD_MR1 |
平台亮点 |
Android 2.3.2 Android 2.3.1 Android 2.3 | 9 | GINGERBREAD |
|
Android 2.2.x | 8 | FROYO |
平台亮点 |
Android 2.1.x | 7 | ECLAIR_MR1 |
平台亮点 |
Android 2.0.1 | 6 | ECLAIR_0_1 |
|
Android 2.0 | 5 | ECLAIR |
|
Android 1.6 | 4 | DONUT |
平台亮点 |
Android 1.5 | 3 | CUPCAKE |
平台亮点 |
Android 1.1 | 2 | BASE_1_1 |
|
Android 1.0 | 1 | BASE |
所有危险的 Android 系统权限都属于权限组。如果设备运行的是 Android 6.0(API 级别 23),并且应用的 targetSdkVersion
是 23 或更高版本,则当用户请求危险权限时系统会发生以下行为:
如果设备运行的是 Android 5.1(API 级别 22)或更低版本,并且应用的 targetSdkVersion
是 22 或更低版本,则系统会在安装时要求用户授予权限。再次强调,系统只告诉用户应用需要的权限组,而不告知具体权限。
注意:
如果targetSdkVersion小于23,即被认为是Android 6.0发布之前开发的应用, 还没有兼容6.0.
这种应用即便是被装在Android 6.0的机器上,也是采用原来的安装即授予权限逻辑, 所有权限在应用安装时全部被授权.
在Android 6.0的设备上安装targetSdkVersion小于23的应用之后, 可以在应用的设置中查看,发现所有的dangerous权限状态都是打开.
Android 6.0以下,在AndroidManifest.xml文件中注册权限即可。
Android 6.0及其以后,既要在AndroidManifest.xml文件中注册,又要动态申请危险权限。
如果执行的操作需要一个dangerous permission, 那么每次在执行操作的地方都必须check你是否有这个permission, 因为用户可以在应用设置里随意地更改授权情况, 所以必须每次在使用前都检查是否有权限.
在申请危险权限时,有些用户觉得涉及到了他的隐私内容,可能不会授权。在用户拒绝后,再提示授权危险权限的必要性,就为时已晚,用户需要去设置里打开(拒绝时设置不在提醒)。如若我们在申请权限前,就有一个温馨提示,告诉用户危险权限的必要性,用户理解后更容易授权。
参考资料:
https://blog.csdn.net/chy555chy/article/details/52976607
https://developer.android.google.cn/guide/topics/security/permissions
https://developer.android.google.cn/guide/topics/manifest/uses-sdk-element.html#target
https://www.jianshu.com/p/30cb93984c04?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
http://www.runoob.com/w3cnote/android-advance-authority-management.html
https://www.cnblogs.com/zhangmiao14/p/7427855.html