preface
We have learned a lot about Groovy basics, Gradle tasks and projects, and now we can use these basics to customize plug-ins.
I believe many companies have such a plug-in in their projects, which can realize automatic packaging, reinforcement and upload to a platform (generally companies will build their own FTP server) and send relevant links to the nail group messages through the nail robot.
The reinforcement adopted by the author here is 360 reinforcement. The reinforced APK will be uploaded to dandelion, and then relevant information returned after uploading to dandelion will be sent to Dingding. Therefore, there are three steps in total, namely, three tasks will be defined, which are as follows:
- strengthening
- Upload dandelions
- Send to the pin message
Create plug-in Module
- AS version: Arctic fox
- AGP version: 4.2.0
- Development language: Groovy
- The Groovy Version: 3.0.9
BuildSrc = ‘buildSrc’; buildSrc = ‘buildSrc’; buildSrc = ‘buildSrc’;
Keep the.gitignore file in the red box if you need to upload it to a remote repository. Otherwise, when creating a Module, delete all files except the SRC directory and build.gradle. Then create the directory and code as SRC -> main -> groovy -> package name, and delete all the code under build.gradle.
Here I’m going to add all the build.gradle code directly, and the comments will be very detailed:
plugins {
id 'groovy'
id 'maven-publish'
id 'java-gradle-plugin'
}
dependencies {
// Introduce AGP, then use AppExtension
implementation 'com. Android. Tools. Build: gradle: 4.2.0'
// Retrofit is used because network requests are required
implementation 'com. Squareup. Retrofit2: retrofit: 2.9.0'
implementation 'com. Squareup. Retrofit2: converter - gson: 2.9.0'
}
gradlePlugin {
plugins {
standaloneGradlePlugins {
// Configure the plugin ID. The configured ID will generate an xxx.properties file at compile time, which is the plugin ID that you need to import when using the plugin
id = "com.imiyar.upload"
// Configure the plug-in's implementation class
implementationClass = "com.imiyar.upload.UploadApkPlugin"
}
}
}
publishing {
publications {
/ / configure the plug-in id and version number: com. Imiyar. Upload: uploadApk: 1.0.0
// See the official documentation link below for details
maven(MavenPublication) {
groupId = 'com.imiyar.upload'
artifactId = 'uploadApk'
version = '1.0.0'
from components.java // Upload the source jar package}}}Copy the code
This section focuses on the three plugins used in plugins closures, the rest of which are related configuration code
-
Groovy: This is a minor issue, and is intended to support the Groovy language.
-
Maven-publish: Publishes plug-in code to Maven.The official documentation
-
Java-gradle-plugin: Used to assist in the development of Gradle plug-ins. It will automatically apply the Java library plug-in
gradleApi()
Dependencies are added to the configuration and executed during the taskapi
Performs validation of plug-in metadata during.
strengthening
After creating the plug-in Module, we can start writing code by creating a Plugin class that implements the Plugin
UploadApkPlugin
class UploadApkPlugin implements Plugin<Project> {
// AppExtension extension name in AGP
static final String ANDROID_EXTENSION = "android"
// Customize an extension to configure the information required by the custom plug-in
static final String UPLOAD_APK_EXTENSION = "uploadApk"
@Override
void apply(Project project) {
. / / when in build gradle configured in UploadApkExtension attribute, if directly through UploadApkExtension getXxx () is unable to get get value
AfterEvaluate is called. This closure will be called after gradle configuration is complete, i.e. after the build.gradle file has been parsed
project.afterEvaluate {
}
}
}
Copy the code
The apply method is called when the plugin ID is defined in build.gradle, so if we need the extension attribute we need to get it in the project.afterEvaluate closure, otherwise it will be empty.
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.imiyar.upload'
}
uploadApk {
}
Copy the code
For example, when we call id ‘com.imiyar. Upload ‘, we execute the apply method and wait for Gradle configuration to complete before we get the properties we defined in the uploadApk closure (now empty, Because we haven’t started defining our own extensions yet).
Next we customize an extension class:
UploadApkExtension
class UploadApkExtension {
// -------------- Hardening related extensions --------------
String reinforceUserName // 360 Hardened user name
String reinforcePassword // 360 Hardening password
String reinforceFilePath // 360 Hardening jar package path
String outputDirectory // Output apK directory after hardening
boolean isOpenReinforce = true // Whether hardening is required. The default value is true
}
Copy the code
After defining our extension class and the required attributes, we need to create our extension in Plugin and start writing our hardened task-related logic, so we can continue writing the above plug-in class
UploadApkPlugin
class UploadApkPlugin implements Plugin<Project> {.@Override
void apply(Project project) {
// Create the uploadApk extension
project.extensions.create(UPLOAD_APK_EXTENSION, UploadApkExtension.class)
project.afterEvaluate {
// AppExtension is an extension created by the Android plugin, corresponding to the Android {} closure in the App Module
AppExtension androidExtension = project.extensions.findByName(ANDROID_EXTENSION)
// Get variants of the APK package. ApplicationVariants will come with debug and Release variants by default
androidExtension.applicationVariants.all { ApplicationVariant variant ->
if (variant.name.equalsIgnoreCase("release")) {
// Create a Task for hardening
ReinforceTask reinforceTask = project.tasks.create("reinforceRelease", ReinforceTask)
reinforceTask.init(variant)
}
}
}
}
}
Copy the code
Note that there are two variants of APK by default: DEBUG and Release. Of course, you can also create multiple variants by yourself. This is only for the hardening operation of the release package, so when creating the Task, only check whether the variant name is “release”. Next we will write the logic of hardening Task.
Before writing the hardening logic, you can download the compression package of the corresponding platform from 360 hardening, because we need the jiagu.jar package inside. After downloading, we can take a look at the decompression file directory:
Jar and help.txt. You can open help.txt to read the corresponding code later. If I don’t want to open it, I can also put screenshots here:
Note: If you find error messages such as insufficient permissions when using this JAR package later, you can download the old version of 360 hardening to test.
ReinforceTask
class ReinforceTask extends DefaultTask {
@Internal
ApplicationVariant variant // Get the variant of APK
void init(ApplicationVariant variant) {
this.variant = variant
description = "Reinforce Release Apk"
// Define the group to which the task belongs. If you do not define a group, the task will be in the Other group
group = "uploadApk"
}
@TaskAction
void action() {
UploadApkExtension uploadApkExtension = project.extensions.findByName(UploadApkPlugin.UPLOAD_APK_EXTENSION)
// Get the signature information of the variant for later re-signing
SigningConfig signingConfig = variant.signingConfig
String apkFilePath
variant.outputs.all { BaseVariantOutput output ->
Outputs apK -> outputs APk -> outputs apK -> release
apkFilePath = output.outputFile.absolutePath
}
// Invoke the cli tool to perform 360 hardening login
project.exec { ExecSpec spec ->
spec.commandLine(
"java"."-jar", uploadApkExtension.reinforceFilePath,
"-login", uploadApkExtension.reinforceUserName, uploadApkExtension.reinforcePassword)
}
// Invoke the cli tool to obtain the signature information in 360 hardening
if (signingConfig) {
project.exec { ExecSpec spec ->
spec.commandLine("java"."-jar", uploadApkExtension.reinforceFilePath,
"-importsign", signingConfig.storeFile.absolutePath, signingConfig.storePassword,
signingConfig.keyAlias, signingConfig.keyPassword)
}
}
// Use the cli tool to perform 360 Hardening
project.exec { ExecSpec spec ->
spec.commandLine("java"."-jar", uploadApkExtension.reinforceFilePath,
"-jiagu", apkFilePath, uploadApkExtension.outputDirectory, "-autosign")}}}Copy the code
Creating a Task first inherits from DefaultTask, and the @TaskAction annotation is used here to indicate that the method is the entry point for executing the Task, and that the logic will be executed when the Task is double-clicked.
The relevant codes for calling the command line in the following are compiled according to the help document in help.txt just mentioned. The only thing to note here is that 360 hardening requires you to get your signature information first, and then re-sign after hardening, so it must be inThe build of the app. Gradle
Fill in the relevant ones belowsigningConfigs
Otherwise, the hardened file will be an unsigned APK file.
Now that the ReinforceTask is done, let’s fix the code for UploadApkPlugin:
class UploadApkPlugin implements Plugin<Project> {.@Override
void apply(Project project) {
...
project.afterEvaluate {
...
androidExtension.applicationVariants.all { ApplicationVariant variant ->
if (variant.name.equalsIgnoreCase("release")) {
// Define a Task for hardening
ReinforceTask reinforceTask = project.tasks.create("reinforceRelease", ReinforceTask)
reinforceTask.init(variant)
// Modify task dependencies
variant.getAssembleProvider().get().dependsOn(project.getTasks().findByName("clean"))
reinforceTask.dependsOn(variant.getAssembleProvider().get())
}
}
}
}
}
Copy the code
An assembleRelease must be mandatory or mandatory. An assembleRelease must be mandatory or mandatory. So finally we just need to hit the reinforceTask and do the packing and reinforcement.
Next we can open Gradle in the upper right corner of the AS and see the following directory:
Click on publishToMavenLocal to publish the plugin to the local Maven repository. If you open the local Maven repository, you can see the newly published plugin.
- For Mac: The default path to the local Maven repository is
M2 / repository/package name
- For Windows: The default path to the local Maven repository is
C: / / UsersAdministrator/m2 / epository/package name
To configure our plugin, open build.gradle in app Module and add the following script:
plugins {
id 'com.android.application'
id 'kotlin-android'
// The plug-in ID just defined
id 'com.imiyar.upload'
}
uploadApk {
// 360 is related to hardening
reinforceUserName "360 hardened account"
reinforcePassword "360 Hardened password"
reinforceFilePath "The absolute path to the 360 hardened JAR package just downloaded"
// Directory output after hardening
outputDirectory "/Users/sherry/ASProjects/UploadApkPlugin/app/build/outputs/apk/release/"
// Whether to enable hardening
isOpenReinforce true
}
// Then add signature-related information to the Android closure
android {
signingConfigs {
release {
storeFile file('.. /upload.keystore')
storePassword '123456'
keyAlias 'upload'
keyPassword '123456'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}}Copy the code
Finally, we need to configure the plugin in the root directory of the project and add the mavenLocal() plugin to load the local Maven repository:
buildscript {
repositories {
...
mavenLocal()
}
dependencies {
...
classpath "Com. Imiyar. Upload: uploadApk: 1.0.0"
}
}
allprojects {
repositories {
...
mavenLocal()
}
}
Copy the code
After adding this information, we can click Sync Now and see the Task we just defined in Gradle to the right of AS
Double-click the reinforceRelease, you can do the packing and reinforcement. Here are some information printed during the reinforcement. If the reinforcement fails, it will also print an error message.
Let’s take a look at the reinforced APK:
You can also try to see if the installation is successful or decompile to see if it is truly hardened. I have tested these and now we are done
Upload dandelions
After the reinforcement, we need to upload it to the distribution platform, whether it is your own or a third party’s. Only after uploading it to the distribution platform can we get the link of apK for others to download and install. Here we use dandelion.
So how do you upload a packed APK to a dandelion? Dandelion document portal
UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension
UploadApkExtension
class UploadApkExtension {.// ------------ Upload dandelion related extensions ------------
String apiKey // API Key
String appName // Application name
}
Copy the code
Create a Task that implements the logic of uploading dandelions. This Task is named PgyUploadTask.
class PgyUploadTask extends DefaultTask {
@Internal
ApplicationVariant variant
void init(ApplicationVariant variant) {
this.variant = variant
description = "Upload apk to Pgyer"
group = "uploadApk"
}
@TaskAction
void action() {
// Get our custom extension
UploadApkExtension uploadApkExtension = project.extensions.findByName(UploadApkPlugin.UPLOAD_APK_EXTENSION)
// Get the Android extension AppExtension
AppExtension appExtension = project.extensions.findByName(UploadApkPlugin.ANDROID_EXTENSION)
// This is just normal printing, nothing special, just convenient to see related information when executing task
println("# # # # # # # # # # # # # # # # # # # # # # # # # # # # to upload the dandelion # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
println("# applicationId : " + variant.getApplicationId())
println("# versionName : " + appExtension.defaultConfig.versionName)
println("# versionCode : " + appExtension.defaultConfig.versionCode)
println("# appName : " + uploadApkExtension.appName)
println("# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #")
File outputFile
// Get the output directory defined when hardening
File directory = new File(uploadApkExtension.outputDirectory)
// Check if it is a directory. If so, traverse the files in the directory and get the hardened APK
if (directory.isDirectory()) {
File[] files = directory.listFiles()
for (File file : files) {
// If hardening is enabled, check whether the APK file in the output path is the hardened APK file
// Since we do not know the name rules generated by 360 after the reinforcement, we can distinguish them by matching "jiagu" and ".apk"
if (uploadApkExtension.isOpenReinforce) {
if (file.getName().contains("jiagu") && file.getName().endsWith(".apk")) {
outputFile = file
break}}else {
// If hardening is not enabled, there will be only one. Apk file in this directory
if (file.getName().endsWith(".apk")) {
outputFile = file
break
}
}
}
}
}
}
Copy the code
Here we also create a Task that inherits from DefaultTask and start defining our upload logic. AssembleRelease contains only the apK files in the output directory, so you don’t have to worry about contains matching files that are incorrect.
Next we need to use the network request, the author for convenience, just a simple Java language encapsulation, do not consider any performance issues, directly related to the code posted and do not explain, I believe that the network request Retrofit part of the world is already familiar.
ApiFactory
public class ApiFactory {
private static volatile ApiFactory mInstance;
private ApiFactory(a) {}public static ApiFactory getInstance(a) {
if (mInstance == null) {
synchronized (ApiFactory.class) {
if (mInstance == null) {
mInstance = newApiFactory(); }}}return mInstance;
}
public <T> T create(String baseUrl, Class<T> clazz) {
return new Retrofit.Builder()
.baseUrl(baseUrl)
.client(newClient())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(clazz);
}
private OkHttpClient newClient(a) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS);
return builder.build();
}
public MultipartBody.Part getFilePart(String mediaType, File file) {
return MultipartBody.Part.createFormData("file", file.getAbsoluteFile().getName(),
RequestBody.create(MediaType.parse(mediaType), file));
}
public RequestBody getTextBody(String text) {
return RequestBody.create(MediaType.parse("text/plain"), text); }}Copy the code
ApiConstants
public interface ApiConstants {
String PGY_BASE_URL = "https://www.pgyer.com/apiv2/";
}
Copy the code
PgyUploadService
public interface PgyUploadService {
@Multipart
@POST("app/upload")
Call<ResponseBody> uploadFile(@Part("_api_key") RequestBody key,
@Part("buildName") RequestBody buildName,
@Part MultipartBody.Part file);
}
Copy the code
Now that we have simply wrapped the Retrofit-related code and the interface that needs to be called, we are ready to perform the actual upload operation, and we will now add the upload code to the PgyUploadTask above:
PgyUploadTask
class PgyUploadTask extends DefaultTask {
@TaskAction
void action() {
...
// Add the following code at the end
if(outputFile ! =null) {
// This part needs no further explanation
PgyUploadService pgyService = ApiFactory.getInstance().create(ApiConstants.PGY_BASE_URL, PgyUploadService.class)
// Upload the file
Response<ResponseBody> appResponse = pgyService.uploadFile(
ApiFactory.getInstance().getTextBody(uploadApkExtension.apiKey),
ApiFactory.getInstance().getTextBody(uploadApkExtension.appName),
ApiFactory.getInstance().getFilePart("application/vnd.android.package-archive", outputFile)
).execute()
// Prints the result returned after upload
println("\nappResponse: ${appResponse.body().string()}")}else {
println("Could not found the apk file")}}}Copy the code
The parameters that need to be passed in here are explained in the document above. If you don’t understand the function of parameters, you can refer to the document of dandelion
After defining the Task we need to go back to UploadApkPlugin and create our Task:
class UploadApkPlugin implements Plugin<Project> {.@Override
void apply(Project project) {
...
project.afterEvaluate {
...
androidExtension.applicationVariants.all { ApplicationVariant variant ->
if (variant.name.equalsIgnoreCase("release")) {
// Define a Task for hardening
ReinforceTask reinforceTask = project.tasks.create("reinforceRelease", ReinforceTask)
reinforceTask.init(variant)
// Define a Task for uploading APK to dandelion
PgyUploadTask pgyUploadTask = project.tasks.create("pgyUploadRelease", PgyUploadTask)
pgyUploadTask.init(variant)
// Modify task dependencies
variant.getAssembleProvider().get().dependsOn(project.getTasks().findByName("clean"))
reinforceTask.dependsOn(variant.getAssembleProvider().get())
Make the task depend on the reinforceTask
pgyUploadTask.dependsOn(reinforceTask)
}
}
}
}
}
Copy the code
It should be mentioned here because we don’t want to reinforce every package, so if we don’t need to reinforce, we can set isOpenReinforce in UploadApkExtension to false and add it from the dependencies above.
Next we just need to modify our app build.gradle and add the extension we just set up
build.gradle
uploadApk {
// 360 is related to hardening
reinforceUserName "360 hardened account"
reinforcePassword "360 Hardened password"
reinforceFilePath "The absolute path to the 360 hardened JAR package just downloaded"
// Directory output after hardening
outputDirectory "/Users/sherry/ASProjects/UploadApkPlugin/app/build/outputs/apk/release/"
// Whether to enable hardening
isOpenReinforce true
// Upload dandelion
apiKey "If there is no apiKey, you need to apply on the official document given above."
appName "UploadApkPlugin"
}
Copy the code
Click on publishToMavenLocal to publish the plugin id to the local Maven repository and Sync Now. This is the only way to keep the plug-in code in the Maven repository up to date.
Now let’s do pgyUploadRelease, because we’re defining pgyUploadRelease dependsOn reinforceRelease So we will do the reinforceRelease first when we do the pgyUploadRelease, so don’t worry about not doing the reinforcement.
Take a look at the relevant log printed after uploading to dandelion, we will return the file link of APK after uploading successfully, because the printed log is too long, the screenshot cannot be taken later, you can look at the document, and put the document portal again here
Send to the pin message
When upload the dandelion we must hope to share out to let everyone download, so here we use nailing for sharing, this advantage when we pack in the implementation of the time we also don’t need to always staring at the packaging progress, because when finished packing after upload messages will be automatically sent to the nailing group, So we know that we’re done packing.
First, we need to look at the document portal that connects to the nail. According to the document, we need to first build a group in the nail, and then customize a robot, and then call the interface and pass the parameter according to the document.
It is important to note that in the security Settings section, if you select “checkmark”, you will have to read another document when accessing the interface.Secure the portal, the security Settings used by the author are user-defined keywords, which means that only the parameters you send contain this keyword can be sent successfully.
UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension UploadApkExtension
class UploadApkExtension {
// ----------- Send pin messages related extensions -----------
String webHook // pin the WebHook address of the robot
}
Copy the code
Here, it’s easy to just add webhooks, and if you check in your security Settings, you’ll need to add Secret. With the extension defined, we can start defining our Task that sends a pin message, named SendMsgToDingTalkTask:
class SendMsgToDingTalkTask extends DefaultTask {
@Internal
ApplicationVariant variant
// Need to send a short link to pin for everyone to open, need to be concatenated with "http://www.pgyer.com/"
static String mShortCutUrl
// Need to send to Nail nail for everyone to scan the download of the TWO-DIMENSIONAL code picture link
static String mQRCodeURL
void init(ApplicationVariant variant) {
this.variant = variant
description = "Send message to DingTalk"
group = "uploadApk"
}
// Upload the short link returned after successful upload to dandelion and download the QR code link
static void setUrl(String shortCutUrl, String qrUrl) {
mShortCutUrl = shortCutUrl
mQRCodeURL = qrUrl
}
@TaskAction
void action() {
UploadApkExtension uploadApkExtension = project.extensions.findByName(UploadApkPlugin.UPLOAD_APK_EXTENSION)
AppExtension appExtension = project.extensions.findByName(UploadApkPlugin.ANDROID_EXTENSION)
// If you don't understand the meaning of these parameters, you can look at the following parameters
Link link = new Link()
link.picUrl = mQRCodeURL
link.messageUrl = "http://www.pgyer.com/" + mShortCutUrl
link.title = uploadApkExtension.appName + "Official edition"
link.text = Version of the "${appExtension. DefaultConfig. VersionName}"
DingTalkRequest request = new DingTalkRequest(link, "link")
// Just like apK uploading to dandelion, we need to define an interface before performing network operations
The SendDingTalkService code is shown below
SendDingTalkService dingTalkService = ApiFactory.getInstance().create(ApiConstants.DING_TALK_BASE_URL, SendDingTalkService.class)
Response<ResponseBody> appResponse = dingTalkService.sendMsgToDingTalk(uploadApkExtension.webHook, request)
.execute()
// Print here to see the result
println("\nDingTalkMsgResponse:" + new Gson().toJson(appResponse.body().string()))
}
// Define the parameters that need to be passed to send the pin message
static class DingTalkRequest {
String msgtype
Link link
DingTalkRequest(Link link, String msgtype) {
this.link = link
this.msgtype = msgtype
}
}
static class Link {
String picUrl
String messageUrl
String title
String text
}
}
Copy the code
Just like the task created before, we need to get the extension we defined and the Android extension in AGP first. Here we pass the Link type. For details, you can see the Link type in the above document, which has the corresponding parameter description. Take a screenshot of the parameter description:
Let’s define the interface we use, as follows:
ApiConstants
public interface ApiConstants {
String DING_TALK_BASE_URL = "https://oapi.dingtalk.com/";
}
Copy the code
SendDingTalkService
public interface SendDingTalkService {
@POST("robot/send")
Call<ResponseBody> sendMsgToDingTalk(
@Query("access_token") String accessToken,
@Body SendMsgToDingTalkTask.DingTalkRequest request
);
}
Copy the code
We have finished the code of sending the pins. Now we need to modify the code of PgyUploadTask. After all, we need to send the short link and the TWO-DIMENSIONAL code link.
PgyUploadTask
class PgyUploadTask extends DefaultTask {
@TaskAction
void action() {
// Now we can modify this part of the code, you can compare the modification
if(outputFile ! =null) {
PgyUploadService pgyService = ApiFactory.getInstance().create(ApiConstants.PGY_BASE_URL, PgyUploadService.class)
Response<ResponseBody> appResponse = pgyService.uploadFile(ApiFactory.getInstance().getTextBody(uploadApkExtension.apiKey), ApiFactory.getInstance().getTextBody(uploadApkExtension.appName),
ApiFactory.getInstance().getFilePart("application/vnd.android.package-archive", outputFile))
.execute()
// The following is the code that needs to be modified
String result = appResponse.body().string()
// Use Gson to convert the returned data into the desired object
PgyResponse response = new Gson().fromJson(result, PgyResponse.class)
if(response ! =null) {
// Pass the relevant information to SendMsgToDingTalkTask
SendMsgToDingTalkTask.setUrl(response.data.buildShortcutUrl, response.data.buildQRCodeURL)
}
} else {
println("Could not found the apk file")}}// Add the object definition to the end of PgyUploadTask
// This object corresponds to the data returned after successfully uploading the dandelion
static class PgyResponse {
public int code
public String message
public PgyDetail data
// It returns a lot of data, which is not needed in this article
static class PgyDetail {
public String buildShortcutUrl
public String buildQRCodeURL
public String buildIcon
}
}
}
Copy the code
After modifying PgyUploadTask, we also need to modify our UploadApkPlugin, after all, we haven’t created the task yet, just add a few lines of code
class UploadApkPlugin implements Plugin<Project> {.@Override
void apply(Project project) {
...
project.afterEvaluate {
...
androidExtension.applicationVariants.all { ApplicationVariant variant ->
if (variant.name.equalsIgnoreCase("release")) {
// Define a Task for hardening
ReinforceTask reinforceTask = project.tasks.create("reinforceRelease", ReinforceTask)
reinforceTask.init(variant)
// Define a Task for uploading APK to dandelion
PgyUploadTask pgyUploadTask = project.tasks.create("pgyUploadRelease", PgyUploadTask)
pgyUploadTask.init(variant)
// Define the task that sends the pin message
SendMsgToDingTalkTask dingTalkTask = project.tasks.create("sendMsgRelease", SendMsgToDingTalkTask)
dingTalkTask.init()
// Modify task dependencies
variant.getAssembleProvider().get().dependsOn(project.getTasks().findByName("clean"))
reinforceTask.dependsOn(variant.getAssembleProvider().get())
pgyUploadTask.dependsOn(reinforceTask)
// Depends on pgyUploadTask
dingTalkTask.dependsOn(pgyUploadTask)
}
}
}
}
}
Copy the code
We need to add the extension webHook~ we just defined
build.gradle
uploadApk {
...
// Pin the robot
webHook "Go to the robot management page you just created and you can see this webHook."
}
Copy the code
Okay, remember what we were talking about? Comment out the related plugin id and extension code before releasing the plugin. Instead of repeating this step, let’s look at the result of executing the task:
Click sengMsgRelease:
Take a look at the print:
Messages received from Nail:
Click on this message to go to the download link for dandelion
All right, let’s finish
Finally, post the Github address for all the code in this article