Android系统 权限组管理和兼容性


Android系统 文件访问权限笔记
Android系统 理解/sys/目录权限和UID和GID?
Android系统 应用存储路径与权限
Android系统 自定义系统和应用权限
Android系统 AppOps默认授予应用相应的权限
Android系统 权限组管理和兼容性


参考学习: Android 中的权限

Android权限的目的是为了保护用户数据和设备。Android系统中有两种类型的权限普通权限和危险权限 , 为了方便用户管理危险权限又分为不同的权限组 从Android 6.0开始,又引入了运行时权限机制。除了普通权限和危险权限之外 存在系统级别或签名级别的特殊权限。反正不同Android版本间的权限都有差异 越新版本权限越严格(S/B)。

核心点详细描述
权限目的保护用户的数据和设备安全。
权限类型- 普通权限: 不会对用户隐私或设备造成大的影响。如访问网络。
- 危险权限: 可能对用户隐私或设备造成大的影响。如读取联系人。
权限组危险权限被分为不同的权限组,如电话、存储、位置等。授予组内任一权限会自动授予该组其他权限。
运行时权限从Android 6.0开始,应用在使用危险权限时需在运行时请求用户授权,而非安装时。
特殊权限系统级别或签名级别的权限,如修改系统设置。通常只由系统应用或相同签名的应用使用,但有例外情况。
版本差异不同Android版本间的权限有差异,比如从6.0引入运行时权限,10.0开始限制后台位置访问。

权限组

权限组的概念和作用

权限组是一种将相关的危险权限进行分类和分组的方式,每个危险权限都属于一个或多个权限组,如存储、相机等。权限组的作用是方便用户管理危险权限,减少用户频繁地处理授权请求,也让用户更清楚地知道应用需要什么样的功能。

Android系统中有以下几个权限组:

  • 存储:允许应用访问外部存储空间,如读取和写入文件、获取存储信息等。
  • 相机:允许应用使用设备的相机功能,如拍照、录像、获取相机参数等。

每个权限组中包含了一个或多个危险权限,可以在这里查看每个权限组中具体包含哪些危险权限。

如何定义和使用权限组

在开发应用时,需要在AndroidManifest.xml文件中声明需要的权限,无论是普通权限还是危险权限。可以使用<uses-permission>标签来声明一个单独的权限,也可以使用<uses-permission-group>标签来声明一个整个的权限组。例如:

<!-- 声明单独的危险权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<!-- 声明整个的权限组 -->
<uses-permission-group android:name="android.permission-group.CAMERA" />
<uses-permission-group android:name="android.permission-group.MICROPHONE" />

如果声明了一个整个的权限组,那么不需要再声明该组中的单独的危险权限了。但是如果只声明了该组中的某些危险权限,那么就只能使用这些声明过的危险权限,而不能使用该组中其他没有声明过的危险权限。例如:

<!-- 声明存储组中的写入外部存储危险权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<!-- 不能使用存储组中其他没有声明过的危险权限,如读取外部存储 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在运行时,需要向用户请求授权需要的危险权限,可以使用ActivityCompat.requestPermissions()方法来请求一个或多个危险权限,也可以使用ActivityCompat.requestPermissionsFromGroup()方法来请求一个整个的权限组。例如:

// 请求单独的危险权限
ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO},
        REQUEST_CODE);

// 请求整个的权限组
ActivityCompat.requestPermissionsFromGroup(this,
        Manifest.permission-group.CAMERA,
        REQUEST_CODE);

如果请求了一个整个的权限组,那么用户只需要一次授权就可以授予该组中的所有危险权限。但是如果只请求了该组中的某些危险权限,那么用户只会授予这些请求过的危险权限,而不会授予该组中其他没有请求过的危险权限。例如:

// 请求存储组中的写入外部存储危险权限
ActivityCompat.requestPermissions(this,
        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
        REQUEST_CODE);

// 用户只会授予写入外部存储危险权限,而不会授予存储组中其他没有请求过的危险权限,如读取外部存储

在请求权限时,需要提供一个请求码,用于标识请求。在用户做出授权选择后,可以在onRequestPermissionsResult()方法中接收用户的选择结果,并根据结果进行相应的处理。例如:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    // 判断请求码是否匹配
    if (requestCode == REQUEST_CODE) {
        // 判断授权结果是否成功
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // 授权成功,执行相应的操作
            Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show();
        } else {
            // 授权失败,提示用户或者退出应用
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
        }
    }
}

在使用危险权限时,需要先检查是否已经获得了该权限,可以使用ContextCompat.checkSelfPermission()方法来检查某个单独的危险权限,也可以使用ContextCompat.checkPermissionGroup()方法来检查某个整个的权限组。例如:

// 检查单独的危险权限
int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
int audioPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO);

// 检查整个的权限组
int cameraGroup = ContextCompat.checkPermissionGroup(this, Manifest.permission-group.CAMERA);
int microphoneGroup = ContextCompat.checkPermissionGroup(this, Manifest.permission-group.MICROPHONE);

如果检查结果为PackageManager.PERMISSION_GRANTED,则表示已经获得了该权限或者该组中的所有权限,可以直接使用。如果检查结果为PackageManager.PERMISSION_DENIED,则表示没有获得了该权限或者该组中的任何一个权限,需要向用户请求授权。例如:

// 检查存储组中的写入外部存储危险权限
int writePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);

if (writePermission == PackageManager.PERMISSION_GRANTED) {
    // 已经获得了写入外部存储危险权限,可以直接使用
    saveFileToExternalStorage();
} else {
    // 没有获得了写入外部存储危险权限,需要向用户请求授权
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
            REQUEST_CODE);
}

权限管理

Android系统的权限管理机制

Android的权限管理机制涉及应用如何请求、获得和使用权限,以及用户如何授予和管理这些权限。早期版本(6.0以下)在安装时请求权限,而6.0及以上版本在运行时请求危险权限。从11.0开始,用户可以授予应用一次性的使用权,特定于当前会话。而从10.0开始,应用要在后台访问位置信息,除了需要精确位置权限外,还需要一个特殊的后台位置访问权限。

权限管理类型描述适用版本
安装时权限应用在安装时展示所需权限,用户选择是否接受。权限可以在系统设置中启用或禁用,但不能单独控制。6.0以下
运行时权限应用在运行时请求危险权限。用户可以在系统设置中查看或修改,可以单独或整组控制。6.0及以上
一次性权限用户可以授予应用当前会话的一次性使用权。权限在应用退出或设备锁屏后失效。11.0及以上
后台位置访问应用需要特殊的后台位置访问权限才能在后台获取位置信息,否则只能在前台访问。10.0及以上

如何在应用中实现权限管理

在开发Android应用时,为了提高功能、安全性和用户体验,开发者应仅请求必要的权限,明确告知用户为何需要某权限,尊重用户的选择和隐私,并适配不同版本的权限特性和规则。

建议描述
只请求必要的权限根据应用功能和需求确定所需权限,避免请求不必要或冗余的权限,以增加用户信任。
解释权限需求在请求危险权限前,明确告知用户为何需要该权限及其用途,以减少用户疑虑。
尊重用户选择和隐私接受用户的授权决策,无论同意或拒绝。避免强迫、诱导或反复请求。确保不滥用或泄露用户数据。
适配版本的权限特性考虑到Android不同版本间的权限差异,如6.0的运行时权限和10.0的后台位置访问限制,确保应用在各版本上正常运行。

以确保应用在各个版本上都能正常运行。可以使用Build.VERSION.SDK_INT来判断当前设备的系统版本,并根据版本进行相应的处理。例如:

// 判断当前设备是否为6.0及以上版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    // 是6.0及以上版本,使用运行时权限机制
    // 检查是否已经获得某个危险权限
    int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
    if (cameraPermission == PackageManager.PERMISSION_GRANTED) {
        // 已经获得了危险权限,可以直接使用
        openCamera();
    } else {
        // 没有获得了危险权限,需要向用户请求授权
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.CAMERA},
                REQUEST_CODE);
    }
} else {
    // 是6.0以下版本,使用安装时权限机制
    // 不需要检查或请求危险权限,可以直接使用
    openCamera();
}

权限兼容性

Android不同版本间的权限差异

Android系统在不同版本中对权限有所变化。从6.0开始,引入了运行时权限机制,要求应用在运行时请求危险权限。11.0版本引入了一次性权限,允许用户为敏感权限授予一次性使用权。从10.0开始,应用在后台访问位置信息需要特殊的权限,并引入了分区存储模式,限制应用直接访问外部存储。

特性/变化描述适用版本
运行时权限机制应用在运行时请求危险权限,而非安装时。6.0及以上
一次性权限用户可以为敏感权限(如位置、相机)授予一次性使用权,仅在当前会话有效。11.0及以上
后台位置访问应用在后台访问位置需要ACCESS_BACKGROUND_LOCATION权限,而非仅ACCESS_FINE_LOCATION10.0及以上
分区存储应用只能访问自己的沙盒存储,访问其他存储需通过特定API或权限。10.0及以上

如何处理权限的兼容性问题

开发Android应用时,为确保在各版本正常运行,开发者需考虑权限差异。建议设置最新的目标SDK版本,根据设备系统版本判断权限需求,并使用Jetpack兼容库简化权限处理。

建议描述示例/备注
设置目标SDK版本在AndroidManifest.xml中设置应用的目标SDK版本,尽量选择最新版本以适配新权限特性。若目标SDK低于6.0,应用使用安装时权限机制,可能降低透明度和信任度。
判断当前系统版本在请求/使用权限前,检查设备系统版本以确定权限需求。使用Build.VERSION.SDK_INT判断。例如,10.0及以上版本需请求后台位置访问权限。
使用兼容库利用Android Jetpack的兼容库简化不同版本间的权限处理。使用PermissionCompat请求危险权限,无需判断版本。

可以使用Build.VERSION.SDK_INT来判断当前设备的系统版本,并根据版本进行相应的处理。例如:

// 判断当前设备是否为10.0及以上版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    // 是10.0及以上版本,需要请求后台位置访问危险权限
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
            REQUEST_CODE);
} else {
    // 是10.0以下版本,不需要请求后台位置访问危险权限
    // 可以直接使用位置信息
    getLocation();
}

可以使用Android Jetpack中提供的一些兼容库来简化和统一对于不同版本间权限差异的处理。例如,可以使用PermissionCompat类来请求一个或多个危险权限,而不需要判断当前设备是否为6.0及以上版本。例如:

// 使用PermissionCompat类来请求危险权限
PermissionCompat.requestPermissions(this,
        new String[]{Manifest.permission.CAMERA},
        REQUEST_CODE);

如何请求和使用特殊权限

在开发应用时,如果需要使用某些特殊权限来实现一些高级或者特殊的功能,需要以下几个步骤:

  • 声明特殊权限:需要在AndroidManifest.xml文件中声明需要使用的特殊权限,使用<uses-permission>标签来声明一个单独的特殊权限。例如:
<!-- 声明修改系统设置特殊权限 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
  • 检查特殊权限:需要在使用某个特殊权限之前,检查是否已经获得了该特殊权限,可以使用Settings.System.canWrite()方法来检查修改系统设置特殊权限,使用Settings.canDrawOverlays()方法来检查悬浮窗特殊权限,使用DevicePolicyManager.isAdminActive()方法来检查设备管理器特殊权限,使用NotificationManager.isNotificationPolicyAccessGranted()方法来检查通知监听特殊权限,使用AccessibilityManager.isEnabled()方法来检查辅助功能特殊权限,使用PackageManager.canRequestPackageInstalls()方法来检查安装未知来源应用特殊权限。例如:
// 检查修改系统设置特殊权限
boolean canWrite = Settings.System.canWrite(this);

// 检查悬浮窗特殊权限
boolean canDraw = Settings.canDrawOverlays(this);

// 检查设备管理器特殊权限
DevicePolicyManager devicePolicyManager = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
ComponentName componentName = new ComponentName(this, MyDeviceAdminReceiver.class);
boolean isAdminActive = devicePolicyManager.isAdminActive(componentName);

// 检查通知监听特殊权限
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
boolean isNotificationAccessGranted = notificationManager.isNotificationPolicyAccessGranted();

// 检查辅助功能特殊权限
AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
boolean isAccessibilityEnabled = accessibilityManager.isEnabled();

// 检查安装未知来源应用特殊权限
PackageManager packageManager = getPackageManager();
boolean canRequestPackageInstalls = packageManager.canRequestPackageInstalls();

如果检查结果为true,则表示已经获得了该特殊权限,可以直接使用。如果检查结果为false,则表示没有获得了该特殊权限,需要向用户请求授权。

  • 请求特殊权限:需要在运行时向用户请求授权需要的特殊权限,以使用startActivityForResult()方法来启动一个系统提供的设置界面,让用户在该界面中授予或拒绝请求。需要提供一个请求码,用于标识请求。在用户做出授权选择后,可以在onActivityResult()方法中接收用户的选择结果,并根据结果进行相应的处理。例如:
// 请求修改系统设置特殊权限
Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);

// 请求悬浮窗特殊权限
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);

// 请求设备管理器特殊权限
Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "请授予设备管理器权限");
startActivityForResult(intent, REQUEST_CODE);

// 请求通知监听特殊权限
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
startActivityForResult(intent, REQUEST_CODE);

// 请求辅助功能特殊权限
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, REQUEST_CODE);

// 请求安装未知来源应用特殊权限
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // 判断请求码是否匹配
    if (requestCode == REQUEST_CODE) {
        // 判断授权结果是否成功
        if (canWrite || canDraw || isAdminActive || isNotificationAccessGranted || isAccessibilityEnabled || canRequestPackageInstalls) {
            // 授权成功,执行相应的操作
            Toast.makeText(this, "Permission granted", Toast.LENGTH_SHORT).show();
        } else {
            // 授权失败,提示用户或者退出应用
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
        }
    }
}

希望这篇文章能对您有所帮助。如果还有其他问题或建议,请留言与私信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Anroid6.0权限问题 apk22之后Android把一些涉及用户个人信息的权限都做了默认没有权限处理,需要用户确认才可以: 用户不需要在安装软件的时候一次性授权所有申请的权限,而是可以在软件的使用过程中再对某一项权限申请进行授权。举例说明:一款相机应用在运行时申请了地理位置定位权限,就算我拒绝了这个权限,我仍然可以使用这款应用的其他功能,不用像6.0之前无法安装它。 解决办法: ● 投机取巧 如果我们不想使用6.0或者7.0的新特性,那么我们把targetSdkVersion设置22,就可以很好的避开动态配置运行时权限。而targetSdkVersion设置为22,并不影响其在Android 6.0或7.机制上使用,因为高版本兼容低版本。 解决办法:(简单到没朋友) AndroidAcp ● Acp 为 Android check permission 缩写,此库简化Android 6.0 系统复杂的权限操作而编写。 特点 ● 支持批量权限申请,不需要重写 onRequestPermissionsResult 方法,Activity 与 Fragment 中用法一致,一句话搞定。 ● 处理权限拒绝,或勾选不再询问,导致不能正常使用功能的提示框,支持跳转设置权限界面开启权限,所有提示框文字可自定义。 ● #使用Gradle构建时添加一下依赖即可: compile 'com.mylhyl:acp:1.1.7' 怎麽用? Acp.getInstance(this).request(new AcpOptions.Builder() .setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE , Manifest.permission.READ_PHONE_STATE , Manifest.permission.SEND_SMS) /*以下为自定义提示语、按钮文字 .setDeniedMessage() .setDeniedCloseBtn() .setDeniedSettingBtn() .setRationalMessage() .setRationalBtn()*/ .build(), new AcpListener() { @Override public void onGranted() { writeSD(); getIMEI(); } @Override public void onDenied(List permissions) { makeText(permissions.toString() + "权限拒绝"); } }); ***************************** 二維碼的使用: ZXING ● 可打开默认二维码扫描页面 ● 支持对图片Bitmap的扫描功能 ● 支持对UI的定制化操作 ● 支持对条形码的扫描功能 ● 支持生成二维码操作 ● 支持控制闪光灯开关 ● 集成默认的二维码扫描页面 在具体介绍该扫描库之前我们先看一下其具体的使用方式,看看是不是几行代码就可以集成二维码扫描的功能。 ● 在module的build.gradle中执行compile操作 compile 'cn.yipianfengye.android:zxing-library:2.1' ● 1 ● 1 ● 在Application中执行初始化操作 @Override public void onCreate() { super.onCreate(); ZXingLibrary.
1、暗黑模式 Android Q 的暗黑模式和 Android Pie 的暗黑模式不同,在 Android Q 中,暗黑模式适用于任何地方,如果应用不支持暗黑模式,那么系统将自动设置一个暗黑模式 [1] 。 2、桌面模式 Android Q 将支持桌面模式,类似三星 Dex 和华为的投影模式。它提供类似一个类似于 PC 的体验 [1] 。 3、隐私增强 Android Q 还将更多地使用 Android Pie 中推出的隐私功能。 在 Android Q中,用户可以选择应用程序在后台运行时是否可以访问该位置。此外,当应用程序使用您的位置数据、麦克风或摄像头时,用户在通知栏中看到相应的图标,它会告诉用户哪个应用程序正在使用该权限Android Q 中还有一个新的专用隐私页面。它显示了用户的联系人、短信和其他敏感信息的应用程序的确切数量 [1] 。 4、超级锁定模式 Android Q 泄漏的信息中包括一个“传感器关闭”切换按钮,该按钮将设备置于飞机模式,并禁用手机上的所有传感器 [1] 。 5、屏幕录制 Android Q 支持屏幕录制,可以通过长时间按下“电源”菜单中的“屏幕快照”来开启 [1] 。 6、移除 Android Beam 用于在设备之间共享文件的 Android Beam 选项消失了 [1] 。 7、运营商锁定 如果用户从运营商那里购买锁定的 Android Q 设备,将阻止用户使用其他特定运营商的SIM卡 [1] 。 8、面部识别 Android 10 将具有内部面部识别功能,谷歌官方支持面部解锁系统 [1] 。 9、不允许从后台读取剪贴板信息 Android Q 包含了名为“READ_CLIPBOARD_IN_BACKGROUND”的新权限。 新的权限将阻止随机的后台应用程序访问剪贴板内容 [1] 。 10、降级应用程序更新 Android Q 将有将应用程序回滚到以前的版本的功能 [1] 。 11、新字体、图标形状和提示颜色 Android Q 中展示了新的两种新字体,图标形状,如正方形、松鼠、TearDrop,新的提示颜色:黑色、绿色和蓝色 [1]
Android Studio是一款由Google开发的集成开发环境(IDE),用于开发Android应用程序。在Android应用程序中,权限设置是非常重要的一部分,以确保应用程序的安全性和用户隐私的保护。Android Studio提供了全兼容的权限设置功能,使开发者可以轻松管理应用程序的权限。 在Android Studio中,可以通过以下步骤进行全兼容权限设置: 1. 在项目的AndroidManifest.xml文件中声明所需的权限。例如,如果应用程序需要访问设备的相机,则需要添加以下权限声明: ```xml <uses-permission android:name="android.permission.CAMERA" /> ``` 2. 在代码中检查和请求权限。在Android 6.0(API级别23)及以上版本中,需要在运行时动态请求一些敏感权限。可以使用`checkSelfPermission()`方法检查权限是否已被授予,如果未被授予,则使用`requestPermissions()`方法请求权限。例如,请求相机权限的代码如下: ```java if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, CAMERA_PERMISSION_REQUEST_CODE); } ``` 3. 处理权限请求结果。在`onRequestPermissionsResult()`方法中处理权限请求的结果。可以根据用户的选择来执行相应的操作。例如,如果用户授予了相机权限,可以执行打开相机的操作;如果用户拒绝了权限,可以显示一个提示信息或者提供其他替代方案。 以上是Android Studio中全兼容权限设置的基本步骤。通过正确设置和管理权限,可以确保应用程序的正常运行和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值