JKS制作及静默安装
- 前言
- 系统APP
- APK的安装流程及管理:
- 系统签名JKS制作
- 1. 签名资料准备
- 2. JKS文件生成
- 3. JKS生成中遇到的问题
- APK静默安装
- ROOT安装法
- 总结
前言
最近公司软件有需求要求将Android apk经系统签名以达到更新静默安装的效果。文章主要讲解如何进行系统签名的jks文件生成和静默安装的代码执行,内容及代码都是我亲自实验可行的,如遇疑问请联系我进行沟通讨论及解决。
系统APP
1. android:sharedUserId
想要将app做成系统App,必定需要在在AndroidManifest.xml中配置属性android:sharedUserId。
此声明将使APK拥有系统权限,接下来需要为它进行系统签名。否则安装时会出现 INSTALL_FAILED_SHARED_USER_INCOMPATIBLE
报错
// 根据个人不同的需求进行选择,只能四选一
android:sharedUserId="android.uid.system"
android:sharedUserId="android.uid.shared"
android:sharedUserId="android.media"
android:sharedUserId="android.uid.system"
2. 系统app的签名
apk想要发布是需要签名的,系统apk的签名有两种方式。
方式1:生成系统签名jks,然后常规方式在Android Studio中Build apk安装包。
配置后调试和打包都非常方便快捷,强烈支持这种方式。
方式2:先生成普通签名apk ,然后通过如下方式签名。
// 注意将signapk.jar, platform.x509.pem ,platform.pk8,unsign.apk,sign.apk放在同一文件夹,且cmd进入该文件夹目录下。
java -jar signapk.jar platform.x509.pem platform.pk8 apk路径(签名前) apk路径(签名后)
两种方式都需要 platform.x509.pem和 platform.pk8文件
,在后面的系统签名JKS制作中会详细说明两文件。
3. Android安装方式
- 系统应用安装,apk放在系统文件夹中,无安装界面
- 手机应用市场安装,每个手机自带的厂商应用市场可能是经系统文件签名,所以安装其他软件无界面
- ADB工具安装,没有安装界面
- 第三方应用安装,比如我们自己软件下载更新然后安装,有安装界面
APK的安装流程及管理:
1. apk安装流程
- system/app : 系统自带的应用程序,无法删除。该路径下放system.apk
- data/app:用户程序安装的目录,有删除权限。该路径下放customer.apk
- data/data: 存放应用程序的数据
- Data/dalvik-cache: 将apk中的dex文件(Dalvik字节码)安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)
APK的安装过程:将apk复制到data/app或system/app中,解压并扫描安装包,把dex文件保存到dalvik-cache目录,并在data/data目录下创建对应的应用数据目录。
2. apk开机管理
PackageManagerService处理各种应用的安装,卸载,管理等工作,开机时由systemServer启动此服务。PackageManagerService的启动流程如下:
1. 首先扫描安装“system\framework”目录下的jar包
scanDirLI(mFrameworkDir,PackageParser.PARSE_IS_SYSTEM,scanMode | SCAN_NO_DEX);
2. 第二步扫描安装“system\app”目录下的各个系统应用,即安装系统应用
scanDirLI(mSystemAppDir,PackageParser.PARSE_IS_SYSTEM, scanMode);
3. 第三步扫描“data\app”目录,即用户安装的第三方应用
scanDirLI(mAppInstallDir, 0, scanMode);
4. 第四步扫描" data\app-private"目录,即安装DRM保护的APK文件(此类应用极少)。
scanDirLI(mDrmAppPrivateInstallDir,0, scanMode | SCAN_FORWARD_LOCKED);
系统签名JKS制作
我们都知道apk安装到设备上需要签名制作成release 版apk.一般软件使用Android studio制作的jks签名秘钥签名就行。对于需要系统签名的APK的JKS文件则有了一些特殊额外的操作。
系统签名JKS需要Linux环境
,Linux环境配置教程
1. 签名资料准备
1. 首先需要准备签名文件
它们在Android系统源码build\target\product\security 。签名文件有四种类型,它们必定是成对出现的(.pem,.pk8代表私钥,.x509.pem代表公钥 )
可以看见Android的签名有四种类型media,platform,shared,testkey四种。经过四种签名的apk具有不同的权限。
2. 准备签名工具signapk.jar
它在系统源码的out/host/linux-x86/framework/signapk.jar 中
3.签名工具 keytool-importkeypair
下载地址:
https://github.com/getfatday/keytool-importkeypair
2. JKS文件生成
签名文件及操作方法资源我
系统签名JKS文件需要在Linux环境下生成,在Windows环境下无法生成。linux下执行命令如下:
./keytool-importkeypair -k djKey.jks -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias djKey
注意:
1. 文件夹的名字一定要是keytool-importkeypair
2. platform.pk8和platform.x509.pem文件每个Android系统都可能不一样,请自己替换
3. JKS生成中遇到的问题
1 ./keytool-importkeypair: Permission denied
在Linux系统中生成签名文件时,可能会碰到该问题。此为文件权限不够,在keytool-importkeypair文件夹的上一层执行如下命令即可。
chmod 7777 keytool-importkeypair
2. bash: keytools: command not found
Linux系统下没有安装JDK环境。需要安装JDK并部署环境。
Linux系统下载安装JDK请参考
在过程中如果碰
JDK环境配置
// JAVA_HOME目录写对,绝对路径
export JAVA_HOME=/java/jdk1.7.0_79
export CLASSPATH=.:%JAVA_HOME%/lib/dt.jar:%JAVA_HOME%/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
APK静默安装
我们在软件更新部分经常会自己检查服务器是否有更新的APK版本。有最新版本下载后就进行安装。
静默安装实质就是安装APK,此时不再弹出询问使用者是否安装等弹框,可直接无感Android后台运行。
所以静默安装是一种不安全的行为,使用请谨慎选择。请注意静默安装的APK可以是普通APK也可以是经系统签名文件签名的 系统APK。
/**
* m命令可以通过adb在shell中执行,同样,我们可以通过代码来执行
* execCommand("pm","install","-f",filePath);//安装apk,filePath为apk文件路径,如/mnt/sdcard/ApiDemos.apk
* ("pm", "install", "-r", apkFile)
* execCommand("pm","uninstall", packageName);//卸载apk,packageName为包名,如com.example.android.apis
*/
public static String execCommand(String... command) {
Process process = null;
InputStream errIs = null;
InputStream inIs = null;
String result;
try {
process = new ProcessBuilder().command(command).start();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int read;
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);
}
result = new String(baos.toByteArray());
} catch (IOException e) {
result = e.getMessage();
} finally {
try {
if (inIs != null) {
inIs.close();
}
if (errIs != null) {
errIs.close();
}
if (process != null) {
process.destroy();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
ROOT安装法
该方法安装的的APK不一定是系统签名APK,但是要求手机必须Root过。
该方法缺点明显:
- 手机需要root过,可能引起其他安全隐患
- 如果你是本安装了APK,现在是版本更细下载后想实现静默安装,第一次安装会弹出一个该软件申请授权root权限的弹框,静默安装完全无感的效果打折扣。
在自己的软件产品中第一次安装都需要给软件授权root权限,一但弹框中拒绝授予root权限,该弹框后面不在出现,只能通过root精灵类的软件手动设置授权。
root安装法的java调用代码如下:
/**
* 执行具体的静默安装逻辑,需要手机ROOT,且调用该代码的app也需要授权root权限。
* @param apkPath 要安装的apk文件的路径
* @return 安装成功返回true,安装失败返回false。
*/
public boolean installRoot(String apkPath) {
boolean result = false;
DataOutputStream dataOutputStream = null;
BufferedReader errorStream = null;
try {
// 申请su权限,第一次软件调用会弹出 请求授予软件root权限的弹出框
Process process = Runtime.getRuntime().exec("su");
dataOutputStream = new DataOutputStream(process.getOutputStream());
// 执行pm install命令
String command = "pm install -r " + apkPath + "\n";
dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));
dataOutputStream.flush();
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
process.waitFor();
errorStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
StringBuilder msg = new StringBuilder();
String line;
// 读取命令的执行结果
while ((line = errorStream.readLine()) != null) {
msg.append(line);
}
Log.d("TAG", "install msg is " + msg);
// 如果执行结果中包含Failure字样就认为是安装失败,否则就认为安装成功
if (!msg.toString().contains("Failure")) {
result = true;
}
} catch (Exception e) {
Log.e("TAG", e.getMessage(), e);
} finally {
try {
if (dataOutputStream != null) {
dataOutputStream.close();
}
if (errorStream != null) {
errorStream.close();
}
} catch (IOException e) {
Log.e("TAG", e.getMessage(), e);
}
}
return result;
}
/**
* 判断手机是否拥有Root权限。
* @return 有root权限返回true,否则返回false。
*/
public boolean isRoot() {
boolean bool = false;
try {
bool = new File("/system/bin/su").exists() || new File("/system/xbin/su").exists();
} catch (Exception e) {
e.printStackTrace();
}
return bool;
}
总结
文章主要讲解了系统app 的JKS文件生成和静默安装流程,一般此类的软件针对定制化App软件。