[Android]AndroidManifest.xml之permission浅谈

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011195398/article/details/52447747

概述

昨天群友在群里丢了一个日志信息,说Jpush的服务初始化异常,我就帮忙下了个Demo集成了下。发现是自定义用户权限的出错了。下面献上我的分析。

09-05 21:22:45.279: D/JPush(21334): [PushService] Action: init PushService
09-05 21:22:45.279: D/JPush(21334): [AndroidUtil] action:checkValidManifest
09-05 21:22:54.289: E/JPush(21334): [AndroidUtil] The permission should be defined - com.machinebook.customer.permission.JPUSH_MESSAGE
09-05 21:22:54.293: W/JPush(21334): [PushService] JPush running checked failed!
09-05 21:22:54.308: D/JPush(21334): [PushService] onStartCommand - intent:Intent { act=cn.jpush.android.intent.REPORT cmp=com.machinebook.customer/cn.jpush.android.service.PushService (has extras) }, pkg:com.machinebook.customer, connection:0
09-05 21:22:54.308: D/JPush(21334): [PushService] onStartCommand - not valid JPush running - Should not be here.
09-05 21:22:54.308: D/JPush(21334): [PushService] onStartCommand - intent:Intent { act=cn.jpush.android.intent.INIT cmp=com.machinebook.customer/cn.jpush.android.service.PushService (has extras) }, pkg:com.machinebook.customer, connection:0
09-05 21:22:54.308: D/JPush(21334): [PushService] onStartCommand - not valid JPush running - Should not be here.

上面的日志可以看见,我初始化失败了。搜索JPUSH Android常见问题说我没有没有正确的定义permision,请添加权限。查看后发现我下面没有添加这行权限。

    <!-- 自定义权限 -->
    <permission
        android:name="com.machinebook.customer.permission.JPUSH_MESSAGE"
        android:protectionLevel="signature" />

    <!--用户权限请求-->
    <uses-permission android:name="com.machinebook.customer.permission.JPUSH_MESSAGE" />

API文档
- permission

权限

权限是一种限制,用于限制对部分代码或设备上数据的访问。 施加限制是为了保护可能被误用以致破坏或损害用户体验的关键数据和代码。

每种权限均由一个唯一的标签标识。标签通常指示受限制的操作。 例如,以下是由 Android 定义的一些权限:

android.permission.CALL_EMERGENCY_NUMBERS 
android.permission.READ_OWNER_DATA 
android.permission.SET_WALLPAPER 
android.permission.DEVICE_POWER

一个功能最多只能由一种权限保护。

如果应用需要访问受权限保护的功能,则必须在清单文件中使用 元素声明应用需要该权限。 但是,将应用安装到设备上之后,安装程序会通过检查签署应用证书的颁发机构并(在某些情况下)询问用户,确定是否授予请求的权限。 如果授予权限,则应用能够使用受保护的功能。 否则,其访问这些功能的尝试将会失败,并且不会向用户发送任何通知。

此外,应用也可以使用权限保护自己的组件(Activity、服务、广播接收器和内容提供程序)。 它可以采用由 Android 定义(如 android.Manifest.permission 中所列)或由其他应用声明的任何权限。或者,它也可以定义自己的权限。新权限用 元素来声明。 例如,Activity 可受到如下保护:

<manifest . . . >
    <permission android:name="com.example.project.DEBIT_ACCT" . . . />
    <uses-permission android:name="com.example.project.DEBIT_ACCT" />
    . . .
    <application . . .>
        <activity android:name="com.example.project.FreneticActivity"
                  android:permission="com.example.project.DEBIT_ACCT"
                  . . . >
            . . .
        </activity>
    </application>
</manifest>

请注意,在此示例中,DEBIT_ACCT 权限不仅是通过 元素来声明,而且其使用也是通过 元素来请求。要让应用的其他组件也能够启动受保护的 Activity,就必须请求其使用权限,即便保护是由应用本身施加的亦如此。

同样还是在此示例中,如果将 permission 属性设置为在其他位置(例如,android.permission.CALL_EMERGENCY_NUMBERS)声明的权限,则无需使用 元素再次声明。 但是,仍有必要通过 请求使用它。

一个权限隐含的潜在风险,并指示决定是否准予许可请求它的应用程序时,系统应遵循的程序,Standard permissions有一个预定义的和永久的ProtectionLevel。如果您在应用程序中创建自定义权限,您可以定义下面列出的值之一的ProtectionLevel属性。如果没有的ProtectionLevel为自定义权限定义,系统分配的默认(“正常”)。

Android protectionLevel分4个级别:

“normal”
“dangerous”
“signature”
“signatureOrSystem”

image

  • 如果定义的是前面两种normal或者dangerous, 我们自己的应用需要去访问其对应受保护的资源时只需要在androidManifest.xml中添加相同的uses-permission就行了
  • 如果是signature, 我们仅仅添加对权限的使用还不行, 必须同时具有相同的签名。
  • 如果是signatureOrSystem(这种权限的应用第三方的应用无法单独访问), 不仅要有相同的签名,而且签名必须是系统签名,此外可能还需要android : sharedUserId=”android.uid.system”。

深入源码

系统定义权限主要来自于两处:
- framework/base/core/res/AndroidManifest.xml
查看源码

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android" coreApp="true" android:sharedUserId="android.uid.system"
    android:sharedUserLabel="@string/android_system_label">
    <!-- ================================================ -->
    <!-- Special broadcasts that only the system can send -->
    <!-- ================================================ -->
    <eat-comment />
    <protected-broadcast android:name="android.intent.action.SCREEN_OFF" />
    <protected-broadcast android:name="android.intent.action.SCREEN_ON" />
    <protected-broadcast android:name="android.intent.action.USER_PRESENT" />
    <protected-broadcast android:name="android.intent.action.TIME_SET" />
    <protected-broadcast android:name="android.intent.action.TIME_TICK" />
    <protected-broadcast android:name="android.intent.action.TIMEZONE_CHANGED" />
    <protected-broadcast android:name="android.intent.action.DATE_CHANGED" />
    <protected-broadcast android:name="android.intent.action.BOOT_COMPLETED" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_INSTALL" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_ADDED" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_REPLACED" />
    <protected-broadcast android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_REMOVED" />
    <protected-broadcast android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
....
  • framework/base/data/etc/platform.xml

静态读取

在6.0以前,APP在第一次安装的时候,就会读取我们的配置清单文件,告知用户APP获取的权限。这时候我们就可以选择是否全部授权了。

动态读取

6.0以后,系统源码加入了动态读取权限,也就是说,当某个功能使用到的时候,在去弹窗提示用户。大大的加入了灵活性和安全性。

这里说的比较简单,有兴趣的可以自行搜索下其他文章。

思维拓展:

有兴趣的还可以研究一下几个问题。
为什么Jpush要自定义权限,对应用有什么好处?

从上面的API来看,当第三方要读取我们的数据时候,如果设置signature,那么可以提高对我们自己应用数据的保护。如果是这样我们平常来做应用的时候,如果想提高APP数据的安全,是不是相应的也可以构造自己的权限加以利用。

  1. App安装流程,如何从源码的角度分析,系统怎么读取manifest文件?
  2. 6.0的动态申请权限,如何做适配?

剩下的两个问题都是大坑,今天不谈了,有兴趣的可以自行深究下。

参考文档

猜你喜欢

转载自blog.csdn.net/u011195398/article/details/52447747