技术经验谈 技术经验谈
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

hss01248

一号线程序员
首页
  • 最佳实践

    • 抓包
    • 数据库操作
  • ui

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • 总纲
  • 整体开发框架
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 编译和自动化

    • gradle基础
    • gradle-task
    • appbundle打包的自动化
      • bundlerelease打包输出路径如下:
      • bundletool.sh
      • bun_install.sh(一键安装apks)
    • cmake vs gradle
    • cmake入门
    • gradle依赖管理
    • gradle加速之拉取依赖的加速
    • gradle远程脚本
    • maven
    • 多module时自动发布所有lib
    • 将react native打包成一个aar
  • 异常上报和监测

  • SDK封装方法论
  • 结构化文档一键转代码的实践-埋点-翻译-java api注释
  • 防御式编程例子1-颜色解析工具的处理
  • 工程方法
  • 编译和自动化
hss01248
2021-05-19
目录

appbundle打包的自动化

# appbundle打包的自动化

app bundle是谷歌的一个打包方式,输出的是未签名的aab文件

拿到aab文件不能直接安装,要先用谷歌提供的bundletools.jar基于aab生成apks文件,然后使用bundletools.jar install来安装apks文件

每次手动运行bundletools.jar命令行很蛋疼,可以结合shell脚本和gradle脚本,直接在运行bundleDebug或者bundleRelease打包时直接拿到aab,apks,以及解压apks得到真正的apk. 以及脚本运行apks

# 首先,在项目根目录下放置好bundletool和keystore

image-20210519171454060

# bundlerelease打包输出路径如下:

使用outputs下的bundleapks作为生成的apks目录

image-20210519171646907

# 然后编写shell脚本.

本质上就是调用bundletools的命令:

其他无非是处理各种路径,删除上次的文件等问题.

java -jar $bundletool build-apks --bundle=$aabFile --output=$apks --ks=$RELEASE_STORE_FILE --ks-pass=pass:$RELEASE_KEY_PASSWORD --ks-key-alias=$RELEASE_KEY_ALIAS --key-pass=pass:$RELEASE_KEY_PASSWORD
1

以及安装:

# 安装apks
java -jar $bundletool install-apks --apks=$apks
#打开app
adb shell am start -n 包名/activity名
1
2
3
4

此处将apks的生成和安装分离,均放置于项目根目录下

image-20210519172132631

全部脚本如下:

# bundletool.sh

#!/bin/bash
set -e

#echo "\033[33m === 请输入aab文件名 === \033[0m"

#echo "\033[05m"

#read aabFileName
#bundletool解析出的apks路径
###获取脚本执行的目录
SCRIPTDIR="$( cd "$( dirname "$0"  )" && pwd  )"
echo "当前文件夹:"$SCRIPTDIR


#bundletool路径
bundletool=$SCRIPTDIR/doc/bundletools/bundletool-all-1.2.0.jar

#数字签名证书密码别名
RELEASE_KEY_PASSWORD=xxxxx
RELEASE_KEY_ALIAS=xxxxx
RELEASE_STORE_PASSWORD=xxxxx
#数字签名证书的文件路径
RELEASE_STORE_FILE=$SCRIPTDIR/doc/keystore/xxxx


#if [ -e $apks ]
#then
#    rm -rf $apks
#fi

#接收用户输入的aab文件路径
aabDir=$SCRIPTDIR/app/build/outputs/bundle/release/

echo "aabDir:"$aabDir

# 遍历文件夹outputs/bundle/release
files=$(ls $aabDir)
for filename in $files
do
echo $filename

aabFile=$aabDir$filename
apks=$SCRIPTDIR/app/build/outputs/bundleapks/$filename.apks
echo "aab文件路径:"$aabFile
echo "开始生成apks:"$apks
#先查找本地是否存在apks文件,存在就删除
if [ -e $apks ]
then
    rm -rf $apks
fi

java -jar $bundletool build-apks --bundle=$aabFile --output=$apks --ks=$RELEASE_STORE_FILE --ks-pass=pass:$RELEASE_KEY_PASSWORD --ks-key-alias=$RELEASE_KEY_ALIAS --key-pass=pass:$RELEASE_KEY_PASSWORD
# java -jar $bundletool install-apks --apks=$apks
echo "\033[32m === apks已经生成,开始自动zip解压(gradle脚本处),提取内部apk,也可以另外运行脚本(sh bun_install.sh)安装 === \033[0m"
echo "apks路径:点击打开:"$SCRIPTDIR/app/build/outputs/bundleapks/
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

# bun_install.sh(一键安装apks)

#!/bin/bash
set -e

#echo "\033[33m === 请输入aab文件名 === \033[0m"

#echo "\033[05m"

#read aabFileName
#bundletool解析出的apks路径
###获取脚本执行的目录
SCRIPTDIR="$( cd "$( dirname "$0"  )" && pwd  )"
echo "当前文件夹:"$SCRIPTDIR


#bundletool路径
bundletool=$SCRIPTDIR/doc/bundletools/bundletool-all-1.2.0.jar



#接收用户输入的aab文件路径
aabDir=$SCRIPTDIR/app/build/outputs/bundle/release/

echo "aabDir:"$aabDir

files=$(ls $aabDir)
for filename in $files
do
echo $filename

aabFile=$aabDir$filename
apks=$SCRIPTDIR/app/build/outputs/bundleapks/$filename.apks
echo "aab文件路径:"$aabFile
echo "apks:"$apks




java -jar $bundletool install-apks --apks=$apks
#打开app
adb shell am start -n 包名/activity全限定名

echo "\033[32m === 已安装aab到手机,请前往手机验证功能 === \033[0m"
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

以上脚本可以先使用命令行运行调通,再与gradle对接.

# 使用gralde来运行上述shell脚本

gradle打包监听的完成回调里,执行上述shell

在根目录的build.gradle里:

this.gradle.addBuildListener(new BuildListener() {
    @Override
    void buildStarted(Gradle gradle) {
        println '--->buildStarted...'
        println(gradle.startParameter.taskNames)
    }

    @Override
    void settingsEvaluated(Settings settings) {
        println '--->settingsEvaluated...'
    }

    @Override
    void projectsLoaded(Gradle gradle) {
        println '--->projectsLoaded...'
    }

    @Override
    void projectsEvaluated(Gradle gradle) {
        println '--->projectsEvaluated...开始打包'
        println '--->根目录:'+ getRootDir().absolutePath
        

    }

    @Override
    void buildFinished(BuildResult result) {
        println '--->buildFinished...'
        println("taskNames:"+gradle.startParameter.taskNames)
        List<String> names = gradle.startParameter.taskNames;
       if(names != null && names.size()>0){
           if("bundleRelease".equalsIgnoreCase(names.get(0))){
             //只在bundleRelease打包时才执行脚本
               exec {
                   executable "./bundletool.sh"
               }
               println '--->bundletool finished'
               unzipApks();
           }
       }


    }
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

unzipApks()方法:

groovy虽然提示不够只能,但是可以和java代码混着写,就是这么任性

def unzipApks(){
    String dirPath = getRootDir().absolutePath+"/app/build/outputs/bundleapks/"
    println '--->目录:'+ dirPath
    File dir = new File(dirPath);
    if(!dir.exists()){
        println '--->目录不存在:'
        return
    }
    def files = dir.listFiles(new FilenameFilter() {
        @Override
        boolean accept(File file, String s) {
            return s.endsWith(".apks")
        }
    })
    if(files == null || files.length ==0){
        println '--->文件夹里没有apks文件'
        return
    }
    for (int i = 0; i < files.length; i++) {
        File file = files[i];
        File dir2 = new File(dir,file.getName());
        dir2.mkdirs();
        unZipFiles(file);

    }
}



def unZipFiles(File zipFile)  {

    try {
        ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"));//解决中文文件夹乱码
        String name = zip.getName().substring(zip.getName().lastIndexOf('\\')+1, zip.getName().lastIndexOf('.'));
        println("name:"+name)

        File pathFile = new File(name);
        if (!pathFile.exists()) {
            pathFile.mkdirs();
        }
        println("pathFile:"+name)

        for (Enumeration<? extends ZipEntry> entries = zip.entries(); entries.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            String zipEntryName = entry.getName();
            InputStream inputStream = zip.getInputStream(entry);
            String outPath = (name +"/"+ zipEntryName).replaceAll("\\*", "/");

            // 判断路径是否存在,不存在则创建文件路径
            File file = new File(outPath.substring(0, outPath.lastIndexOf('/')));
            if (!file.exists()) {
                file.mkdirs();
            }
            // 判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
            if (new File(outPath).isDirectory()) {
                continue;
            }
            // 输出文件路径信息
//			System.out.println(outPath);
            println '--->outPath:'+outPath
            FileOutputStream out = new FileOutputStream(outPath);
            byte[] buf1 = new byte[1024];
            int len;
            while ((len = inputStream.read(buf1)) > 0) {
                out.write(buf1, 0, len);
            }
            inputStream.close();
            out.close();
        }
        System.out.println("******************apks解压完毕********************");
    }catch(Throwable throwable){
        throwable.printStackTrace()
    }


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

我们可以看到最终效果:

Standalones里的就是可以直接分发的apk

image-20210519173150314

编辑 (opens new window)
上次更新: 2022/08/25, 20:20:31
gradle-task
cmake vs gradle

← gradle-task cmake vs gradle→

最近更新
01
截图后的自动压缩工具
12-27
02
图片视频文件根据exif批量重命名
12-27
03
chatgpt图片识别描述功能
02-20
更多文章>
Theme by Vdoing | Copyright © 2020-2025 | 粤ICP备20041795号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式