android权限管理

系统权限

Android 是一个权限分隔的操作系统,其中每个应用都有其独特的系统标识(Linux 用户 ID 和组 ID)。系统各部分也分隔为不同的标识。Linux 据此将不同的应用以及应用与系统分隔开来。

安全架构

在默认情况下,任何应用都没有权限执行对其他应用、操作系统或用户有不利影响的任何操作。比如:读写用户私有数据、执行网络访问等。

Android应用都在进程沙盒中运行,如需访问沙盒外的额外功能,应用应该静态声明所需权限,android系统提示用户同意。

用户 ID 和文件访问

在android系统上,每个应用是一个Linux用户,他们都拥有唯一一个用户ID。应用程序的数据只能被拥有该应用程序对应的用户ID的程序在可以访问,为此,我们可以通过设置AndroidManifest.xml 的 manifest 标记中使用 sharedUserId 属性,以及和该应用程序打相同的签名来共享用户ID,以实现共享数据的功能。在android也可以通过ContentProvider提供数据给其他应用访问。

UserId不同时:

包名不同:未设定process属性时,各自的Activity在各自的进程。 即使process指定了包名,也不会和另一个用户的同名包共享进程。

 包名相同:签名相同:覆盖旧的同包名apk。

           签名不同:新的apk会安装失败。

UserId相同时:

 包名不同:未设定process属性时,各自的Activity在各自的进程。

           process属性指定,则可以共享进程。

  包名相同:签名相同:覆盖旧的同包名apk。

            签名不同:新的apk会安装失败。

使用权限

在android应用中,要利用受保护的设备功能,必须在清单文件中包含一个或者多个<uses-permission>标记。

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

在清单文件中列出的权限,如果是正常权限(不涉及用户隐私数据和设备正常运行)系统自动授予该权限,危险权限(涉及用户隐私数据和正常运行),需要系统通知用户并获得用户同意。

自动权限调整

随着时间的推移,一些特定API的访问,低版本不需要的权限,在高版本API Level中可能需要添加相关权限。Android 将根据为 targetSdkVersion 属性提供的值决定应用是否需要权限。如果该值低于在其中添加权限的版本,则 Android 会自动添加该权限。

例如,API Level 4 中加入了 WRITE_EXTERNAL_STORAGE 权限,用以限制访问共享存储空间。如果您的 targetSdkVersion 为 3 或更低版本,则会向更新 Android 版本设备上的应用添加此权限。

注意:如果某权限自动添加到应用,则即使您的应用可能实际并不需要这些附加权限,Google Play 上的应用列表也会列出它们。

正常权限和危险权限

正常权限涵盖应用需要访问其沙盒外部数据或资源,但对用户隐私或其他应用操作风险很小的区域,不需要用户授予,系统自动授予。

危险权限涵盖应用需要涉及用户隐私信息的数据或资源,或者可能对用户存储的数据或其他应用的操作产生影响的区域,需要系统通知用户,用户授予。

 

权限组

正常权限和危险权限都是属于权限组,如果设备运行的是 Android 6.0(API 级别 23),targetSdkVersion 是23 或者更高版本:

如果应用请求其清单中列出的危险权限,而应用目前在权限组中没有任何权限,则系统会向用户显示一个对话框,描述应用要访问的权限组。对话框不描述该组内的具体权限。例如,如果应用请求 READ_CONTACTS 权限,系统对话框只说明该应用需要访问设备的联系信息。如果用户批准,系统将向应用授予其请求的权限。

如果应用请求其清单中列出的危险权限,而应用在同一权限组中已有另一项危险权限,则系统会立即授予该权限,而无需与用户进行任何交互。例如,如果某应用已经请求并且被授予了 READ_CONTACTS 权限,然后它又请求 WRITE_CONTACTS,系统将立即授予该权限。

如果设备运行的是 Android 5.1(API 级别 22)或更低版本,并且应用的 targetSdkVersion 是 22 或更低版本,则系统会在安装时要求用户授予权限。再次强调,系统只告诉用户应用需要的权限组,而不告知具体权限。

表 1. 危险权限和权限组。

权限组

权限

CALENDAR

·         READ_CALENDAR

·         WRITE_CALENDAR

CAMERA

·         CAMERA

CONTACTS

·         READ_CONTACTS

·         WRITE_CONTACTS

·         GET_ACCOUNTS

LOCATION

·         ACCESS_FINE_LOCATION

·         ACCESS_COARSE_LOCATION

MICROPHONE

·         RECORD_AUDIO

PHONE

·         READ_PHONE_STATE

·         CALL_PHONE

·         READ_CALL_LOG

·         WRITE_CALL_LOG

·         ADD_VOICEMAIL

·         USE_SIP

·         PROCESS_OUTGOING_CALLS

SENSORS

·         BODY_SENSORS

SMS

·         SEND_SMS

·         RECEIVE_SMS

·         READ_SMS

·         RECEIVE_WAP_PUSH

·         RECEIVE_MMS

STORAGE

·         READ_EXTERNAL_STORAGE

·         WRITE_EXTERNAL_STORAGE


定义和实施权限

一、定义权限

在AndroidManifest.xml 定义一个或多个<permission>权限。例如:

<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>

android:description:对权限的描述,一般是两句话,第一句话描述这个权限所针对的操作,第二句话告诉用户授予app这个权限会带来的后果

android:permissionGroup:权限所属权限组的名称,是可选属性,只是用于帮助系统向用户显示权限。大多数情况下,您要将此设为标准系统组(列在android.Manifest.permission_group 中),但您也可以自己定义一个组。建议使用现有的组,因为这样可简化向用户显示的权限 UI。

android:protectionLevel:权限的等级,

normal是最低的等级,声明此权限的app,系统会默认授予此权限,不会提示用户。

dangerous权限对应的操作有安全风险,系统在安装声明此类权限的app时会提示用户。

signature权限表明的操作只针对使用同一个证书签名的app开放。

signatureOrSystem与signature类似,只是增加了rom中自带的app。(系统app)。

注:系统不允许多个软件包使用同一名称声明权限,除非所有软件包都使用同一证书签署。如果软件包声明权限,则系统不允许用户安装具有相同权限名称的其他软件包,除非这些软件包使用与第一个软件包相同的证书签署。为避免命名冲突,建议对自定义权限使用相反域名样式命名,例如com.example.myapp.ENGAGE_HYPERSPACE。

一、实施权限

如果你开发一套只在自己设备上运行的应用,那可以开发出一个管理权限的软件包,各个应用之间的调用可以通过<uses-permission> 元素请求这些权限。

 

如果应用的调用和被调用方仅适用于相同的签名才可以,那就可以采用验证签名的方式,而不需要自定义权限。

 

多个不同签名的应用互相调用,尽可能每个权限只定义一次,多个相同签名的应用也是如此。

实施 AndroidManifest.xml 中的权限

可能在程序运行期间的多个位置实施特定权限

在调用系统时,防止应用执行某些功能。

在启动 Activity 时,防止应用启动其他应用的 Activity。

在发送和接收广播时,控制谁可以接收您的广播,谁可以向您发送广播。

在访问和操作内容提供程序时。

绑定至服务或启动服务。

 

Activity权限:在定义Activtiy中设置权限,在startActivity和startActvitiyForResult调用时检查权限,没有权限将会抛出SecurityException。

Service权限:限制谁可以启动或者绑定该Service。在 Context.startService()、Context.stopService() 和 Context.bindService() 时会检查权限;如果调用方没有所需的权限,则调用会抛出 SecurityException。

BroadcastReceiver 权限:限制谁可以发送广播给相关的接收方。在 Context.sendBroadcast() 返回后检查权限,因为系统会尝试将提交的广播传递到指定的接收方。因此,权限失效不会导致向调用方抛回异常;只是不会传递该 intent。同样,可以向 Context.registerReceiver() 提供权限来控制谁可以广播到以编程方式注册的接收方。另一方面,可以在调用 Context.sendBroadcast() 时提供权限来限制允许哪些 BroadcastReceiver 对象接收广播。

ContentProvider 权限:限制谁可以访问 ContentProvider 中的数据。与其他组件不同,您可以设置两个单独的权限属性:android:readPermission 限制谁可以读取提供程序,android:writePermission 限制谁可以写入提供程序。请注意,如果提供程序有读取和写入权限保护,仅拥有写入权限并不表示您可以读取提供程序。第一次检索提供程序时将会检查权限(如果没有任何权限,将会抛出 SecurityException),对提供程序执行操作时也会检查权限。使用 ContentResolver.query() 需要拥有读取权限;使用 ContentResolver.insert()、ContentResolver.update()、ContentResolver.delete() 需要写入权限。在所有这些情况下,没有所需的权限将导致调用抛出 SecurityException。

通常,权限失效会导致 SecurityException 被扔回应用。但不能保证每个地方都是这样。例如,sendBroadcast(Intent) 方法在数据传递到每个接收者时会检查权限,在方法调用返回后,即使权限失效,您也不会收到异常。但在几乎所有情况下,权限失效会记入系统日志。

发送广播时实施权限

除了实施谁可以向注册的 BroadcastReceiver 发送 intent 的权限(如上所述),您还可以指定在发送广播时需要的权限。通过使用权限字符串调用 Context.sendBroadcast(),您可以要求接收方的应用必须拥有该权限才可接收您的广播。

请注意,接收者和广播者可能需要权限。此时,这两项权限检查都必须通过后方可将 intent 传递到相关的目标。

其他权限实施

可对任何服务调用实施任意细化的权限。这可通过Context.checkCallingPermission() 方法完成。使用所需的权限字符串调用,它将返回一个整数,表示权限是否已授予当前的调用进程。请注意,仅在执行从另一个进程传入的调用(通常是通过从服务发布的 AIDL 或者指定给另一进程的某种其他方式完成)时才可使用此方法。

检查权限还有许多其他有用的方法。如果您有另一个进程的 pid,可以使用 Context 方法Context.checkPermission(String, int, int) 检查针对该 pid 的权限。如果您有另一个应用的软件包名称,可以使用直接的 PackageManager 方法PackageManager.checkPermission(String, String) 了解是否已为特定软件包授予特定权限。

	// 检查调用者是否具有 permission权限  
	// 此方法仅在调用IPC(interprocess communication)方法时有用  
	public static boolean checkPermission(Context context, String permission) {  
	    //检查如果是当前应用则返回真  
	    if (Binder.getCallingPid() == Process.myPid()) {  
	        return true;  
	    }  
	    if (context.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {  
	        return true;  
    }  	    return false;  
	}


判断本程序是否拥有某权限的方法:

	private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";  
	  
	private static boolean hasExternalStoragePermission(Context context) {  
	        int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);  
	        return perm == PackageManager.PERMISSION_GRANTED;  
	    } 

判断某个程序是否拥有某权限的方法:

	private static boolean checkPermission(Context context, String permName, String pkgName){  
	        PackageManager pm = context.getPackageManager();  
	        if(PackageManager.PERMISSION_GRANTED == pm.checkPermission(permName, pkgName)){  
	            System.out.println(pkgName + "has permission : " + permName);  
	            return true;  
	        }else{  
	            //PackageManager.PERMISSION_DENIED == pm.checkPermission(permName, pkgName)  
	            System.out.println(pkgName + "not has permission : " + permName);  
	            return false;  
	        }  
	    }


URI 权限

到目前为止所述的是标准权限系统,内容提供程序仅仅使用此系统通常是不够的。内容提供程序可能需要通过读取和写入权限保护自己,而其直接客户端也需要将特定 URI 传给其他应用以便于它们运行。邮件应用中的附件是一个典型的示例。应通过权限保护对邮件的访问,因为这是敏感的用户数据。但是,如果将图像附件的 URI 提供给图像查看程序,该图像查看程序不会有打开附件的权限,因为它没有理由拥有访问所有电子邮件的权限。

此问题的解决方法是采用 per-URI 权限机制:在启动 Activity 或返回结果给 Activity 时,调用方可以设置Intent.FLAG_GRANT_READ_URI_PERMISSION 和/或Intent.FLAG_GRANT_WRITE_URI_PERMISSION。这将授予接收 Activity 权限访问 intent 中的特定数据 URI,而不管它是否具有访问 intent 对应的内容提供程序中数据的任何权限。此机制支持常见的能力式模型,其中用户交互(打开附件、从列表中选择联系人等)驱动临时授予细化的权限。这是一项关键功能,可将应用所需的权限缩小至只与其行为直接相关的权限。但授予细化的 URI 权限需要与拥有这些 URI 的内容提供程序进行一定的合作。强烈建议内容提供程序实施此功能,并且通过 android:grantUriPermissions 属性或<grant-uri-permissions> 标记声明支持此功能。详细使用信息见:URI权限




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt for Android 提供了一种方便的方式来管理 Android 权限。在 Qt Android 的应用程序中,我们可以使用 Qt Android Extras 模块中的 API 来请求和检查权限。 首先,在.pro 文件中添加 Qt Android Extras 模块的依赖,如:QT += androidextras。然后,使用 Qt 代码将请求的权限名称添加到 AndroidManifest.xml 文件中。 在代码中,我们可以使用 QAndroidJniObject 类来调用 Java 提供的 API 来请求权限。例如,要请求读取外部存储的权限,可以使用如下代码: QAndroidJniObject permission = QAndroidJniObject::fromString("android.permission.READ_EXTERNAL_STORAGE"); QAndroidJniObject::callStaticMethod<void>("org/qtproject/example/MainActivity", "requestPermission", "(Ljava/lang/String;I)V", permission.object<jstring>(), 0); 这里的 "org/qtproject/example/MainActivity" 是 Qt Android 应用程序的主活动类。 然后,在 MainActivity.java 文件中,我们需要定义一个 requestPermission 的静态函数来处理权限请求: public static void requestPermission(String permission, int requestCode) { ActivityCompat.requestPermissions(this, new String[]{permission}, requestCode); } 在用户处理权限请求的结果后,可以通过重写 onRequestPermissionsResult 方法来获得结果: @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 0: // 根据请求代码进行处理 if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 权限被授予 } else { // 权限被拒绝 } break; // 其他权限请求处理 } } 这样,我们就可以通过 Qt 的代码来请求和检查 Android 权限。请注意,要请求敏感权限,例如读取电话状态或访问摄像头,用户可能需要手动在设备的应用程序设置中授予权限。 ### 回答2: 在Qt for Android中,权限管理是一项非常重要的功能。它允许开发者请求和管理应用程序所需的各种权限。为了确保应用程序的正常运行,以及为用户提供更好的安全性和隐私保护,Android操作系统要求应用在使用某些功能之前获得相应的权限。 Qt提供了一些API来管理Android权限。可以使用Qt Android Extras模块中的QAndroidJniObject类来与Java层进行交互,并调用Android的权限请求API。使用QAndroidJniObject,开发者可以请求授予或拒绝访问到某些敏感信息的权限,例如GPS位置、联系人、照相机等。 首先,开发者需要在应用程序的AndroidManifest.xml文件中声明所需的权限。可以使用Qt的AndroidManifest.xml文件来进行声明,或者使用AndroidManifest.xml文件模板并将其放置在应用程序的资源文件夹中。 接下来,开发者需要在Qt代码中请求权限。可以使用QAndroidJniObject类来获取当前应用的Activity对象,并调用其requestPermissions方法请求权限。该方法将弹出一个系统对话框,显示所请求的权限,并询问用户是否同意授权。 在权限请求完成后,开发者可以通过处理Qt的Android活动生命周期事件来处理权限的授权结果。如果用户授予了权限,开发者可以相应地处理并执行所需的功能。如果用户拒绝了权限,开发者可以选择显示错误消息或提供替代功能。 总之,在Qt for Android中,权限管理是一项关键功能,通过QAndroidJniObject和AndroidManifest.xml文件,开发者可以方便地请求和管理应用程序所需的权限,以确保应用程序的正常运行和用户的安全性和隐私保护。 ### 回答3: Qt for Android 提供了一套完善的权限管理机制,可以使开发者在使用 Qt 开发 Android 应用时更方便地管理和申请权限。 首先,可以通过 Qt 的 AndroidExtras 模块中的 QAndroidPermissions类来进行权限管理。这个类提供了一系列的静态方法,可以用来查询、申请、检查和撤销权限。开发者可以通过调用这些方法来完成对权限的管理操作。 具体而言,可以使用 QAndroidPermissions::hasPermission() 方法来检查某个权限是否已被授权。如果权限未被授权,可以使用 QAndroidPermissions::requestPermissions() 方法来申请权限。该方法接受一个权限列表作为参数,然后会弹出系统权限请求框。用户可以在这个框中选择是否授权。申请权限的结果将通过 QAndroidPermissions::requestPermissionsFinished() 信号返回。 另外,使用 Qt 的 Android Intent 和 JNI 机制,也可以在 Qt 代码中通过调用 Android 平台的权限管理 API 来进行权限管理。这种方式需要开发者熟悉 Java 和 Android 开发的相关知识。 需要注意的是,在申请敏感权限时,需要在 AndroidManifest.xml 文件中声明相应的权限。如果没有正确声明权限,应用在运行时将无法进行相关操作。 总之,Qt for Android 提供了便捷的权限管理机制,开发者可以灵活地使用这些API来管理和申请权限,以确保应用在运行时获得所需的权限,提高应用的安全性和稳定性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值