欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于应用调用系统权限的一些想法

程序员文章站 2022-03-12 23:01:37
...

在开发APP的时候,经常会遇到这种情况:想调用Android SDK的某个API实现某个功能,但是这个API是@hide的,或者private。这种情况我们通常的做法是:
① 如果没有权限拦截,可以考虑反射来调用。
② 有系统权限拦截,这种情况下,方法①就失效了。以下是不同的方案实现相同的效果:
A. 在AndroidManifest.xml配置android:sharedUserId="android.uid.system"让我们的APP拥有平台系统权限。然后在build.gradle的android节点添加系统签名(为了在AS能直接Run进行安装),如果不知道怎么生成系统签名文件,参考我的另一篇文章https://blog.csdn.net/ithouse/article/details/89467346:

signingConfigs {
        release_6683_p {
            storeFile file("../platform_p_6683.jks")
            storePassword 'platform123'
            keyAlias 'platform'
            keyPassword 'platform123'
        }

        debug_6683_p {
            storeFile file("../platform_p_6683.jks")
            storePassword 'platform123'
            keyAlias 'platform'
            keyPassword 'platform123'
        }
    }

B

  1. 加入android:sharedUserId="android.uid.system"这个属性。
  2. 使用AS编译出未加签名的apk文件,但是这个apk文件是不能用的。
  3. 使用目标系统的platform**来重新给apk文件签名。这步比较麻烦,首先找到**文件,在我的Android源码目录中的位置是"build/target/product/security",下面的platform.pk8和platform.x509.pem两个文件。然后用Android提供的Signapk工具来签名,signapk的源代码是在"build/tools/signapk"下,用法为"signapk platform.x509.pem platform.pk8 input.apk output.apk",文件名最好使用绝对路径防止找不到,也可以修改源代码直接使用。(上边的文件在上一个帖子中都发布过)

C

  1. 在应用程序的AndroidManifest.xml中的manifest节点中加入android:sharedUserId="android.uid.system"这个属性(并生成apk)。
  2. 修改(增加)Android.mk文件,加入LOCAL_CERTIFICATE := platform这一行
  3. 使用mm命令来编译,生成的apk就有修改系统时间的权限了。

以上ABC三种方案其实都可以看作同一种方案,就是通过增加android:sharedUserId属性让我们的APP拥有系统权限,但是这样一来,我们的APP也就成为系统应用了(非第三方应用),与系统紧密关联,在其他平台无法安装运行。

有一些认证需要APP是普通的第三方APP,既可以实现系统权限才有的功能,又可以上架到应用市场,这个时候,我们需要转换一下思维:
方案一:
开发两个APP,一个系统级别APP(简称SA)总是在后台运行,一个可以发布到应用市场的APP(简称TA),SA拥有系统权限,并监听TA发送的广播(或使用AIDL,自行选择合适方案),这样每当TA要执行系统应用才有的功能(如息屏),那么就发送对应的广播,SA收到广播之后,帮TA完成相应功能,并通知TA。

注意的点:安全性问题,因为这样我们就相当于把系统API暴露给第三方APP了,需要对广播内容进行验证,以及SA仅接收TA的包名发过来的请求,等等。

方案二:
基本和方案一相同,区别就是既然可以拿到系统源码定制系统,可以把功能依附在原有系统APP中,如“Setting”应用等,这种方案有其可靠之处,但是也有不足,附加在系统应用的其他功能越来越多,可能会比较臃肿,不利于解耦、升级、维护等等。