应用权限有助于保护对数据和操作的访问/执行权限,从而为保护用户隐私提供支持。如果应用必须访问受限数据或执行受限操作才能实现某个用例,请声明相应的权限。
Android 将权限分为不同的类型,包括安装时权限、运行时权限和特殊权限。每种权限类型都指明了当系统授予应用该权限后,应用可以访问的受限数据范围以及应用可以执行的受限操作范围。每项权限的保护级别取决于其类型以及对车机的影响。
当然你也可以访问Android官方网站查看权限相关的定义,不过很可惜,他只写了一些关于APP的
权限分类:
· 安装时权限:有些权限是用户安装应用时自动授予的权限;
· 运行时权限:其他权限则需要应用在运行时进一步请求权限,比如麦克风、摄像头、地理位置等,系统会为运行时权限分配 dangerous 保护级别。
· 特殊权限:只有平台和原始设备制造商 (OEM) 可以定义特殊权限,为特定应用限制操作范围和限制数据访问范围,系统会为特殊权限分配 appop 保护级别。
存在 /data/system/
文件夹下,记录了系统中所有安装的应用信息,包括基本信息、签名和权限等信息。当系统中的APK安装、删除、升级时,文件就会被更新。
packages.xml文件中主要的信息分为下面几个部分:
default-permissions.xml
存在/system/etc/default-permissions/
文件夹下。Android开机后,除了根据上次开机的记录(runtime-permissions.xml)授予运行时权限外,一些系统重要的组件也需要提前授予运行时权限,最常见的时为系统重要功能的默认组件提前授予运行时权限,例如系统会为默认的浏览器提前授予位置相关的运行时权限。
提前授权的步骤分三步:
default-permission.xml 中的fixed表示授权后是否可以被非系统组件修改权限
runtime-permission.xml
存在/data/misc_de/0/apexdata/com.android.permission/
文件夹下,会记录APP运行时所有的权限配置,运行时权限含有危险权限,此类权限授予应用对受限数据的额外访问权限,或允许应用执行对系统和其他应用具有更严重影响的受限操作。因此,需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。请勿假定这些权限之前已经授予过,务必仔细检查,并根据需要在每次访问之前请求这些权限。系统会为某些运行时权限分配 dangerous 保护级别。
在AOSP中的路径是:frameworks/base/services/java/com/android/server/SystemServer.java
,从Zygote创建system_process进程时,最先调用的就是声明了main()方法的类,main()方法创建了SystemServer的构造方法,构造方法里面只做了从属性系统中读取了工厂测试模式;
public static void main(String[] args) {
new SystemServer().run();
}
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
…………
}
private void run() {
try {
// AndroidRuntime using the same set of system properties, but only the system_server
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Start services.
try {
t.traceBegin("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
…………
}
这里启动了Installer、ActivityManagerService.Lifecycle //Activity管理服务
PowerManagerService //程序包管理服务
……
private void startBootstrapServices() {
Installer installer = mSystemServiceManager.startService(Installer.class);
// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
......
// Start the package manager.
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//PKMS是否是第一次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
......
}
SystemConfigService是用来读取并解析platform.xml
/**
* Starts some essential services that are not tangled up in the bootstrap process.
*/
private void startCoreServices() {
// Service for system config
mSystemServiceManager.startService(SystemConfigService.class);
......
}
这一块知识属于拓展,就是想记录WindowManagerService启动位置
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored and organized.
*/
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
......
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
......
}
`在不同行动设备上,权限的使用和管理有所不同。 为了提高用户对隐私的保护,Android 允许用户在应用运行时授权或拒绝某些敏感权限。 常见的敏感权限包括读取联系人、访问相机、获取位置等。 因此,开发者需要遵循系统规定,进行权限申请。
<manifest ...>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application ...>
...
</application>
</manifest>
// 请求单个权限
private fun checkPermission() {
if (ContextCompat.checkSelfPermission(
this,
android.Manifest.permission.CAMERA
)
!= PackageManager.PERMISSION_GRANTED
) {
Log.d(TAG, "onResume(): requestPermission()没有权限")
// 没有权限,需要请求权限
ActivityCompat.requestPermissions(
this,
arrayOf(android.Manifest.permission.CAMERA), 1001
)
} else {
// 已经有权限,可以执行相关操作
Log.d(TAG, "onResume(): requestPermission()已有权限")
}
}
// 请求多个个权限
private val PERMISSIONS_STORAGE: Array<String> = arrayOf<String>(
android.Manifest.permission.RECORD_AUDIO,
android.Manifest.permission.CAMERA
)
private fun ckeckPermissions() {
for ( permission in PERMISSIONS_STORAGE){
if (ActivityCompat.checkSelfPermission(this,
permission)!= PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "onResume(): requestPermission()没有权限")
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 200);
}else {
Log.d(TAG, "onResume(): requestPermission()已有权限")
}
}
}
// 请求权限回调方法
@Deprecated("Deprecated in Java")
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
1001 -> {
// 1001的请求码对应的是申请的权限
//单个授权
if (grantResults.isNotEmpty()) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "onRequestPermissionsResult(): 同意授权")
} else {
Log.d(TAG, "onRequestPermissionsResult(): 未同意授权")
}
}else{
Log.d(TAG, "onRequestPermissionsResult(): 授权结果为空")
}
// 判断是否同意授权,PERMISSION_GRANTED 这个值代表的是已经获取了权限
//多个授权
// var allGranted = true
// for (result in grantResults) {
// if (result != PackageManager.PERMISSION_GRANTED) {
// allGranted = false
// break
// }
// }
// if (allGranted) {
// // 所有权限都已授予,可以执行相关操作
// Log.d(TAG, "onRequestPermissionsResult(): 同意授权")
// } else {
// // 有部分权限未授予,可能需要提示用户或调整应用功能
// Log.d(TAG, "onRequestPermissionsResult(): 未同意授权")
// }
}
}
}
Activity.java
中会提示“Can request only one set of permissions at a time”只能申请完一组,等用户同意或者拒绝才能申请下一组,所以不会重复弹窗,并且在onRequestPermissionsResult()中会立马收到一个空结果; override fun requestPermissions(permissions: Array<String?>, requestCode: Int) {
require(requestCode >= 0) { "requestCode should be >= 0" }
if (mHasCurrentPermissionsRequest) {
Log.w(TAG, "Can request only one set of permissions at a time")
// Dispatch the callback with empty arrays which means a cancellation.
onRequestPermissionsResult(requestCode, arrayOfNulls(0), IntArray(0))
return
}
val intent: Intent = packageManager.buildRequestPermissionsIntent(permissions)
startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null)
mHasCurrentPermissionsRequest = true
}
另外,不同的应用申请同一个权限不会有问题,因为申请权限的包名不同,弹窗是根据包名以及权限名去显示的