在Android Studio中Demo使用CarAudio时,使用CarAudioManager的setZoneIdForUid()接口时出现缺少权限android.car.permission.CAR_CONTROL_AUDIO_VOLUME的问题。即使在AndroidManifest.xml中配置了该权限还是会提示缺少该权限。
<uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
1. 报错信息:
调用CarAudioManager的setZoneIdForUid()接口出现一下错误信息:
(standard input):07-29 22:02:57.128 30589 30589 D AndroidRuntime: Shutting down VM
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: FATAL EXCEPTION: main
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: Process: com.example.caraudiotest100, PID: 30589
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: java.lang.SecurityException: requires permission android.car.permission.CAR_CONTROL_AUDIO_VOLUME
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Parcel.createException(Parcel.java:2071)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:2039)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Parcel.readException(Parcel.java:1987)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.car.media.ICarAudio$Stub$Proxy.registerVolumeCallback(ICarAudio.java:782)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.car.media.CarAudioManager.<init>(CarAudioManager.java:566)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.car.Car.createCarManager(Car.java:1179)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.car.Car.getCarManager(Car.java:1150)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at com.example.caraudiotest100.MainActivity$1.onServiceConnected(MainActivity.java:246)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.car.Car$3.onServiceConnected(Car.java:729)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1948)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1980)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:883)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:100)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.os.Looper.loop(Looper.java:214)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7407)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
(standard input):07-29 22:02:57.130 30589 30589 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1030)
2. 权限机制
Android 将权限分为不同的类型,包括安装时权限、运行时权限和特殊权限。每种权限类型都指明了当系统授予应用该权限后,应用可以访问的受限数据范围以及应用可以执行的受限操作范围。
1. 普通权限(normal)
此类权限允许访问超出应用沙盒的数据和执行超出应用沙盒的操作。但这些数据和操作对用户隐私及对其他应用的操作带来的风险非常小。
2. 运行时权限(dangerous)
运行时权限也称为危险权限,此类权限授予应用对受限数据的额外访问权限,并允许应用执行对系统和其他应用具有更严重影响的受限操作。因此需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。当应用请求运行时权限时,系统会显示运行时权限弹窗提示。
3. 签名权限(signature)
当应用声明了其他应用已定义的签名权限时,如果两个应用使用同一证书进行签名,系统会在安装时向前者授予该权限。否则,系统无法向前者授予该权限。(注意:有些签名权限不适合第三方应用使用。)
该权限只需要在manifest中声明使用,同时应用和这类权限定义者拥有一样的签名系统就会默认授予应用这类权限;系统授予这类权限后应用无需像运行时权限一样动态申请。
4. 特殊权限(privileged)
特殊权限与特定的应用操作相对应。只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。系统设置中的特殊应用访问权限页面包含一组用户可切换的操作。其中的许多操作都以特殊权限的形式实现。每项特殊权限都有自己的实现细节。系统会为特殊权限分配“appop”保护级别。
该权限只需要在manifest中声明使用,同时拥有系统签名且不是预置到 **/priv_app/ (如:system/priv-app)目录下,系统就会默认授予;如果应用是预置到 **/priv_app/ 目录下则需要在配置文件privapp-permissions-platform.xml中配置权限信息,否则系统不会授予权限,并且也会无法通过cts测试
3. 问题分析
- 查看权限的等级:
adb shell pm list permissions -f | grep -A 5 "android.car.permission.CAR_CONTROL_AUDIO_VOLUME"
查看结果:signature|privileged
+ permission:android.car.permission.CAR_CONTROL_AUDIO_VOLUME
package:com.android.car
label:control car’s audio volume
description:Control your car’s audio volume.
protectionLevel:signature|privileged
signature需要和平台签名一致才能获取成功,需要检查一下签名
- 平台签名:
adb shell dumpsys package android | grep -r signatures
查看结果:
signatures=PackageSignatures{2c2261c version:3, signatures:[b4addb29], past signatures:[]}
- 应用签名:
adb shell dumpsys package com.example.caraudiotest100 | grep -r signatures
查看结果:
signatures=PackageSignatures{449dab9 version:2, signatures:[b4addb29], past signatures:[]}
由于平台签名和应用签名不一致,导致了获取不到权限,所以需要对应用进行平台签名。
4. 添加平台签名
(1)获取平台签名文件“platform.pk8”和“platform.x509.pem”
cd build/make/target/product/security
(2)把pkcs8格式的私钥转化成pkcs12格式
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out shared.priv.pem -nocrypt
(3)把x509.pem公钥转换成pkcs12格式
openssl pkcs12 -export -in platform.x509.pem -inkey shared.priv.pem -out shared.pk12 -name androiddebugkey
(密码都是:android)
(4)生成platform.keystore
keytool -importkeystore -deststorepass android -destkeypass android -destkeystore platform.keystore -srckeystore shared.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey
(生成的路径:build/make/target/product/security)
(5)导入到Android Studio
把platform.keystore放在app目录下。
(6)配置platform.keystore
app目录下的build.gradle配置文件中添加以下配置
------------------------------
android {
signingConfigs {
debug {
storeFile file("debug.keystore")
}
}
}
网友评论