手机系统App开发人员编写代码时使用AndroidStudio,编译时通过 Android.mk 编译,在 Android9.0 上模块编译速度更是不敢恭维,用时单位是以分钟计算的。为了解决编译速度问题,强烈推荐使用 AndroidStudio编译。但是通过gradle编译又会出现各种问题,例如安装android:sharedUserId="android.uid.system"权限的APK
,没关系,下面就带你一一解决这些问题。
我们的App需要系统权限时,需要在 AndroidManifest.xml 配置
android:sharedUserId="android.uid.system"
这样配置后直接是无法运行的,因为签名必须是平台签名,我们需要对其进行系统签名然后方可安装。
build/target/product/security/
)下将 keytool-importkeypair、platform.pk8和platform.x509.pem文件放在同一个目录下,执行如下命令,生成platform.keystore文件:
./keytool-importkeypair -k platform.keystore -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias platform
下面是本人自己执行的及输出结果,底部有Warning 没有关系。
nan@breeze:~/Tools/sign_app/keytool-importkeypair-master$ ./keytool-importkeypair -k platform.keystore -p 123456 -pk8 platform.pk8 -cert platform.x509.pem -alias platform
Importing "platform" with SHA1 Fingerprint=5A:73:D9:4D:F2:CF:1B:6C:41:71:98:BB:C2:16:E4:4F:4D:F6:70:D3
Importing keystore /tmp/keytool-importkeypair.Wqxz/p12 to platform.keystore...
Entry for alias platform successfully imported.
Import command completed: 1 entries successfully imported, 0 entries failed or cancelled
Warning:
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore platform.keystore -destkeystore platform.keystore -deststoretype pkcs12".
platform.keystore
,也可以为platform.jks
,名称任意起。123456
x.509
的数字证书,里面有用户的公钥等信息,是用来解密的,这种文 件格式里面不仅可以存储数字证书,还能存各种key。(有兴趣的可以点击此了解一下)另外keytool -list -v -keystore xxx.jks可以查看key的详细信息
nan@breeze:~/Tools/sign_app/keytool-importkeypair-master$ keytool -list -v -keystore platform.keystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: platform
Creation date: Dec 7, 2019
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: [email protected], CN=VPN, OU=Software Engineering, O=XXX Networks, L=City of Industry, ST=California, C=US
Issuer: [email protected], CN=VPN, OU=Software Engineering, O=XXX Networks, L=City of Industry, ST=California, C=US
Serial number: eccdd3f4278092c5
Valid from: Wed Oct 30 10:25:50 CST 2019 until: Sun Mar 17 10:25:50 CST 2047
Certificate fingerprints:
MD5: E5:74:F5:01:F4:FA:E3:EE:2D:B4:48:6D:FC:A0:B1:6F
SHA1: 5A:73:D9:4D:F2:CF:1B:6C:41:71:98:BB:C2:16:E4:4F:4D:F6:70:D3
SHA256: CF:AA:1F:D4:71:6E:74:E2:47:5F:C4:84:B0:86:B9:74:BE:98:46:58:3D:AE:17:20:B4:34:DC:F3:F1:37:D0:9C
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
...
模块的build.gradle中配置如下
defaultConfig {
applicationId "com.base.module.callapp"
minSdkVersion 28
targetSdkVersion 29
versionCode 1
versionName "1.0"
}
// wangyannan add begin
signingConfigs {
release {
// CallApp/signapk/platform.keystore 自己创建路径,放入即可,其他路径也可以
storeFile file("../signapk/platform.jks")
storePassword '123456'
keyAlias 'platform'
keyPassword '123456'
}
debug {
storeFile file("../signapk/platform.jks")
storePassword '123456'
keyAlias 'platform'
keyPassword '123456'
}
}
// wangyannan add end
大功告成,已经可以运行了,可能会提示与系统中安装的APK签名不一致,替换即可。如果无法运行,rebuild一下或者重启studio 即可。
但是这只是可以运行带有android.uid.system
权限的APP。假如我们需要使用com.android.internal.R.drawable.ic_text_dot
类似这种系统内部资源或者API时,我们是没有提示的,且会编译错误,但是作为系统APP本应是可以使用的,怎么解决?下面这种方法获取
Resources.getSystem().getIdentifier("ic_text_dot", "drawable", "android")
这种方法是针对第三方APP的,未免对于我们具有系统权限的APP有点掉价,一个字low,两个字庸俗。
看我怎么教你就通过com.android.internal.R.drawable.ic_text_dot
这种使用,且具有提示。
jar包为
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
,class.jar 重命名为framework.jar
。
ScanSettings/app/libs/framework.jar
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.2.0-alpha02'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// wangyannan add begin
compileOnly files('libs/framework.jar')
// wangyannan end end
}
这时运行可能遇到两个问题,别怕,我会告诉你解决办法。
模块APP的build.gradle 加入如下code
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.2.0-alpha02'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// wangyannan add begin
compileOnly files('libs/framework.jar')
// wangyannan end end
}
// wangyannan add begin
preBuild {
doLast {
def imlFile = file(project.name + ".iml")
println 'Change ' + project.name + '.iml order'
try {
def parsedXml = (new XmlParser()).parse(imlFile)
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
parsedXml.component[1].remove(jdkNode)
def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
} catch (FileNotFoundException e) {
// nop, iml not found
}
}
}
// wangyannan add end
工程build.gradle加入
allprojects {
repositories {
google()
jcenter()
}
// wangyannan add begin, 最好全路径,相对路径不一定能过
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:/home/nan/Dog/project/wp850/android/packages/apps/ScanSettings/app/libs/framework.jar')
}
}
// wangyannan add end
}
加入这些是为了解决Androidstudio默认使用自带sdk,而不使用framework.jar的问题。
编译失败是由于Android存在只能有 64k 个方法的限制,这是由于Dalvik执行规则限制。我们可以通过开启 Multidex 即可绕过 64k 限制,如果你的 minSdkVersion 设置为 21 或更高值,默认情况下就启用了多 dex 文件,但如果小于,可以参考官方文档开启。具体可见点此处。
此时如果还是报错,请确保 AndroidStudio 兼容 java8,具体配置如下
android {
...
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
好了,这个时候世界就美好了。
如果这篇文章对你有用,请留个赞:),如果有疑问也可以留言哦!,
参考: