最近在做有关静默安装和静默卸载的功能,6.0之前可以使用:
String[] args = null;
if (loc == InsLoc.EXT) {
args = new String[]{ _pm, _install, __r, __s, apkAbsolutePath };
} else if (loc == InsLoc.INT){
args = new String[]{ _pm, _install, __r, __f, apkAbsolutePath };
} else {
args = new String[]{ _pm, _install, __r, apkAbsolutePath };
}
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
DataInputStream errIs = null;
DataInputStream inIs = null;
try {
process = processBuilder.start();
MyLog.d(TAG, "----install before waitfor----");
int r = process.waitFor();
MyLog.d(TAG, "----install after waitfor----r:" + r);
errIs = new DataInputStream(process.getErrorStream());
String line = null;
while ((line = errIs.readLine()) != null) {
MyLog.d(TAG, "----err line:[" + line + "]----");
if (line.contains(_Failure)) {
result = line;
}
}
inIs = new DataInputStream(process.getInputStream());
line = null;
while ((line = inIs.readLine()) != null) {
MyLog.d(TAG, "----std line:[" + line + "]----");
if (line.contains(_Success)) {
result = line;
}
}
} catch (IOException e) {
MyLog.w(TAG, "----install ERROR:" + e.getMessage());
} catch (Exception e) {
MyLog.w(TAG, "----install ERROR:" + e.getMessage());
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
}
if (process != null) {
process.destroy();
}
}
能够正常静默,必须使用root样机。
当放到7.0样机上时,发现静默不了:出现java.lang.SecurityException: Package xxxx does not belong to 10054异常。通过不断的google和度娘,最终使用下面的方法解决:
String result = "";
// ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
DataInputStream errIs = null;
DataInputStream inIs = null;
try {
process = Runtime.getRuntime().exec("pm install -i "+packageName+" --user 0 "+apkAbsolutePath);
MyLog.d(TAG, "----install before waitfor----");
int r = process.waitFor();
MyLog.d(TAG, "----install after waitfor----r:" + r);
errIs = new DataInputStream(process.getErrorStream());
String line = null;
while ((line = errIs.readLine()) != null) {
MyLog.d(TAG, "----err line:[" + line + "]----");
if (line.contains(_Failure)) {
result = line;
}
}
inIs = new DataInputStream(process.getInputStream());
line = null;
while ((line = inIs.readLine()) != null) {
MyLog.d(TAG, "----std line:[" + line + "]----");
if (line.contains(_Success)) {
result = line;
}
}
} catch (IOException e) {
MyLog.w(TAG, "----install ERROR:" + e.getMessage());
} catch (Exception e) {
MyLog.w(TAG, "----install ERROR:" + e.getMessage());
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
}
if (process != null) {
process.destroy();
}
}
return result;
值得注意的是,上面的package指的是自身应用的package。当时就因为这个package踩了不少坑。
有关静默卸载:6.0以下使用:
String[] args = null;
if (keepData){
args = new String[]{ _pm, _uninstall, __k, packageName };
}else {
args = new String[]{ _pm, _uninstall, packageName };
}
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder(args);
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read = -1;
process = processBuilder.start();
errIs = process.getErrorStream();
while ((read = errIs.read()) != -1) {
baos.write(read);
}
baos.write('\n');
inIs = process.getInputStream();
while ((read = inIs.read()) != -1) {
baos.write(read);
}
byte[] data = baos.toByteArray();
result = new String(data);
MyLog.i(TAG, "----unInstallPackage exec cmd finish:[" + result.trim() + "]");
} catch (IOException e) {
MyLog.w(TAG, "----unInstallPackage ERR:" + e.getMessage(), e);
} catch (Exception e) {
MyLog.w(TAG, "----unInstallPackage ERR:" + e.getMessage(), e);
} finally {
try {
if (errIs != null) {
errIs.close();
}
if (inIs != null) {
inIs.close();
}
} catch (IOException e) {
MyLog.w(TAG, "----unInstallPackage WARN:" + e.getClass().getName() + "--" + e.getMessage(), e);
}
if (process != null) {
process.destroy();
}
}
return result;
能够正常在root样机下卸载,但是到了6.0以上的时候。又坑爹了。经过研究可以使用反射:
try {
PackageManager pm = context.getPackageManager();
Method[] methods = pm != null ? pm.getClass().getDeclaredMethods() : null;
Method mDel = null;
if (methods != null && methods.length > 0) {
for (Method method : methods) {
if (method.getName().toString().equals("deletePackage")) {
mDel = method;
break;
}
}
}
if (mDel != null) {
mDel.setAccessible(true);
mDel.invoke(pm, pkgName,null, 0);
}
} catch (Exception e) {
}
基本就是这样了。~~