android 系统应用签名及问题处理
在做系统级的APP开发时,我们就会给app签名。这个不是我们通常的签名打包,有所不同。要拿到的两个文件platform.x509.pem,platform.pk8它们存放在系统的/build/target/product/security/目录下,当然这个是要你对应的android系统开发提供的,拿到这两个文件后就可以做我们的app签名了。
当然你可以cmd签名方式生成apk,后面会说项目需要添加的东西,这里先跳过。
只需要这个两个文件的文件夹下,打开终端切换到这个路径输入(xxx为你放入你打包的apk,XXXNew是你生成的apk名称)
java -jar signapk.jar platform.x509.pem platform.pk8 XXX.apk XXXNew.apk
这个就能生成你的签名系统应用包了。
但是这样不方便我们打包,也不能使用jenkins自动打包。下面我要说的就是生成一个keystore签名文件。来实现系统应用签名。
1.下载keytool工具。和上面两个文件放在同一目录下。
sh keytool-importkeypair -k ./platform.keystore -p android -pk8 platform.pk8 -cert platform.x509.pem -alias platform
- -p 表示新生成的keystore的密码是什么,这里为android
- -pk8 表示要导入的pk8文件的名称,可以包括路径,pk8文件用来保存private key的,是个私钥文件。
- -cert 表示要导入的证书文件,和pk8文件在同一个目录,pem这种文件就是一个X.509的数字证书,里面有用户的公钥等信息,是用来解密的,这种文 件格式里面不仅可以存储数字证书,还能存各种key。(有兴趣的可以点击此了解一下)
- -alias 表示给生成的platform.keystore取一个别名,这个名字只有我们在签名的时候才用的到,这里我们生成的文件名是platform。这个名字,可以随便取,但是你自己一定要记住。
2.AndroidManifest.xml修改
AndroidManifest.xml中添加共享系统进程属性,如下:
android:sharedUserId="android.uid.system"
android:sharedUserId="android.uid.shared"
android:sharedUserId="android.media"
根据自己需求添加,因为我们测试验证用的是platform的,所以在xml中添加的是android:sharedUserId="android.uid.system"。
到这里如果你没有用到webview基本就只是前签名文件的配置就可以了
当然一般项目都会用到。那么就签名成功后的apk,当你加载webview时候就报应用闪退。
你会看到这样的报错信息。
See android 5.1 source code below
static WebViewFactoryProvider getProvider() {
synchronized (sProviderLock) {
// For now the main purpose of this function (and the factory abstraction) is to keep
// us honest and minimize usage of WebView internals when binding the proxy.
if (sProviderInstance != null) return sProviderInstance;
final int uid = android.os.Process.myUid();
if (uid == android.os.Process.ROOT_UID || uid == android.os.Process.SYSTEM_UID) {
throw new UnsupportedOperationException(
"For security reasons, WebView is not allowed in
privileged processes");
}
...
Android do such security check during creating WebViewFactory
's field sProviderInstance
(when it is null), and sProviderInstance
is a static field. So we can make a instance of sProviderInstance
before the security check by using reflection.
不同android版本的源码有所不用,需要用反射做下兼容处理。
public static void hookWebView(){
int sdkInt = Build.VERSION.SDK_INT;
try {
Class<?> factoryClass = Class.forName("android.webkit.WebViewFactory");
Field field = factoryClass.getDeclaredField("sProviderInstance");
field.setAccessible(true);
Object sProviderInstance = field.get(null);
if (sProviderInstance != null) {
Log.i(TAG,"sProviderInstance isn't null");
return;
}
Method getProviderClassMethod;
if (sdkInt > 22) {
getProviderClassMethod = factoryClass.getDeclaredMethod("getProviderClass");
} else if (sdkInt == 22) {
getProviderClassMethod = factoryClass.getDeclaredMethod("getFactoryClass");
} else {
Log.i(TAG,"Don't need to Hook WebView");
return;
}
getProviderClassMethod.setAccessible(true);
Class<?> factoryProviderClass = (Class<?>) getProviderClassMethod.invoke(factoryClass);
Class<?> delegateClass = Class.forName("android.webkit.WebViewDelegate");
Constructor<?> delegateConstructor = delegateClass.getDeclaredConstructor();
delegateConstructor.setAccessible(true);
if(sdkInt < 26){//低于Android O版本
Constructor<?> providerConstructor = factoryProviderClass.getConstructor(delegateClass);
if (providerConstructor != null) {
providerConstructor.setAccessible(true);
sProviderInstance = providerConstructor.newInstance(delegateConstructor.newInstance());
}
} else {
Field chromiumMethodName = factoryClass.getDeclaredField("CHROMIUM_WEBVIEW_FACTORY_METHOD");
chromiumMethodName.setAccessible(true);
String chromiumMethodNameStr = (String)chromiumMethodName.get(null);
if (chromiumMethodNameStr == null) {
chromiumMethodNameStr = "create";
}
Method staticFactory = factoryProviderClass.getMethod(chromiumMethodNameStr, delegateClass);
if (staticFactory!=null){
sProviderInstance = staticFactory.invoke(null, delegateConstructor.newInstance());
}
}
if (sProviderInstance != null){
field.set("sProviderInstance", sProviderInstance);
Log.i(TAG,"Hook success!");
} else {
Log.i(TAG,"Hook failed!");
}
} catch (Throwable e) {
Log.w(TAG,e);
}
}
包括兼容android8.0.在Application OnCreate方法中加入上面方法即可。
如何你不清楚如何在build.gradle中配置签名文件。那么我下片写一篇如何配置以及jenkins动态变量配置的文章
本文地址:https://blog.csdn.net/chengzuidongfeng/article/details/107941916
下一篇: Aidl进阶 ----- 自定义类型传输