本文主要介绍程序如何利用root权限静默安装(卸载)APK,如何自动选择普通安装(卸载)还是静默安装(卸载)。
1、root权限静默安装(卸载)调用
引入TrineaAndroidCommon@Github(欢迎star和fork^_^)作为你项目的library(如何拉取代码及添加公共库),或自己抽取PackageUtils.installSlient(PackageUtils.uninstallSilent)函数进行调用,系统授权管理会弹出对话框让用户选择是否允许应用获得root权限。允许的话即可静默安装。
该函数返回PackageUtils.INSTALL_SUCCEEDED表示安装成功,失败则返回相应错误码,可以得到失败的详细原因,包括文件不存在,apk无效,系统内存不足,签名不正确,缺少公共库,share user错误等等判断。
注意对于较大apk安装过程非常耗时,所以最好新启线程去调用PackageUtils.installSlient。
2、root权限静默安装实现
PackageUtils.installSlient的实现实际使用的是su pm install -r filePath命令。核心代码如下:
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
68
69
70
71
72
73
74
75
|
public
static
final
String
COMMAND_SU
=
"su"
;
public
static
final
String
COMMAND_SH
=
"sh"
;
public
static
final
String
COMMAND_EXIT
=
"exit\n"
;
public
static
final
String
COMMAND_LINE_END
=
"\n"
;
public
static
CommandResult
execCommand
(
String
[
]
commands
,
boolean
isRoot
,
boolean
isNeedResultMsg
)
{
int
result
=
-
1
;
if
(
commands
==
null
||
commands
.
length
==
0
)
{
return
new
CommandResult
(
result
,
null
,
null
)
;
}
Process
process
=
null
;
BufferedReader
successResult
=
null
;
BufferedReader
errorResult
=
null
;
StringBuilder
successMsg
=
null
;
StringBuilder
errorMsg
=
null
;
DataOutputStream
os
=
null
;
try
{
process
=
Runtime
.
getRuntime
(
)
.
exec
(
isRoot
?
COMMAND_SU
:
COMMAND_SH
)
;
os
=
new
DataOutputStream
(
process
.
getOutputStream
(
)
)
;
for
(
String
command
:
commands
)
{
if
(
command
==
null
)
{
continue
;
}
// donnot use os.writeBytes(commmand), avoid chinese charset error
os
.
write
(
command
.
getBytes
(
)
)
;
os
.
writeBytes
(
COMMAND_LINE_END
)
;
os
.
flush
(
)
;
}
os
.
writeBytes
(
COMMAND_EXIT
)
;
os
.
flush
(
)
;
result
=
process
.
waitFor
(
)
;
// get command result
if
(
isNeedResultMsg
)
{
successMsg
=
new
StringBuilder
(
)
;
errorMsg
=
new
StringBuilder
(
)
;
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
(
)
;
}
catch
(
Exception
e
)
{
e
.
printStackTrace
(
)
;
}
finally
{
try
{
if
(
os
!=
null
)
{
os
.
close
(
)
;
}
if
(
successResult
!=
null
)
{
successResult
.
close
(
)
;
}
if
(
errorResult
!=
null
)
{
errorResult
.
close
(
)
;
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
(
)
;
}
if
(
process
!=
null
)
{
process
.
destroy
(
)
;
}
}
return
new
CommandResult
(
result
,
successMsg
==
null
?
null
:
successMsg
.
toString
(
)
,
errorMsg
==
null
?
null
:
errorMsg
.
toString
(
)
)
;
}
|
其中commands为pm install -r . 从中可以看出主要就是使用su切换到root环境下,再调用pm install -r进行安装。
3、普通安装,系统权限静默安装,root权限静默安装的自动选择
查看PackageUtils源码会发现我还提供了其他几个安装函数,其中PackageUtils.install(PackageUtils.uninstall)函数会根据是否是系统应用以及是否拥有root权限,从而确定调用哪种安装方式(普通安装方式、root静默安装方式还是系统权限静默安装),源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
/**
* install according conditions
* <ul>
* <li>if system application or rooted, see {@link #installSilent(Context, String)}</li>
* <li>else see {@link #installNormal(Context, String)}</li>
* </ul>
*
* @param context
* @param filePath
* @return
*/
public
static
final
int
install
(
Context
context
,
String
filePath
)
{
if
(
!
PackageUtils
.
isSystemApplication
(
context
)
&&
!
ShellUtils
.
checkRootPermission
(
)
)
{
return
installNormal
(
context
,
filePath
)
?
INSTALL_SUCCEEDED
:
INSTALL_FAILED_INVALID_URI
;
}
return
installSilent
(
context
,
filePath
)
;
}
|
如果是系统应用记得添加<uses-permission android:name=”android.permission.INSTALL_PACKAGES” />权限,从而走普通安装方式,不用申请root权限进行静默安装。
4、PackageUtils 实现静默卸载应用
调用PackageUtils.uninstallSlient
转载地址:http://www.trinea.cn/android/android-silent-install/