Android Apk一键打包上传至蒲公英平台的gradle脚本

news2025/1/13 9:36:34

一、背景

项目中每次手动打包后,生成的测试包,都需要手动打开蒲公英平台的网址,登录账号,手动上传apk。之前写过一键上传至fir平台的脚本,想着这次可以搞一下一键打包上传至蒲公英的gradle脚本,提高下工作效率(关键每次都是我们开发自己手动打包,再手动上传蒲公英,太繁琐~)

在这里插入图片描述

二、gradle脚本安排

1、创建gradle脚本文件

因为脚本涉及到上传功能,所以需要网络请求,而蒲公英平台已经提供好了一套相关的Api接口:蒲公英接口2.0

而蒲公英官方提供了新版旧版上传两种方式,我自己曾先尝试了新版(快速上传)的上传方式,但是在尝试过程中,发现一直报一个错,后来由于时间的缘故,改为了旧版的上传方式,后面有时间了再研究下新版的上传。
在这里插入图片描述
新版上传
旧版上传接下来的gradle脚本主要以旧版上传为主,有哪位大佬,使用了新版上传,可以在评论区贴下脚本链接,向大佬学习下~

由于使用到了网络请求,这里使用到了OKhttp(当然也可以不使用Okttp请求使用其他网络请求库),所以需要引入下Okhttp库。
首先创建一个上传脚本gradle文件,我这里命名为pack-release.gradle
我把pack-release.gradle放到了项目工程的gradle文件夹下:

在这里插入图片描述

2、在pack-release.gradle中引入okhttp库
buildscript {
    repositories {
        mavenCentral()

        dependencies {
            classpath rootProject.ext.dependencies.okhttp//1.添加依赖
        }
    }
}

这里我使用的是okhttp版本是: 3.14.9
在这里插入图片描述在这里插入图片描述

3、定义task
task("uploadPgy") {
    group 'pack'
    dependsOn("app:assembleXXXRelease") 

    doLast {
        uploadApk()
    }
}

在这里定义了一个名字叫:uploadPgy的task。注意到里面还有一行group ‘pack’,这个意思是这个task任务会在pack文件夹下出现

在这里插入图片描述

dependsOn(“app:assembleXXXRelease”) 这里是这个task依赖于"app:assembleXXXRelease"
这个task任务。而"app:assembleXXXRelease"
中的app即为,主module的名字,如果主module名字为app那么这里写app,如果主module名字为mmm,这里也写mmm。
而后面assembleXXXRelease即为,项目打包的任务命令

4、定义uploadApk方法
/**
 * 上传apk到蒲公英
 */
def uploadApk() {

    def apkFile
    rootProject.subprojects {
        if (it.name == 'app') {//此处根据gradle project的名字查找到对应module下需要上传的apk
            //查找上传的apk文件
            def apkDir = new File(it.buildDir.path + "/outputs/apk/xxx", "release")
            if (!apkDir.exists()) {
                apkDir = new File(it.buildDir.path + "/intermediates/apk/iguopin", "release")
            }
            if (!apkDir.exists()) {
                throw new RuntimeException("apk output path not exists!")
            }


            def modified = 0
            def lastModifiedDir = apkDir
            //寻找当前路径下最新apk包所在路径
            apkDir.listFiles().each { dir ->
                def last = dir.lastModified()
                if (dir.isDirectory() && last > modified) {
                    modified = last
                    lastModifiedDir = dir
                }
            }

            //println("lastModifiedDir=====$lastModifiedDir")

            //寻找当前路径下后缀为apk、名称包含release字样的文件
            def apkfiles = lastModifiedDir.listFiles(new FilenameFilter() {
                @Override
                boolean accept(File dir, String name) {
                    //println("name=====$name")
                    return (name.endsWith('.apk') && name.contains('XX_64_'))
                }
            })
            if (apkfiles == null || apkfiles.length == 0) {
                println("出错啦!没有找到apk文件")
                return
            }
            //由于我们的项目对每次打包的包名根据时间戳进行命名, 默认第一个为最新包,所以取first
            apkFile = apkfiles.first()
        }
    }

    println "********************************************* start upload file *********************************************"
    println ""
    println ""
    println "正在上传的apk的本地路径:==================》   $apkFile"
    println ""
    println ""
    println "正在上传,请稍等。。。。。。。。。。。。。"
    println("")
    println("")

    def response = uploadToPgyer(apkFile)
    def uploadBean = new JsonSlurper().parseText(response)
    def buildVersion = uploadBean['data']['buildVersion']//版本名称
    def buildVersionNo = uploadBean['data']['buildVersionNo']//版本号
    def buildBuildVersion = uploadBean['data']['buildBuildVersion']//蒲公英平台apk的build版本
    def buildCreated = uploadBean['data']['buildCreated']//apk上传时间


    println("")
    println "********************************************* upload finish *********************************************"
    println ""
    println ""
    println "上传时间:==================》   $buildCreated"
    println "版本名称:==================》   $buildVersion"
    println "版本号:==================》   $buildVersionNo"
    println "蒲公英平台apk的build版本:==================》   $buildBuildVersion"

    if (uploadBean.code != 0) {
        throw new RuntimeException(uploadBean.message)
    }

    //浏览器中打开短连接
    def url = "https://www.pgyer.com/" + uploadBean.data.buildKey
    println "最新下载地址:$url"
    exec {
        commandLine 'open', url
    }
}
5、定义uploadToPgyer方法
// 自定义上传方法
def uploadToPgyer(File apkFile) {

    // 蒲公英上传配置
    def pgyerUploadUrl = "https://www.pgyer.com/apiv2/app/upload"
    def pgyerApiKey = "蒲公英平台的apiKey"   //蒲公英平台需要实名认证才能拿到apiKey
    def uploadUrl = pgyerUploadUrl + "?_api_key=" + pgyerApiKey

    OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(15, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .build()


    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file", apkFile.name, RequestBody.create(MediaType.parse("application/octet-stream"), apkFile))
            .addFormDataPart("_api_key", pgyerApiKey)
            .build()

    Request request = new Request.Builder()
            .url(uploadUrl)
            .post(requestBody)
            .build()

    Response response = client.newCall(request).execute()
    return response.body().string()
}

脚本中:

		//浏览器中打开短连接
    def url = "https://www.pgyer.com/" + uploadBean.data.buildKey
    println "最新下载地址:$url"
    exec {
        commandLine 'open', url
    }

在上传成功后,还会自动用浏览器打开最新的apk下载地址。

三、在项目工程中引入脚本

脚本写好了,需要在项目中引入一下:在项目工程的build.gradle中引入:

apply from:"$rootDir/gradle/pack-release.gradle"

在这里插入图片描述

四、结语

好了,以上便是一键打包apk并上传至蒲公英平台的gradle脚本了。有什么问题,大家可以在评论区留言,共同学习~。我是Shy,一个永不停止学习的程序员

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1127753.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下QT打开文件选择对话框时,程序报错退出

系统:Ubuntu QString fileName QFileDialog::getOpenFileName(this, "open", "./", "document Files (*.pdf)"); 调用该语句弹出文件对话框时,程序崩溃退出 错误提示: (Widget:5272): Gtk-WARNING **: 14…

73 应急响应-WEB分析phpjavaweb自动化工具

目录 应急响应:必备知识点:准备工作:有明确信息网站被入侵:无明确信息网站被入侵:常见分析方法: 演示案例:WindowsIISSql-日志,搜索LinuxBT_Nginxtp5-日志,后门360星图日志自动分析工…

Spring Cloud之服务注册与发现(Eureka)

目录 Eureka 介绍 角色 实现流程 单机构建 注册中心 服务提供者 服务消费者 集群搭建 注册中心 服务提供者 自我保护机制 原理分析 Eureka 介绍 Eureka是spring cloud中的一个负责服务注册与发现的组件,本身是基于REST的服务,同时还提供了…

虚拟化 vs. 裸金属:K8s 部署环境架构与特性对比

伴随着 IT 云化转型的逐步推进,越来越多的用户加入应用容器化改造的行列,并使用 Kubernetes(K8s)进行容器部署管理。然而,令不少用户感到困惑的是,由于大部分应用此前都部署在虚拟化或超融合环境&#xff0…

批量处理图片,轻松转换JPG到TIFF,让你的图片管理更优化!

作为图片处理的专业人士,您可能经常需要处理大量的图片文件,其中包括各种不同的格式,如JPG、PNG、GIF等。然而,不同的格式有着不同的优缺点,有时候为了更好地保存和传输图片,您可能需要将其转换为其他格式。…

NEFU系统分析与设计

系统分析与设计概述 用户故事 用来描述用户希望得到的功能 三要素:角色、活动、商业价值 举例:作为一个“网站管理员”,我想要“统计每天有多少人访问了我的网站”,以便于“我的赞助商了解我的网站会给他们带来什么收益。 系统…

Jmeter(十二):线程组元件第三方插件的线程组压力和负载线程详解

线程组(thread group) 线程组元件是任何一个测试计划的开始点。在一个测试计划中的所有元件 都必须在某个线程下。所有的任务都是基于线程组。 一个线程组可以看做一个虚拟用户组,线程组中的每个线程都可以理解为一 个虚拟用户。多个用户同时去执行相同的一批次任…

升讯威在线客服系统的并发高性能数据处理技术:为多线程处理同步数据

我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户。对我来说,只要能获得用户的认可,就是我最大的动力。 最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可。 客户组织多名客服上线后&a…

uniapp跨域

配置 /manifest.json "devServer" : { "https" : false, "port" : 7101, "proxy": { "/api": { "target": "https://域名", "changeOrigin": t…

3D模型如何添加表面贴图?

1、模型表面贴图介绍 模型表面贴图(Texture Mapping)是一种将纹理映射到三维模型表面的技术,用于增加模型的细节和真实感。它通过在模型的每个表面点上应用纹理坐标,并将纹理像素与模型的对应点进行匹配,使得模型表面…

elasticSearch put全局更新和单个字段更新语法

1、如下:更新改类型未doc(文档)的全局字段数据 注意:如果你使用的是上面的语句,但是只写了id和title并赋值,图片上其他字段没有填写,执行命令后,则会把原文档中的其他字段都给删除了,你会发现查…

prosemirror 学习记录(二)创建 apple 节点

apple type 向 schema 中添加 apple type const nodes {apple: {inline: true,attrs: {name: { default: "unknown" },},group: "inline",draggable: true,parseDOM: [{tag: "span[custom-node-typeapple]",getAttrs(dom) {return {name: dom…

【高效开发工具系列】Apifox

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…

Vue单页面应用(SPA)怎么做SEO

在Vue单页面应用(SPA)中,由于内容的动态加载和路由切换,搜索引擎可能无法直接获取和索引页面的内容。不过,你可以采取一些策略来优化SEO,使你的Vue单页面应用在搜索引擎中更好地被索引和展示: 1:使用预渲染(Prerendering)或服务器端渲染(Server-Side Rendering,SS…

爬虫采集如何解决ip被限制的问题呢?

在进行爬虫采集的过程中,很多开发者会遇到IP被限制的问题,这给采集工作带来了很大的不便。那么,如何解决这个问题呢?下面我们将从以下几个方面进行探讨。 一、了解网站的反爬机制 首先,我们需要了解目标网站的反爬机制…

设计模式(13)适配器模式

一、介绍: 1、定义:是一种结构型设计模式,它可以将一个类的接口转换成客户端所期望的另一种接口。适配器模式常用于系统的不兼容性问题。 2、组成: (1)目标接口(Target)&#xff…

商品价格区间筛选

列表应用,商品价格区间筛选。 (本笔记适合熟悉python列表及列表的条件筛选的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么…

允许mysql远程访问

一、修改表 进入mysql,mysql -u root ,如果没有root用户,那么是可以直接进入的 使用 mysql数据库 use mysql 执行 update user set host% where userroot; 查询 用户表 select User,Host from user 把root用户的host改为 % 允许任何主…

elment-ui 日期选择器 月份区间选择的问题解决(含代码、截图)

elment-ui 日期选择器 月份区间选择的问题解决(含代码、截图) 参考文章: elment-ui 日期选择器 月份区间选择的问题解决官方文档参考:https://element.eleme.cn/#/zh-CN/component/date-picker 效果图: 代码案例&…