Gradle 自定义Plugin插件之上传APK到蒲公英
在之前的文章:Gradle 自定义Plugin插件介绍 中,介绍了通过Gradle自定义插件的几种方式。
作为一个的Coder,我们当然不希望我们自定义插件只是简单的打印log啦。比如,之前我们版本开发完成的时候,每次测试的流程都需要手动的打包,加固,上传,钉钉通知等等 。
现在,我们就通过自定义插件来实现一个打包完成后,自动上传到蒲公英的插件。
首先,在自定义这个插件的时候,我们需要弄明白几个问题。
- 既然是自动上传,肯定是在打包完的时候上传,那么什么时候打包完成或者说怎么让我们的插件再打包完了以后执行呢?
- 打包完成后,怎么自动上传?
- 自动上传肯定需要一些appkey等参数,怎么样传递我们的参数呢?
- 什么样的包,我们才上传到蒲公英提测呢?
Q1: 什么时候,打包完成?
Gradle的打包,其实也是一组组的Task任务,所以,我们只要在Assemble任务执行完了以后,再执行就可以了。
每个任务都有一个dependsOn()方法。我们只要,让我们的上传任务依赖打包任务就可以了
Q2:打包完成后,怎么自动上传?
我们能自动上传apk,需要提测的地方有公开的API,供我们调用。
这里,我们上传到蒲公英:蒲公英上传文档。
通过API,我们就可以实现自动上传了。当然,我们需要传递参数。
Q3:怎么参数传递?
我们知道Project是支持扩展的,我们可以通过
Extension customExtension = project.getExtensions().create(PLUGIN_EXTENSION_NAME, Extension.class);
把我们自定义的extension的数据类型,作为Project的一个扩展。
然后,在project里面有个回调方法,afterEvaluate(),它就会在构建完成后,执行。我们在这个方法里,来获取,就可以了。
Q4:什么样的包,我们才上传到蒲公英提测呢?
一般需要提测的肯定buildType都是release类型的包。但是,release包可能有一些其他的配置。如果,我们误操作很可能会造成不必要的包上传。
我们可以定义一个新的buidType。比如,uploadRelease?
这样,只有buildType是这个类型的时候,我们才上传,我们的apk。
到这里,我们就清楚了,我们要实现的步骤:
一、自定义Extension扩展
把我们需要传递的参数,通过它传递过来。
二、创建一个Task任务,上传apk
三、创建一个我们要上传的插件 实现 Plugin
在里面监听project.afterEvaluate()方法,以便完成后执行上传任务
四、项目引用插件
在构建回调里面,我们需要上传Task任务。上传Task任务,需要参数。在Gradle 自定义Plugin插件介绍中,我们使用的是Java语言,这里我们也用Java语言。
我们先定义一个project的扩展。
一、自定义extension扩展
这个里面都是,上传需要的参数,就是一个实体类。
public class Extension {public String uKey;public String apiKey;public String appName;public boolean useUpload;public Extension(){}public Extension(String appName,String uKey,String apiKey){this.uKey = uKey;this.apiKey = apiKey;this.appName = appName;}public Extension(String appName,String uKey,String apiKey,boolean useUpload){this.uKey = uKey;this.apiKey = apiKey;this.appName = appName;this.useUpload = useUpload;}public static Extension getConfig(Project project) {Extension extension = project.getExtensions().findByType(Extension.class);if (extension == null) {extension = new Extension();}return extension;}}
这就是一个简单的model类。主要有上传到蒲公英需要的uKey,apiKey等等
二、自定义任务,上传apk
有了上传的参数,我们就可以创建我们上传的任务了。
public class PGYUploadTask extends DefaultTask {private BaseVariant mVariant;private Project mTargetProject;public static class PGYRequest {public String uKey;public String apiKey;//1,install by public 2,install by password 3,install by invitepublic String installType;}public void init(BaseVariant variant, Project project) {this.mVariant = variant;this.mTargetProject = project;setDescription("upload to pgy");setGroup(TestJavaPlugin.PLUGIN_EXTENSION_NAME);}@TaskActionpublic void uploadToPGY() {for (BaseVariantOutput output : mVariant.getOutputs()) {File file = output.getOutputFile();if (file == null || !file.exists()) {throw new GradleException("apk file is not exist!");}Extension extension = Extension.getConfig(mTargetProject);PGYRequest request = new PGYRequest();request.apiKey = extension.apiKey;request.uKey = extension.uKey;upload(request.uKey, request.apiKey, file);}}private void upload(String ukey, String apiKey, File apkFile) {//builderMultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);//add partbodyBuilder.addFormDataPart("uKey", ukey);bodyBuilder.addFormDataPart("_api_key", apiKey);//add filebodyBuilder.addFormDataPart("file", apkFile.getName(), RequestBody.create(MediaType.parse("*/*"), apkFile));//requestRequest request = new Request.Builder().url("http://upload.pgyer.com/apiv1/app/upload").post(bodyBuilder.build()).build();OkHttpClient client = new OkHttpClient();try {Response response = client.newCall(request).execute();String result = response.body().string();System.out.println("upload result: " + result);} catch (IOException e) {e.printStackTrace();} catch (Exception e) {}}
}
这里,可以看出,我们就是使用OKHttp来调用api上传apk的。
并且通过upload result打印上传返回的结果。
添加了@TaskAction的注解后,我们的方法就会被执行。
通过BaseVariantOutput 获取apk的输入路径。通过Extension来获取要上传的参数信息。通过upload(),把我们的apk及需要的参数上传到蒲公英。
有了任务,下面,就是创建插件跟任务绑定。
三、创建我们要上传的插件Plugin
我们实现Plugin,然后,在apply()方法里,监听project.afterEvaluate()回调。
public class TestJavaPlugin implements Plugin<Project> {//project的扩展名字public static final String PLUGIN_EXTENSION_NAME = "uploadHelperJava";public static final String ANDROID_EXTENSION_NAME = "android";@Overridepublic void apply(Project project) {//创建project的扩展Extension customExtension = project.getExtensions().create(PLUGIN_EXTENSION_NAME, Extension.class);//项目编译完成后,回调project.afterEvaluate(new Action<Project>() {@Overridepublic void execute(Project project) {DomainObjectSet<ApplicationVariant> appVariants = ((AppExtension) project.getExtensions().findByName(ANDROID_EXTENSION_NAME)).getApplicationVariants();//这里,可以实现多渠道的打包for (ApplicationVariant variant : appVariants) {//只监听buildType是uploadRelease的包if (variant.getBuildType().getName().equalsIgnoreCase("uploadRelease") ) {String variantName =variant.getName().substring(0, 1).toUpperCase() + variant.getName().substring(1);//创建我们,上传到蒲公英的task任务PGYUploadTask uploadTask = project.getTasks().create("uploadJavaFor" + variantName, PGYUploadTask.class);uploadTask.init(variant, project);//依赖关系 。上传依赖打包,打包依赖clean。variant.getAssembleProvider().get().dependsOn(project.getTasks().findByName("clean"));uploadTask.dependsOn(variant.getAssembleProvider().get());}}}});}
}
这里,我们首先创建了Exension的扩展,然后,判断buildType,是否是我们要上传的type。最后,就是让我们的上传任务依赖打包任务,这样就做到了先打包后上传。
四、项目引用插件
项目下的build.gradle,引入插件
buildscript {repositories {google()jcenter()maven{url uri('./repo/')}}dependencies {classpath 'com.android.tools.build:gradle:3.3.1'classpath 'com.liu.alone.plugin:java-plugin:1.0.0'}
}allprojects {repositories {google()jcenter()}
}task clean(type: Delete) {delete rootProject.buildDir
}
我们把发布的插件,放到了repo目录下,让其引入。
app module使用插件及配置buildType
android{...buildTypes {release {minifyEnabled falsesigningConfig signingConfigs.releaseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}uploadRelease {minifyEnabled falsesigningConfig signingConfigs.releaseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}}
...apply plugin: 'com.liu.alone.plugin'
uploadHelperJava {appName = "testGradle"uKey = "c9d2625c0cf221d8f4a98738f4c05e9a"apiKey = "fac8875534d045a2be3f229abd46cc3e"
}
如果,buildType里面设置了跟构建无关的东西的话。最好,还是添加一个独立的buildType,当然,这个不是必须的。
五、执行
执行,我们插件uploadhelerjava下面的uploadJavaForUploadRelease任务。
执行结果
> Task :app:packageUploadRelease
> Task :app:assembleUploadRelease> Task :app:uploadJavaForUploadRelease
WARNING: API 'variantOutput.getPackageApplication()' is obsolete and has been replaced with 'variant.getPackageApplicationProvider()'.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variantOutput.getPackageApplication(), use -Pandroid.debug.obsoleteApi=true on the command line to display a stack trace.
upload result: {"code":0,"message":"","data":{"appKey":"c5a8638d37251c8410ef476615ae9a8e","userKey":"c9d2625c0cf221d8f4a98738f4c05e9a","appType":"2","appIsLastest":"2","appFileSize":"169960","appName":"ObjectAnimatorTest","appVersion":"1.0","appVersionNo":"1","appBuildVersion":"6","appIdentifier":"com.liu.objectanimatortest","appIcon":"c2e1b68bbeda5d500f3f90fb9213512b","appDescription":"","appUpdateDescription":"","appScreenshots":"","appShortcutUrl":"t6rG","appCreated":"2019-12-28 13:08:14","appUpdated":"2019-12-28 13:08:14","appQRCodeURL":"http:\/\/www.pgyer.com\/app\/qrcodeHistory\/45111fcbd38c3951c823007bbc33a007e1147a6f442e81200235c6899ba4ea87"}}Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/4.10.1/userguide/command_line_interface.html#sec:command_line_warningsBUILD SUCCESSFUL in 28s
可以看到,上传成功后,返回的信息upload result已经显示出来。
六、其他的文件
其他的文件跟Gradle 自定义Plugin插件介绍 中的一样。这里贴下代码。
插件的结构,跟properties内容
插件的build.gradle
这个里面,因为涉及到了联网上传,添加了okhttp。
apply plugin: 'java-library'
apply plugin: 'maven'
dependencies {compile gradleApi()compile localGroovy()compile 'com.android.tools.build:gradle:3.3.1'implementation("com.squareup.okhttp3:okhttp:3.8.1")
}
repositories {mavenCentral()}group = 'com.liu.alone.plugin'
version = '1.0.0'
archivesBaseName = 'java-plugin'
//
//upload
uploadArchives {repositories {mavenDeployer {repository(url: uri('../repo'))}}
}
Gradle 自定义Plugin插件之上传APK到蒲公英相关推荐
- Gradle 自定义Plugin插件之360加固
之前发布的文章:Gradle 自定义Plugin插件之上传APK到蒲公英.让我们知道了自定义插件的一些功能. 一般来说,在发布的时候,我们的APK都需要加固的,毕竟安全点.这里,我们就结合之前的插件, ...
- Gradle 自定义Plugin插件之发送钉钉通知
在之前的文章中,我们介绍了怎么使用Gradle插件,apk加固,上传到蒲公英. 这篇文章,主要就是把流程进一步完善,通过Gradle插件实现:打包-加固-上传蒲公英-发送钉钉消息,实现完全自动化.. ...
- gradle自定义plugin实践之360多渠道加固打包
项目地址 使用AndroidStudio新建一个工程或者新建一个module, 在src/main下新建两个文件夹,groovy.resources, PS:这里的名字其实叫什么都可以,之前的java ...
- Jenkins使用Publish Over FTP Plugin插件上传FTP详解
一.安装插件[Publish Over FTP] 二.在[系统管理]->[系统设置]->[Publish over FTP]->点击[增加]按钮,增加一个要连接的FTP: FTP S ...
- 蒲公英使用一行命令上传Apk文件
在安卓开发中,为了给测试人员提供测试包,我们经历了从U盘拷贝.发邮件或者QQ.微信等通讯工具发送测试Apk文件,不像IOS一样有AppleStore的测试模式.安卓就只能自己来想办法给测试组提供测试包 ...
- Android使用Github Actions持续集成并自动上传apk到蒲公英App内测分发平台(含证书密码脱敏)
目录 1.前言 2.Github Actions持续集成 3.上传apk到蒲公英 4.Gradle配合Github Actions的Secret使用 4.1设置Github Actions Secre ...
- AS 自定义 Gradle plugin 插件 案例 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Gradle入门(五)——Gradle其它模块与Plugin插件详解
Gradle其它模块 一.Settings类 settings.gradle(对应Settings.java)决定哪些工程需要被gradle处理,占用了整个gradle生命周期的三分之一,即Initi ...
- Gradle自定义插件
本教程介绍了创建Gradle独立自定义插件的方法. 它涵盖以下主题 创建任务,并在"自定义"插件中使用它 独立的自定义插件 简短的插件ID 使用settings.gradle自定义 ...
最新文章
- 线程创建后,立刻调用CloseHandle的原因
- Linux中如何安装MySQL详细步骤
- mapreduce分组统计_Mongodb的分组统计MapReduce
- VUE之文字跑马灯效果
- 转:mysql group by 用法解析(详细)
- NYOJ995硬币找零(简单dp)
- groovy 字符串截取最后一个_python数据类型总结——数字和字符串
- tcp、http协议的长连接和短连接
- E-Learning是学习系统而不是教育系统
- catia保存成stp文件时部件丢失_在线教学文件同步神器——坚果云
- 不愧是最好用的 pdf 阅读器~
- IsPostBack深入探讨
- 未来房价涨or跌?大数据告诉你
- 智能营销获客引流-入门-宁波慧客科技有限公司
- 云计算--VMware私有云平台搭建
- 宝塔面板搭建WordPress网站完整教程
- 《学Unity的猫》——第十章:Unity的物理碰撞,流浪喵星计划
- svchost.exe占网速的解决办法
- 0033__PDM,全称为 Persepolis Download Manager
- Win7系统交互式服务检测关闭方法-
热门文章
- CPU Utilization is Wrong
- 【电商】电商系统---供应商管理
- LeetCode Java刷题笔记—297. 二叉树的序列化与反序列化
- java 绘制螺旋线,java-如何创建漩涡/漩涡效果?
- 谷粒商城笔记(13)——商城业务-检索服务
- 信号采样基本概念 —— 5. 加权移动平均滤波(Weighted Moving Average Filtering)
- 计算机软件硬件试讲,2019上半年山东教师资格证高中信息技术面试试讲真题:计算机的软件系统...
- 随机森林,随机森林中进行特征重要性
- 玲珑杯Unity开发心得——开始菜单GUI制作
- SQL游标使用——格式、实例、嵌套