前提:在游戏出包时,一个母包出多个子包,往往会遇到游戏母包在AndroidManifest配置的fileProvider,或推送是同一个包名时;
如果出子包不去处理这个,会导致打出来的游戏子包,由于同一包名的配置,手机安装不了多个游戏子包。
以下通过shell脚本的命令行来自动替换成打不同子包,配置不同的包名的fileProvider或推送。
思路:通过反编译,获取到AndroidManifest文件的包名和配置的fileProvider或推送的包名进行替换修改,即可实现。
一、编写获取到AndroidManifest文件的包名和fileProvider配置的包名进行替换的jar包
public class ModifyAndroidManifest {
public static void main(String[] args) {
String inputPathName=args[0];//读取AndroidMainifest文件的路径
String outputPathName=args[1];//输出AndroidManifest文件的路径
String packageName="";
String str_provider="";
try {
FileReader reader = new FileReader(inputPathName);
BufferedReader br = new BufferedReader(reader);
FileWriter writer = new FileWriter(outputPathName);
BufferedWriter bw = new BufferedWriter(writer);
String str = null;
while((str = br.readLine()) != null) {
if(str.contains("xmlns")||str.contains("FileProvider")){
String[] arr=str.split(" ");
for(String sr:arr){
//获取包名
if(sr.contains("package")){
String[] packageArr=sr.split("=");
packageName=packageArr[1].substring(1,packageArr[1].length()-1);
System.out.println(packageArr[1].substring(1,packageArr[1].length()-1));
}else if(sr.contains("authorities")){
String[] providerArr=sr.split("=");
String provider=providerArr[1].substring(1,providerArr[1].length()-1);
System.out.println(providerArr[1].substring(1,providerArr[1].length()-1));
str_provider=str.replace(provider,packageName);
continue;
}
}
}
if(str.contains("FileProvider")) {
bw.write(str_provider);
}else{
bw.write(str);
}
bw.newLine();
}
br.close();
reader.close();
bw.close();
writer.close();
}
catch(FileNotFoundException e) {
e.printStackTrace();
}
catch(IOException e) {
e.printStackTrace();
}
}
}
在项目的build.gradle文件下配置打出jar包生成的程序
task makeFileProviderJar(type: FatCapsule){
applicationClass 'com.appgame.tool.androidmanifest.ModifyAndroidManifest'
baseName "fileProvider_${signToolVersion}"
}
二、编程shell脚本实现自动替换
#!/bin/bash
# 应用包 build apk script
# file name build-tencent.sh
# ---------配置信息 BEGIN----------
# 游戏APK名字,注意不带后缀
gameApk="zlhcsdzy"
# ---签名信息---
keystoreFile="demo.jks"
keyName="demogame"
keyPassword="123456789"
# 最终打包生成的发布目录
apkReleaseDir="release"
# ---APK命名信息---
# APK最终包的名字
apkReleaseName=${gameApk}-signed.apk
# APK未签名的名字
apkUnsignName=${gameApk}-unsigned.apk
# 创建目录
createDir(){
if [[ ! -d $1 ]]; then
mkdir $1
fi
}
# 反编译APK
decompileApk(){
apktool d -s -f $1
}
# 生成APK
buildApk(){
apktool b $1
}
# 签名
apkSigner(){
jarsigner -verbose -keystore $1 -storepass $3 -signedjar $4 $5 $2 -digestalg SHA1 -sigalg MD5withRSA
}
# ---复制资料到游戏反编译目录 END---
decompileApk "./${gameApk}.apk"
cp ./$gameApk/AndroidManifest.xml ./
#---运行实现包名替换的jar------
java -jar ./fileProvider_1.0.0.jar ./AndroidManifest.xml ./$gameApk/AndroidManifest.xml
buildApk "./$gameApk"
cp ./$gameApk/dist/${gameApk}.apk ./$apkUnsignName
apkSigner "$keystoreFile" "$keyName" "$keyPassword" "$apkReleaseName" "$apkUnsignName"
createDir "$apkReleaseDir"
mv -f ./$apkReleaseName ./$apkReleaseDir
echo "build success"
echo "删除没用文件"
rm -rf ./${gameApk}
rm -f ./$apkUnsignName