静默安装的实现比较简单,但是有个前提:
你的应用必须有system权限。
所以分为两步:
1. 如何获取system权限。
①. 修改androidmanifest.xml , android:sharedUserId="android.uid.system"
②. 修改android.mk ,增加LOCAL_CERTIFICATE := platform
③. 编译即可,这样你的app就有了system权限。
2. 如何静默安装。
在这里我选择的是用Runtime.getRuntime().exec("pm install -r -s " );的方法。
具体实现如下,可以调用这个方法来安装/system/installapp/下以1.apk 2.apk 命名的apk,并选择是否安装到SD卡。
private int installapk_internel(int apkid, boolean sd) {
ByteArrayOutputStream byteary = new ByteArrayOutputStream();
ByteArrayOutputStream errbyteary = new ByteArrayOutputStream();
InputStream input = null;
InputStream errin = null;
Process proc = null;
int read = -1;
int readerr= -1;
String errresult= null;
String result = null;
try {
if (sd == true) {
proc = Runtime.getRuntime().exec(
"pm install -r -s " + APK_DIR + Integer.toString(apkid)
+ ".apk");
} else {
proc = Runtime.getRuntime().exec(
"pm install -r -f " + APK_DIR + Integer.toString(apkid)
+ ".apk");
}
int exitVal = proc.waitFor();
// wait for the proc to complete
input = proc.getInputStream();
errin = proc.getErrorStream();
while ((readerr = errin.read()) != -1) {
errbyteary.write(readerr);
}
// byteary.write('\n');
while ((read = input.read()) != -1) {
byteary.write(read);
}
byte data[] = byteary.toByteArray();
byte dataerr[] = errbyteary.toByteArray();
result = new String(data);
errresult =new String(dataerr);
Log.d(TAG, "INSTALL done ! id= " + apkid + " result code = "
+ exitVal);
Log.d(TAG,"INSTALL DONE ,err = "+errresult);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d(TAG,"INSTALL FAILD!");
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (errin != null) {
try {
errin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (proc != null) {
proc.destroy();
}
Log.d(TAG, " install complete, result = " + result);
}
if (result != null&&errresult != null) {
return handle_install_result(result,errresult);
} else {
return -3;
}
}
这里还增加了对 pm install 的结果的处理
private static final String APK_DIR = "/system/installapp/";
private static final int INSTALL_APK_SUCESS = 0;
private static final int INSTALL_APK_FAILED_SD_CARD_NOT_PRESENT = -1;
private static final int INSTALL_APK_FAILED_INTENER_MEMORY_FULL = -2;
private static final int INSTALL_APK_FAILED_OTHER = -3;
private static final String INSTALL_RESULT_SUCCESS = "Success";
private static final String INSTALL_RESULT_SD_NOT_PRESENT = "Failure [INSTALL_FAILED_MEDIA_UNAVAILABLE]";
private int handle_install_result(String result,String errresult) {
if (result.contains(INSTALL_RESULT_SUCCESS)) {
return INSTALL_APK_SUCESS;
} else if (errresult.contains(INSTALL_RESULT_SD_NOT_PRESENT)) {
return INSTALL_APK_FAILED_SD_CARD_NOT_PRESENT;
} else {
return INSTALL_APK_FAILED_OTHER;
}
}
这样我们可以在安装到sd失败的情况下尝试安装到内存: int ret = installapk_internel(current_id, true);
if (ret == INSTALL_APK_FAILED_SD_CARD_NOT_PRESENT) {
// then we try to install apks to internel memory.
Log.d(TAG,
"sdcard not present, we try to install apk to internel flash .");
ret = installapk_internel(current_id, false);
Log.d(TAG,"ret= "+ret);
if (ret != INSTALL_APK_SUCESS) {
Log.d(TAG, "install faild again.");
// WriteInstall_FAILD_FlagtoFile(current_id);
}
}