最近在做门禁机内嵌app,门禁机基于api22原生系统,涉及到的技术点包括静默安装、自启动。翻阅大量源码、blog以后得到解决方案,因此记录下来。
静默安装,即不弹窗系统安装界面的情况下,完成安装动作,在用户不知情的情况下完成安装动作显然是非常危险的行为
,因此静默安装不会开发给开发者,不过在Google Play商店已经自定义Rom上都有开发此权限,充分说明拥有权限的重要
性,自家的系统想咋样就咋样。
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
有用push到system/app去调用@hide实现的,有用doc命令实现的,对项目需求而言二者皆可,考虑到项目包含过多.so文件,而.so文件需要push到/system/lib赋予权限,故直接采用了第二种策略使用doc命令搞定,即(在子线程安装,避免ANR,需要root权限):
pm install -r
实现代码
/**
* 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;
}
无非就是静态广播拉起laucherActivity,不过这里需要注意的问题是,但静默安装成功后,app进程会被杀死,这个过程中自身无法接收到广播,这时候就需要辅助app了,这个app用来处理接收android.intent.action.PACKAGE_ADDED广播,并发送广播给宿主app从而实现自启动,这个过程代码是很简单的。
如果想要优化的话可以去做定时轮询相互检查进程是否存活,并相互拉起。如何定时轮询,如何检查,整个策略,会在后续中编写…
今天遇到了Task :app:compileDebugJavaWithJavac FAILED问题,网上答案很杂,解决以后总结一下。
该问题基本由于gradle编译导致,可以用
$ gradlew compileDebug --stacktrace
来跟踪gradle编译时的stacktrace信息,如果出现-bash: ./gradlew: Permission denied错误,可以输入
$ chmod +x gradlew
来解决权限问题,不过gradlew comileDebug 并不能看到有价值的信息,根据提示,输入
$ gradlew compileDebugSources --stacktrace -info
解决问题,原来是某个.java文件没push导致。