如何让应用程序获得系统权限以及如何使用platform密钥给apk签名?

如何让应用程序获得系统权限以及如何使用platform密钥给apk签名?,第1张

Android中许多函数只能是系统程序或者有root权限的程序才可以调用,否则会有"Permission denied"异常。所以如果开发时要调用此类函数,必须授予程序root权限。下面是两种具体的实现方法

注:两种方法都不一定适用于所有android系统。

方法一:需要在Android系统源码的环境下用make来编译:

在应用程序的 AndroidManifest.xml 中的 manifest 节点中加入 android:sharedUserId="android.uid.system" 这个属性

修改Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行

使用mm命令来编译,生成的apk就有修改系统时间的权限了。

方法二:

同上,加入android:sharedUserId="android.uid.system"这个属性。

使用eclipse编译出apk文件,但是这个apk文件是不能用的。

用压缩软件打开apk文件,删掉META-INF目录下的CERT.SF和CERT.RSA两个文件。 (这一步我跳过了(原本是无意的,后来发现下面也有提到),结果一样可以)

使

用目标系统的platform密钥来重新给apk文件签名。这步比较麻烦,首先找到密钥文件,在Android源码目录中的位置

是"build\target\product\security",下面的platform.pk8和platform.x509.pem两个文件。然

后用Android提供的Signapk工具来签名,signapk的源代码是在"build\tools\signapk"下,用法为"signapk

platform.x509.pem platform.pk8 input.apk

output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。

解释一下原理,首先加入

android:sharedUserId="android.uid.system"这个属性。通过Shared User id,拥有同一个User

id的多个APK可以配置成运行在同一个进程中。那么把程序的UID配成android.uid.system,也就是要让程序运行在系统进程中,这样就

有权限来调用那些需要系统权限的函数了。 只是加入UID还不够,如果这时候安装APK的话发现无法安装,提示签名不符,原因是程序想要运行在系统进程中

还要有目标系统的platform

key,就是上面第二个方法提到的platform.pk8和platform.x509.pem两个文件。用这两个key签名后apk才真正可以放入系

统进程中。第一个方法中加入LOCAL_CERTIFICATE := platform其实就是用这两个key来签名。

有一个问题,就是这样生成的程序只有在原始的Android系统或者是自己编译的系统中才可以用,因为这样的系统才可以拿到

platform.pk8

和platform.x509.pem两个文件。要是别家公司做的Android上连安装都安装不了。试试原始的Android中的key

来签名,程序在模拟器上运行OK,不过放到G3上安装直接提示"Package ... has no signatures that match

those in shared user android.uid.system",这样也是保护了系统的安全。

最后说一下,这个android:sharedUserId属性不只可以把apk放到系统进程中,也可以配置多个APK运行在一个进程中,这样可以共享数据,应该会很有用的。

使用手机的platform平台签名后,能够获取到系统权限。

1、在AndroidManifest.xml设置android:sharedUserId="android.uid.system"。

2、编译通过后,导出未签名的apk。

3、使用\out\host\Linux-x86\framework\signapk.jar \build\target\product\security\platform.pk8 +platform.x509.pem

4.执行“Java -jar signapk.jar platform.x509.pem platform.pk8 test.apk testSigned.apk”做平台签名得到testSigned.apk。

test.apk必须放在上面同一个目录之下。

一个新建的Android应用默认是没有权限的,这意味着它不能执行任何可能对用户体验有不利影响的 *** 作或者访问设备数据。为了使用受保护的功能,你必须包含一个或者多个标签在你的app manifest中。

1、Android 6.0中权限分为两种,普通权限和危险权限(即运行时权限,下面统称运行时权限)。

1.1普通权限

如果你的应用manifest中只申明了普通权限(也就是说,这些权限对于用户隐私和设备 *** 作不会造成太多危险),系统会自动授予这些权限。

1.2运行时权限

如果你的应用manifest中声明了运行时权限(也就是说,这些权限可能会影响用户隐私和设备的普通 *** 作),系统会明确的让用户决定是否授予这些权限。系统请求用户授予这些权限的方式是由当前应用运行的系统版本来决定的。

1.2.1 Android6.0及以上的系统

如果你的设备运行的是Android6.0(API level 23)及以上的系统,并且你的应用的targetSdkVersion也是23或者更高,那么应用向用户请求这些权限是实时的。这意味着用户可以随时取消 这些运行时权限的授权。所以应用在每次需要用到这些运行时权限的时候都需要去检查是否还有这些权限的授权。

1.2.2 Android 5.1及以下的系统

如果你的设备运行在Android5.1(API level 22)及以下的系统中,或者你的app的targetSdkVersion是22或者更低。系统会请求用户在apk安装的时候授予这些权限。

如果你的应用更新的时候添加了一个权限,系统会在用户更新应用的时候请求用户授予这个权限 , 一旦用户安装了这个应用,唯一可以取消授权的方式就是卸载掉这个应用。 注意这句话的意思,想一下如果app的targetSdkVersion是22或者以下,但是运行在Android6.0及以上的设备中会有什么问题?后面会分析这个问题 。

常常来说一个授权失败会抛出SecurityException,然而这并不是在 所有情况下都会发生。比如,发送一个广播去检查授权(SendBroadcast(Intent)),数据会被发送给所有接收者,但是当这个方法的请求返 回的时候,你不会收到任何一个因为授权失败抛出的异常,其实在大多数情况下,授权失败只会打印系统日志。

1.3自动权限调整

简单的说,如果你的app targetSdkVersion是3,而你当前运行的系统版本是4,那么在android version 4 中新添加的权限会自动添加到你的app中。

比如 WRITE_EXTERNAL_STORAGE权限是在api 4的时候添加的,而你的应用的targetSdkVersion是3,那么这个权限会自动添加到你的应用中。而且在官方商店上这个权限也会列出来(尽管可能你并不需要这个权限)。

所以建议经常更新你的targetSdkVersion到最新版本。

下面来回答上面的那个问题,如果app的targetSdkVersion是22或者以下,但是运行在android 6.0或以上版本的手机中,会发生什么?

安装过程中,会一起请求用户授予所有 权限,如果用户拒绝,将不能安装这个app,只有用户全部同意这些授权,才能安装这个应用,但是问题来了,安装好了这个应用之后,android6.0以 上的系统中,用户是可以去设置中取消授权的,而且是随时都可以取消,所以很多运行时权限可能也得不到,目前官方的做法是,如果用户取消该项授权,那么依赖 该项授权的方法的返回值为null,所以你的app可能会报空指针异常。以后是否会针对22以下的app做改变还不得而知,毕竟crash是很难让人接受 的,但是crash是由用户造成的,用户应该也可以理解。

2、普通权限和运行时权限

系统权限会被传递给两种不同的保护级别,我们所知道这两种最重要的保护级别就是普通权限和运行时权限。

2.1 普通权限

普通权限的覆盖区域是在你的app需要访问沙盒以外的数据和资源的时候,但是对用户隐私和其他app的 *** 作只有很少的影响,比如开启手电筒的权限。这个时候,系统会自动授权这些普通权限。

Normal Permissions:

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

GET_PACKAGE_SIZE

INSTALL_SHORTCUT

INTERNET

KILL_BACKGROUND_PROCESSES

MODIFY_AUDIO_SETTINGS

NFC

READ_SYNC_SETTINGS

READ_SYNC_STATS

RECEIVE_BOOT_COMPLETED

REORDER_TASKS

REQUEST_INSTALL_PACKAGES

SET_ALARM

SET_TIME_ZONE

SET_WALLPAPER

SET_WALLPAPER_HINTS

TRANSMIT_IR

UNINSTALL_SHORTCUT

USE_FINGERPRINT

VIBRATE

WAKE_LOCK

WRITE_SYNC_SETTINGS

2.2 运行时权限

运行时权限的覆盖区域是你的app想要的数据和资源涉及用户的隐私信息,或者是可能潜在的影响用户的存储数据或者其他app的 *** 作。比如,请求获取用户联系人信息的权限。如果一个app申明了运行时权限,用户必须明确的授权这些权限给app。

2.3 权限组

所有的运行时权限都属于对应的权限组,如果你的app运行在android6.0及以上系统,下面的规则都适用:

2.3.1 如果一个app在manifest中请求了一个运行时权限,而且app还没有得到这个运行时权限所在的权限组中的任何一个运行时权限授权,那么系统会d出一个对话框,描述app想要访问的运行时权限的权限组,这个对话框不会描述这个权限组中某一个特定的权限。比如,你的app想要请求READ_CONTACT权限,对话框只会描述app想要请求设备的联系人,如果用户授权通过,系统会授予app所请求的该项权限。

2.3.2 如果一个app在manifest中请求一个运行时权限,并且这个app已经在相同的权限组中有了另一个运行时权限的授权,那么系统不会d出对话框,而是会立即授予app该项运行时权限的授权。比如,一个app之前请求过一个READ_CONTACT的权限并且被授权通过,之后又请求一个WRITE_CONTACT(在同一个权限组)权限,那么系统会自动授予该权限。

其实所有权限(普通权限、运行时权限、用户自定义权限)都属于特定的权限组,但是只有运行时权限的权限组才会影响用户体验。

2.3.3运行时权限组和权限组列表

group:android.permission-group.CONTACTS

permission:android.permission.WRITE_CONTACTS

permission:android.permission.GET_ACCOUNTS

permission:android.permission.READ_CONTACTS

group:android.permission-group.PHONE

permission:android.permission.READ_CALL_LOG

permission:android.permission.READ_PHONE_STATE

permission:android.permission.CALL_PHONE

permission:android.permission.WRITE_CALL_LOG

permission:android.permission.USE_SIP

permission:android.permission.PROCESS_OUTGOING_CALLS

permission:com.android.voicemail.permission.ADD_VOICEMAIL

group:android.permission-group.CALENDAR

permission:android.permission.READ_CALENDAR

permission:android.permission.WRITE_CALENDAR

group:android.permission-group.CAMERA

permission:android.permission.CAMERA

group:android.permission-group.SENSORS

permission:android.permission.BODY_SENSORS

group:android.permission-group.LOCATION

permission:android.permission.ACCESS_FINE_LOCATION

permission:android.permission.ACCESS_COARSE_LOCATION

group:android.permission-group.STORAGE

permission:android.permission.READ_EXTERNAL_STORAGE

permission:android.permission.WRITE_EXTERNAL_STORAGE

group:android.permission-group.MICROPHONE

permission:android.permission.RECORD_AUDIO

group:android.permission-group.SMS

permission:android.permission.READ_SMS

permission:android.permission.RECEIVE_WAP_PUSH

permission:android.permission.RECEIVE_MMS

permission:android.permission.RECEIVE_SMS

permission:android.permission.SEND_SMS

permission:android.permission.READ_CELL_BROADCASTS

可以通过adb shell pm list permissions -d -g进行查看。

看到上面的dangerous permissions,会发现一个问题,好像危险权限都是一组一组的,恩,没错,的确是这样的,那么有个问题:分组对我们的权限机制有什么影响吗?的确是有影响的,如果app运行在Android 6.x的机器上,对于授权机制是这样的。如果你申请某个危险的权限,假设你的app早已被用户授权了 同一组 的某个危险权限,那么系统会立即授权,而不需要用户去点击授权。比如你的app对READ_CONTACTS已经授权了,当你的app申请WRITE_CONTACTS时,系统会直接授权通过。此外,对于申请时d出的dialog上面的文本说明也是对整个权限组的说明,而不是单个权限(ps:这个dialog是不能进行定制的)。不过需要注意的是,不要对权限组过多的依赖,尽可能对每个危险权限都进行正常流程的申请,因为在后期的版本中这个权限组可能会产生变化。

3、相关API

3.1 在AndroidManifest文件中添加需要的权限。

这个步骤和我们之前的开发并没有什么变化,试图去申请一个没有声明的权限可能会导致程序崩溃。

3.2 检查权限

if (ContextCompat.checkSelfPermission(thisActivity,

Manifest.permission.READ_CONTACTS)

!= PackageManager.PERMISSION_GRANTED) {

}else{

//

}

这里涉及到一个API,ContextCompat.checkSelfPermission,主要用于检测某个权限是否已经被授予,方法返回值为PackageManager.PERMISSION_DENIED或者PackageManager.PERMISSION_GRANTED。当返回DENIED就需要进行申请授权了

3.3 申请授权

ActivityCompat.requestPermissions(thisActivity,

new String[]{Manifest.permission.READ_CONTACTS},

MY_PERMISSIONS_REQUEST_READ_CONTACTS)

该方法是异步的,第一个参数是Context;第二个参数是需要申请的权限的字符串数组;第三个参数为requestCode,主要用于回调的时候检测。可以从方法名requestPermissions以及第二个参数看出,是支持一次性申请多个权限的,系统会通过对话框 逐一 询问用户是否授权。

3.4 处理权限申请回调

@Override

publicvoidonRequestPermissionsResult(intrequestCode,

String permissions[],int[] grantResults) {

switch(requestCode) {

case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {

// If request is cancelled, the result arrays are empty.

if(grantResults.length >0&&grantResults[0] == PackageManager.PERMISSION_GRANTED) {

// permission was granted, yay! Do the contacts-related task you need to do.

}else{

// permission denied, boo! Disable the functionality that depends on this permission.

}

return

}

}

}

ok,对于权限的申请结果,首先验证requestCode定位到你的申请,然后验证grantResults对应于申请的结果,这里的数组对应于申请时的第二个权限字符串数组。如果你同时申请两个权限,那么grantResults的length就为2,分别记录你两个权限的申请结果。如果申请成功,就可以做你的事情了!

那么将上述几个步骤结合到一起就是:

// Here, thisActivity is the current activity

if (ContextCompat.checkSelfPermission(thisActivity,

Manifest.permission.READ_CONTACTS)

!= PackageManager.PERMISSION_GRANTED) {

// Should we show an explanation?

if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,

Manifest.permission.READ_CONTACTS)) {

// Show an expanation to the user *asynchronously* -- don't block

// this thread waiting for the user's response! After the user

// sees the explanation, try again to request the permission.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(thisActivity,

new String[]{Manifest.permission.READ_CONTACTS},

MY_PERMISSIONS_REQUEST_READ_CONTACTS)

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an

// app-defined int constant. The callback method gets the

// result of the request.

}

}

谢幕,至此有关于android6.0 以上权限相关的内容已经详细讲完了!


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11640098.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存