Android中的动态权限

Android中的动态权限,android,android-permissions,Android,Android Permissions,我想知道第三方应用程序是否可以动态地向系统添加权限。根据,可以通过使用公共addPermission API;但是,我得到了一个SecurityException,上面写着java.lang.SecurityException:您要么需要管理用户,要么需要创建用户权限:查询用户。我只是想确定这确实是因为系统不允许这样做,而不是因为我在代码中弄错了什么。如果是这样的话,不允许向未使用系统证书签名的第三方应用程序动态添加权限,如果有人能解释这个选择背后的原因,那就太好了 以下是我如何以编程方式添加权

我想知道第三方应用程序是否可以动态地向系统添加权限。根据,可以通过使用公共addPermission API;但是,我得到了一个SecurityException,上面写着java.lang.SecurityException:您要么需要管理用户,要么需要创建用户权限:查询用户。我只是想确定这确实是因为系统不允许这样做,而不是因为我在代码中弄错了什么。如果是这样的话,不允许向未使用系统证书签名的第三方应用程序动态添加权限,如果有人能解释这个选择背后的原因,那就太好了

以下是我如何以编程方式添加权限:

public void addDynamicPermission() {
    PermissionInfo pi = new PermissionInfo();
    pi.name = "com.somedomain.permission.MY_PERMISSION";
    pi.labelRes = R.string.permission_label;
    pi.protectionLevel = PermissionInfo.PROTECTION_DANGEROUS;
    final PackageManager packageManager = getApplicationContext().getPackageManager();
    packageManager.addPermission(pi);
}
这是我清单文件中的内容:

这是异常的完整java堆栈:

FATAL EXCEPTION: main
Process: com.example.myapp, PID: 11824
java.lang.SecurityException: You either need MANAGE_USERS or CREATE_USERS permission to: query users
at android.os.Parcel.readException(Parcel.java:1684)
at android.os.Parcel.readException(Parcel.java:1637)
at android.content.pm.IPackageManager$Stub$Proxy.addPermission(IPackageManager.java:2870)
at android.app.ApplicationPackageManager.addPermission(ApplicationPackageManager.java:535)
at com.example.myapp.MainActivity.addDynamicPermission(MainActivity.java:183)
at com.example.myapp.MainActivity$6.onClick(MainActivity.java:64)
at android.view.View.performClick(View.java:5637)
at android.view.View$PerformClick.run(View.java:22429)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

非常感谢

TL;DR:这本书已经过时了,比棒棒糖更新的Android版本确实需要MANAGE_用户或CREATE_用户,这两个版本的保护级别都是3 signatureOrSystem

详细回答:

不久前,在KitKat时代,我编写了一些与您类似的测试代码,我记得它工作得很好。那是几年前的事了。我刚刚在我当前的牛轧糖7.0环境中启动了那个旧应用程序,结果出现了与您看到的完全相同的异常。出于好奇,我重新安装了KitKat 4.4.4、棒棒糖5.1和棉花糖6.0实例,并在每个实例上试用了该应用程序

对于4.4.4和5.1,一切正常。我通过运行代码验证了这一点,然后检查是否存在自定义权限,如下所示:

% adb shell dumpsys package packagename | grep -i com.example
...
Permission [com.example.permission.TEST_PERMISSION] (79c4d6d):
sourcePackage=com.example.myapplication
perm=Permission{2c725da2 com.example.permission.TEST_PERMISSION}
...
然而,在6.0和7.0上,我得到了安全异常。快速检查表示异常来自UserManagerService中的getPrimaryUser或getUsers方法

getPrimaryUsers在4.4.4或5.1中不存在,getUsers始终受到CheckManager或CreateUsersPermission的保护。因此,我认为合理的假设是addPermission链从6.0开始进行了修改,以便出于某种原因获得用户列表。所以addPermission不需要MANAGE_USERS或CREATE_USERS,但它现在调用的是一个方法


这个额外的访问控制检查是否是有意的,以及原因,是我无法回答的问题。

TL;DR:这本书已经过时了,比棒棒糖更新的Android版本确实需要MANAGE_用户或CREATE_用户,这两个版本的保护级别都是3 signatureOrSystem

详细回答:

不久前,在KitKat时代,我编写了一些与您类似的测试代码,我记得它工作得很好。那是几年前的事了。我刚刚在我当前的牛轧糖7.0环境中启动了那个旧应用程序,结果出现了与您看到的完全相同的异常。出于好奇,我重新安装了KitKat 4.4.4、棒棒糖5.1和棉花糖6.0实例,并在每个实例上试用了该应用程序

对于4.4.4和5.1,一切正常。我通过运行代码验证了这一点,然后检查是否存在自定义权限,如下所示:

% adb shell dumpsys package packagename | grep -i com.example
...
Permission [com.example.permission.TEST_PERMISSION] (79c4d6d):
sourcePackage=com.example.myapplication
perm=Permission{2c725da2 com.example.permission.TEST_PERMISSION}
...
然而,在6.0和7.0上,我得到了安全异常。快速检查表示异常来自UserManagerService中的getPrimaryUser或getUsers方法

getPrimaryUsers在4.4.4或5.1中不存在,getUsers始终受到CheckManager或CreateUsersPermission的保护。因此,我认为合理的假设是addPermission链从6.0开始进行了修改,以便出于某种原因获得用户列表。所以addPermission不需要MANAGE_USERS或CREATE_USERS,但它现在调用的是一个方法


我无法回答此附加访问控制检查是否有意以及原因背后的原因。

我建议您提供一个演示如何尝试执行此操作的示例,显示、addPermission调用以及与崩溃相关的完整Java堆栈跟踪。通常,应用程序通过清单中的元素添加自定义权限。我建议您提供一个示例,演示如何尝试执行此操作,显示、addPermission调用以及与崩溃相关的完整Java堆栈跟踪。一般来说,应用程序通过清单中的元素添加自定义权限。非常感谢Paul给出的这个非常详细的答案!在Android 5或更早版本上,我如何获得对动态创建它的应用程序的权限?我尝试在清单文件中使用标记,并在创建权限后更新应用程序,但它们根本不起作用。非常感谢Paul给出的这个非常详细的答案!在Android 5或更早版本上,我如何获得对动态创建它的应用程序的权限?我尝试在清单文件中使用标记,并在创建权限后更新应用程序,但它们根本不起作用。