应用静默安装能力的权限检查方法探视

本文详细介绍了Android应用静默安装的实现方法,包括所需权限、代码实现及系统权限获取方式。探讨了不同Android版本间的差异,并提供了检测静默安装能力的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用静默安装的时候,一般需要满足一定的苛刻条件。

网上流传的方法有:

1. app具有系统签名(和framwork签名一致)

2.app在system/app/目录下,具体的步骤如下:

分为如下三步
(1)、静默安装需要系统应用安装权限,需要在AndroidManifest.xml中添加

 

(2)、实现代码
静默安装代码如下,实际是通过pm install -r 命令安装。
注意:该函数最好在新建的线程中运行并通过handler发送安装结果给主线程,否则安装时间较长会导致ANR。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* install slient
*
@param context
@param filePath
@return 0 means normal, 1 means file not exist, 2 means other exception error
*/
public  static  int  installSlient  (  Context  context  ,  String  filePath  )  {
      File  file  =  new  File  (  filePath  )  ;
      if  (  filePath  ==  null  ||  filePath  .  length  (  )  ==  0  ||  (  file  =  new  File  (  filePath  )  )  == null  ||  file  .  length  (  )  <=  0
          ||  !  file  .  exists  (  )  ||  !  file  .  isFile  (  )  )  {
          return  1  ;
      }
 
      String  [  ]  args  =  {  "pm"  ,  "install"  ,  "-r"  ,  filePath  }  ;
      ProcessBuilder  processBuilder  =  new  ProcessBuilder  (  args  )  ;
 
      Process  process  =  null  ;
      BufferedReader  successResult  =  null  ;
      BufferedReader  errorResult  =  null  ;
      StringBuilder  successMsg  =  new  StringBuilder  (  )  ;
      StringBuilder  errorMsg  =  new  StringBuilder  (  )  ;
      int  result  ;
      try  {
          process  =  processBuilder  .  start  (  )  ;
          successResult  =  new  BufferedReader  (  new  InputStreamReader  (  process  .  getInputStream  (  ) )  )  ;
          errorResult  =  new  BufferedReader  (  new  InputStreamReader  (  process  .  getErrorStream  (  )  ) )  ;
          String  s  ;
 
          while  (  (  s  =  successResult  .  readLine  (  )  )  !=  null  )  {
              successMsg  .  append  (  s  )  ;
          }
 
          while  (  (  s  =  errorResult  .  readLine  (  )  )  !=  null  )  {
              errorMsg  .  append  (  s  )  ;
          }
      }  catch  (  IOException  e  )  {
          e  .  printStackTrace  (  )  ;
          result  =  2  ;
      }  catch  (  Exception  e  )  {
          e  .  printStackTrace  (  )  ;
          result  =  2  ;
      }  finally  {
          try  {
              if  (  successResult  !=  null  )  {
                  successResult  .  close  (  )  ;
              }
              if  (  errorResult  !=  null  )  {
                  errorResult  .  close  (  )  ;
              }
          }  catch  (  IOException  e  )  {
              e  .  printStackTrace  (  )  ;
          }
          if  (  process  !=  null  )  {
              process  .  destroy  (  )  ;
          }
      }
 
      // TODO should add memory is not enough here
      if  (  successMsg  .  toString  (  )  .  contains  (  "Success"  )  ||  successMsg  .  toString  (  )  . contains  (  "success"  )  )  {
          result  =  0  ;
      }  else  {
          result  =  2  ;
      }
      Log  .  d  (  "installSlient"  ,  "successMsg:"  +  successMsg  +  ", ErrorMsg:"  +  errorMsg  )  ;
      return  result  ;
}

返回值0表示安装成功,1表示文件不存在,2表示其他错误。需要更丰富的安装失败信息(内存不足、解析包出错)可直接使用PackageUtils.installSlient

 

(3) 、获取系统权限
完成了上面两步后,普通方式安装我们的应用仍然无法静默安装。需要我们的应用获得系统权限,编译应用并通过
adb push <your_apk_path> /system/app/
命令实现安装,即可拥有系统权限。


但是实际上呢,第二种方式在android4.4以后的机子上都无法实现了。因为在4.4中增加了目录system/priv-app/ 这个目录下的app是具备比system/app/下更高的权限。

/system/priv-app中包括Launcher,systemui, settingsprovider等,均是系统的核心应用,这些应用能使用系统级的权限,4.4之前的所有/system/app下的软件都能使用系统级的权限。                  Google这样做是把内置到系统的应用也做个级别的区别。
放到/system/priv-app下的应用比放到/system/app下的应用可以声明获得更多的权限。因为定义权限的的时候有protectionLevel字段限制权限的使用.它有四种值 normal dangerous signatrue signatureOrSystem。/system/priv-app符合signatureOrSystem的限制
具体可参考这里: Android 权限的一些细节


在framework的AndroidManifest.xml中定义了INSTALL_PACKAGES的权限级别:


可以看到是signature|privileged最高级别的(signatureOrSystem)。

实践中发现,只要把我们的app放入到system/priv-app/目录下,就能自动获取这个权限了。(放入system/app/目录下是不行的)。直接可以实现静默安装(不需要什么系统签名了)

但是如果我使用了系统签名(判断是否系统签名的条件是代码检测install_packages这个权限是否有获取到),代码检测能有这个权限,但是如果不把app放到这两个目录下面,依旧不能实现静默安装。

这个是系统签名后通过adb shell dumpsys package -p com.xx.xx获取到的install权限:


可以看出权限已经有了,但是还是不能执行静默安装。

那么也就是说,在我司的系统中,静默安装的必要条件必须是在system/priv-app/(在该目录下自动获取了install权限(不需要签名就能获取到))或者system/app/+install权限(通过签名获取)目录下了。

而当前我的app的一个需求就是自动检测是否有静默安装的能力,所以就得判断我的app是否满足以上两个条件中的一个

所以就有了下面这方法:

public static boolean isSystemApp(){
        if ((mAppContext.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
            LogUtils.d("AppContextUtils","是系统应用");
            return true;
        }
        LogUtils.d("AppContextUtils", "非系统应用");
        return false;
    }
实际上,放在system/app/和system/priv-app/目录下的都会标记为FLAG_SYSTEM。

当然,如果我们只判断这个条件的话,在/system/app/目录下满足这个条件,但是如果没有系统签名的话不满足install权限,也就是说在此基础上还要加上install权限的检测。

public boolean hasInstallPermission(){
        if(AppContextUtils.isSystemApp() &&
                (ActivityCompat.checkSelfPermission(AppContextUtils.getAppContext(), "android.permission.INSTALL_PACKAGES") == PackageManager.PERMISSION_GRANTED)){
            LogUtils.d(tag, "具备静默安装能力");
            return true;
        }else{
            return false;
        }
    }
加上权限检查,这样双重保证就能确定是否有静默安装能力了。

这里还列举了其他方法: http://blog.youkuaiyun.com/w6028819321/article/details/12775999 目前来看,并不靠谱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值