Doc-Instroduction

来源:互联网 发布:建筑外观上色软件 编辑:程序博客网 时间:2024/06/06 20:42

Instroduction

https://developer.android.com/guide/index.html

1. App Fundamentals

  每个Android App都存活在独立的安全沙箱内,具备下面4点特性:

  1. Android操作系统是多用户的Linux操作系统,每个app都是一个独立的user用户;
  2. 系统为每个app分配一个唯一的用户ID,对应的app文件只有这个用户ID的app才有访问权限 ;
  3. 每个App都运行在自己独立的VM里,App间互相独立;
  4. 当需要执行App的组件时,才会启动App进程,当任务结束或者系统内存回收时会停止进程;

      安卓四大组件:Activity、Service、ContentProvider、BroadcastReceiver。激活组件需要使用Intent这个异步消息,消息类型有两种:显式类型和隐式类型,显式类型直接指定组件的类名,隐式类型通过action指定。

      注意:如果使用Intent启动Service,要使用显式类型的Intent,隐式类型的Intent有安全风险,无法确认哪个Service会响应这个Intent,并且用户无法看到哪个Service启动了,从Android 5.0(API21)开始,对于使用隐式Intent启动Service的操作,系统会直接抛出异常,所以声明Service的时候不要添加<intent-filter\>描述。

      Android系统会运行在各种平台之上,但不是所有的平台都能提供应用要求的特性,所以需要在应用的manifest.xml中声明App运行需要的条件,应用本身并不会读取这些声明,但是外部服务如Google Play会读取这些声明,从而过滤出能在当前设备环境运行的应用。

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

2. DeviceCompability

  设备兼容性包括:DeviceFeatures、PlatformVersion、ScreenConfiguration。

  设备特性(Device Features):每个设备特性都有一个唯一的ID标识,比如磁罗盘传感器的FEATURE_SENSOR_COMPASS、App小部件的FEATURE_APP_WIDGETS等,如果应用强依赖某一特性,那么可以禁止用户安装这个应用,或者降级处理。

  用户在 Google Play 应用商店搜索时,Google Play 会读取这个应用的uses-feature声明,从而过滤掉这个应用。

<manifest ... >    <uses-feature android:name="android.hardware.sensor.compass"                  android:required="true" />    ...</manifest>

  在应用内降级处理

PackageManager pm = getPackageManager();if (!pm.hasSystemFeature(PackageManager.FEATURE_SENSOR_COMPASS)) {    // This device does not have a compass, turn off the compass feature    disableCompassFeature();}

  平台版本(Platform Version):主要设置minSdkVersion和targetSdkVersion属性

<manifest ... >    <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />    ...</manifest>

  The minSdkVersion attribute declares the minimum version with which your app is compatible and the targetSdkVersion attribute declares the highest version on which you’ve optimized your app.

  targetSdkVersion的定义表明应用需要后向兼容以前的Behaviors,新版本的系统要和之前的Behaviors习惯保持一致。,比如AlarmManager,从API19开始系统把Alarm的处理改为批量处理的策略,不再是之前每次时间一到就唤醒设备,以此提高电源效率。如果需要保持之前每次Alarm一到就唤醒设备的习惯,需要把targetSdkVersion设置为API18,这样即使在新的系统上也能保持以前的处理习惯Behaviors。

  屏幕配置(Screen Configuration):为了根据屏幕对设备进行分类,安卓定义了两种设备特性:screen size (屏幕的物理尺寸)和screen density(屏幕上物理尺寸的密度DPI),系统会根据实际的设备尺寸自动选择最合适的UI布局和图片资源。

  四种size:small, normal, large, xlarge

  不同density:mdpi(medium), hdpi(hdpi), xhdpi(extra high), xxhdpi(extra-extra high), …

3. System Permissions

  Android是一个权限隔离的系统,每个应用都是一个独立的user,所以必须单独申请权限,根据权限的敏感度,系统会自动赋予权限或者提示用户授予权限。

3.1 Requesting permissions

  应用需要的权限在manifest中声明,普通权限系统会自动授予,敏感权限系统会提示用户显式授予:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.android.app.myapp" >    <uses-permission android:name="android.permission.RECEIVE_SMS" />    ...</manifest>

  系统获取权限的方式由系统版本和targetSdkVersion决定:如果系统版本>=6.0(API23)并且targetSdkVersion>=23,应用是在运行时请求权限,而且用户可以随时撤销权限,所以每次使用权限之前,应用都需要检查是否有这个权限;其他情况下(系统版本<6.0||targetSdkVersion<23)系统是在安装应用时请求授权,覆盖安装时如果添加了新权限,系统会再次请求用户授权,一旦应用安装完成,用户只能通过卸载应用才能撤销已授予的权限。执行没有权限的操作,系统会把日志打印到System.log。

  安卓系统还会进行权限调整,比如新版本对某个之前不需要授权的操作增加了权限,而旧版本的应用并没有申请这个权限,为了保证应用能够正常安装运行,系统会根据targetSdkVersion自动增加这些权限申请。

  所有的敏感权限都以权限组(Permission Groups)的方式管理,系统不会以某个具体权限的粒度提示用户,而是以权限组的粒度申请授权,比如应用需要申请READ_CONTACTS权限,系统只会提示用户该应用需要访问设备通讯录,用户授权后,应用默认也获取到了写权限WRITE_CONTACTS。 属于敏感权限组的权限见最后的表格。

3.2 Defining permissions

  关于安卓应用签名的机制可以读一下这两篇文章安卓签名过程和安卓签名验证过程。

  签名过程 的主要步骤:首先生成私钥 -> 对apk中的所有Entry(文件)分别计算SHA1摘要+Base64编码,写入MANIFEST.MF文件 -> 对整个MANIFEST.MF文件计算SHA1摘要+Base64编码,写入CERT.SF文件头部的SHA1-Digest-Manifest属性 -> 再对MANIFEST.MF文件的每个属性快分别计算SHA1摘要+Base64编码,继续写入CERT.SF文件完成 -> 对CERT.SF文件使用私钥计算签名,将签名和包含公钥信息的数据证书一同写入CERT.RSA保存完成。

  签名的安全性证明:如果Apk的任意一个文件被修改,MANIFEST.MF中的摘要将不再匹配,签名验证过程会报错;如果修改文件后同步更新了MANIFEST.MF中的摘要信息,CERT.SF中的摘要还是不能匹配,签名验证过程还是会报错;如果再同步更新了CERT.SF中的摘要,CERT.RAS中记录数字签名和新签名还是不一致,而到这一步数字签名因为没有数字证书对应的私钥,所以无法再伪造。所以APK的任意一个文件被修改后,必须要重新签名,不然会提示安装失败。

  签名验证过程 的主要步骤:直接对system_process进程打断点跟踪,验证过程和签名过程对应。安装的主入口在PackageManagerServer.java#installPackageLI(),主要涉及的类包括:PackageManagerServer、PackageParser、StrictJarFile、JarVerifier;

# com.android.server.pm.PackageManagerServer.javaprivate void installPackageLI(InstallArgs args, PackageInstalledInfo res) {  ...  try {      pp.collectCertificates(pkg, parseFlags);      pp.collectManifestDigest(pkg);  } catch (PackageParserException e) {      res.setError("Failed collect during installPackageLI", e);      return;  }  ...}

  签名验证的过程:主要是使用/META-INFO目录下的签名文件(.MF/.SF/.RSA),对当前Apk中各个文件的一致性进行校验,而不是已安装应用和新应用之间进行校验,验证的目的是防止应用被篡改。如果修改了应用并且重新签名了,只要Apk签名是正确的,应用还是能够被正常安装。

  应用安装的时候,Android系统会给安装包分配一个单独的Linux User ID,只要应用不卸载,这个ID就是固定不变的。一般来说出于安全的需要,每个应用都独立分配一个UID,如果两个App有着相同的签名,系统才会分配相同的UID。应用创建的所有文件数据都会被这个应用的UID赋值标记,以防止被其他应用非法访问。

  自定义权限需要在Manifest中作事先声明,需要注意的是系统不允许多个应用定义相同的权限名称,除非应用使用了相同的证书签名。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.myapp" >    <permission android:name="com.example.myapp.permission.DEADLY_ACTIVITY"        android:label="@string/permlab_deadlyActivity"        android:description="@string/permdesc_deadlyActivity"        android:permissionGroup="android.permission-group.COST_MONEY"        android:protectionLevel="dangerous" />    ...</manifest>

  可以为四大组件定义访问权限检查:

<activity android:permission=""/> 限制谁能启动这个Activity( SecurityException)<service android:permission=""/> 限制谁能启动或者绑定这个Service( SecurityException)<receiver android:permission=""/> 限制谁能发送广播到这个BroadcastReceiver<provider android:permission="" android:readPermission="" android:writePermission=""/> 限制谁能访问ContentProvider里的数据,读写分离

  URI permissions:对于ContentProvider的访问可以使用per-URI permissions进行更精细的权限控制,调用者启动activity或者返回结果给caller时,可以在Intent中设置Intent.FLAG_GRANT_READ_URI_PERMISSION/Intent.FLAG_GRANT_WRITE_URI_PERMISSION,授权接收Activity访问URI数据的权限,此时目标Activity不需要具有访问ContentProvider的权限就可以访问这个数据了。
  

0 0