├── app
├── .gitignore
├── src
│ └── main
│ │ ├── resources
│ │ └── META-INF
│ │ │ └── gradle-plugins
│ │ │ └── center.uploadpgy.plugin.properties
│ │ └── java
│ │ └── net
│ │ └── center
│ │ └── upload_plugin
│ │ ├── PluginUtils.java
│ │ ├── helper
│ │ ├── HttpHelper.java
│ │ ├── CmdHelper2.kt
│ │ ├── CmdHelper.java
│ │ └── SendMsgHelper.java
│ │ ├── params
│ │ ├── GitLogParams.java
│ │ ├── SendWeixinGroupParams.java
│ │ ├── SendFeishuParams.java
│ │ ├── UploadFirImParams.java
│ │ ├── SendDingParams.java
│ │ └── UploadPgyParams.java
│ │ ├── model
│ │ ├── feishu
│ │ │ ├── TextDTO.java
│ │ │ ├── ElementsDTO.java
│ │ │ └── FeiShuRequestBean.java
│ │ ├── BasePgyResult.java
│ │ ├── PgyCOSTokenResult.java
│ │ ├── WXGroupRequestBean.java
│ │ ├── PgyUploadResult.java
│ │ └── DingDingRequestBean.java
│ │ ├── PluginConstants.java
│ │ ├── task
│ │ ├── BuildAndUploadTask.java
│ │ ├── OnlyUploadTask.java
│ │ └── BaseTask.java
│ │ └── UploadApkPlugin.java
├── proguard-rules.pro
└── build.gradle
├── .idea
├── .gitignore
├── compiler.xml
├── vcs.xml
├── misc.xml
├── gradle.xml
└── jarRepositories.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── config.gradle
├── .gitignore
├── settings.gradle
├── gradle.properties
├── gradlew.bat
├── gradlew
└── README.md
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/centerzx/UploadApkPlugin/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/resources/META-INF/gradle-plugins/center.uploadpgy.plugin.properties:
--------------------------------------------------------------------------------
1 | implementation-class=net.center.upload_plugin.UploadApkPlugin
--------------------------------------------------------------------------------
/config.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 | dependenceVersion = [
3 | okhttpVersion : "3.12.12",
4 | GsonVersion : "2.8.8",
5 | ]
6 | }
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Sep 29 01:26:13 CST 2021
2 | distributionBase=GRADLE_USER_HOME
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 | .idea/inspectionProfiles/Project_Default.xml
17 | .idea/
18 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | //dependencyResolutionManagement {
2 | // repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
3 | // repositories {
4 | // google()
5 | // mavenCentral()
6 | // jcenter() // Warning: this repository is going to shut down soon
7 | // }
8 | //}
9 | //rootProject.name = "UploadApkPlugin"
10 | include ':app'
11 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/PluginUtils.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin;
2 |
3 | /**
4 | * Created by Android-ZX
5 | * 2021/9/3.
6 | */
7 | public class PluginUtils {
8 |
9 | public static boolean isEmpty(CharSequence s) {
10 | if (s == null) {
11 | return true;
12 | } else {
13 | return s.length() == 0;
14 | }
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/helper/HttpHelper.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.helper;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | import okhttp3.OkHttpClient;
6 |
7 | public class HttpHelper {
8 |
9 |
10 | public static OkHttpClient getOkHttpClient() {
11 | return new OkHttpClient.Builder()
12 | .readTimeout(60, TimeUnit.SECONDS)
13 | .connectTimeout(60, TimeUnit.SECONDS)
14 | .writeTimeout(60, TimeUnit.SECONDS).build();
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/GitLogParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * 设置获取Git日志的参数
7 | */
8 | public class GitLogParams {
9 |
10 | /**
11 | * 获取以当前时间为准的,多少天之前的Git记录,默认-1为全部,会结合数量进行获取
12 | */
13 | public int gitLogHistoryDayTime = -1;
14 |
15 | /**
16 | * Git记录的最大数量
17 | */
18 | public int gitLogMaxCount = 10;
19 |
20 | public static GitLogParams getGitParamsConfig(Project project) {
21 | GitLogParams extension = project.getExtensions().findByType(GitLogParams.class);
22 | return extension;
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/feishu/TextDTO.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model.feishu;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by center
7 | * Time:2022-09-02.
8 | * Desc:
9 | */
10 | public class TextDTO {
11 |
12 | @SerializedName("content")
13 | private String content;
14 | @SerializedName("tag")
15 | private String tag;
16 |
17 | public String getContent() {
18 | return content;
19 | }
20 |
21 | public void setContent(String content) {
22 | this.content = content;
23 | }
24 |
25 | public String getTag() {
26 | return tag;
27 | }
28 |
29 | public void setTag(String tag) {
30 | this.tag = tag;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/BasePgyResult.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by center
7 | * Time:2022-08-20.
8 | * Desc:
9 | */
10 | public class BasePgyResult {
11 |
12 | @SerializedName("code")
13 | private Integer code;
14 | @SerializedName("message")
15 | private String message;
16 |
17 |
18 | public Integer getCode() {
19 | return code;
20 | }
21 |
22 | public void setCode(Integer code) {
23 | this.code = code;
24 | }
25 |
26 | public String getMessage() {
27 | return message;
28 | }
29 |
30 | public void setMessage(String message) {
31 | this.message = message;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/PluginConstants.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin;
2 |
3 | /**
4 | * Created by Android-ZX
5 | * 2021/9/3.
6 | */
7 | public class PluginConstants {
8 |
9 | public static final String TASK_GROUP_NAME="publishToThirdPlatform";
10 | public static final String TASK_DES="tools of upload to third platform";
11 |
12 | public static final String UPLOAD_PARAMS_NAME = "uploadPgyParams";
13 | public static final String DING_PARAMS_NAME = "buildDingParams";
14 | public static final String FEISHU_PARAMS_NAME = "buildFeiShuParams";
15 | public static final String WEIXIN_GROUP_PARAMS_NAME = "buildWeixinGroupParams";
16 | public static final String GIT_LOG_PARAMS_NAME = "buildGitLogParams";
17 |
18 | public static final String ANDROID_EXTENSION_NAME = "android";
19 | public static final String TASK_EXTENSION_NAME = "ApkBuildUploadPlatform";
20 | public static final String TASK_EXTENSION_NAME_ONLY_UPLOAD = "OnlyUploadApkToPlatform";
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | //支持java语言
2 | apply plugin: 'java-library'
3 | //groovy语言
4 | //apply plugin: 'groovy'
5 | //kotlin语言
6 | //apply plugin: 'kotlin'
7 |
8 | //使用maven
9 | //apply plugin: 'maven'
10 |
11 | //先上传到github,再https://jitpack.io/
12 | apply plugin: 'com.github.dcendents.android-maven'
13 |
14 |
15 | apply from: "../config.gradle"
16 |
17 | dependencies {
18 | // gradle sdk
19 | implementation gradleApi()
20 | // groovy sdk
21 | implementation localGroovy()
22 | implementation "com.android.tools.build:gradle:$build_gradle_version"
23 |
24 | implementation "com.google.code.gson:gson:${dependenceVersion.GsonVersion}"
25 | implementation "com.squareup.okhttp3:okhttp:${dependenceVersion.okhttpVersion}"
26 | }
27 |
28 | //repositories {
29 | // mavenCentral()
30 | //}
31 |
32 |
33 | //uploadArchives {
34 | // repositories.mavenDeployer {
35 | // repository(url: uri('../publishPluginRepo'))
36 | // pom.groupId = "net.center.upload.plugin"
37 | // pom.artifactId = "pgy-plugin"
38 | // pom.version = "1.0.0"
39 | //// pom.packaging = "aar"
40 | // }
41 | //}
42 |
43 | java {
44 | sourceCompatibility = JavaVersion.VERSION_1_8
45 | targetCompatibility = JavaVersion.VERSION_1_8
46 | }
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/SendWeixinGroupParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * Created by Android-ZX
7 | *
8 | * 发送到企业微信群的消息参数
9 | */
10 | public class SendWeixinGroupParams {
11 |
12 | public String webHookUrl;
13 | public String msgtype = "markdown";
14 | /**
15 | * 如果使用文本可添加参数是否@全体群人员,默认true:isAtAll = true。其他类型不支持
16 | */
17 | public boolean isAtAll = true;
18 | public String contentTitle;
19 | public String contentText;
20 | /**
21 | * 是否支持发送git记录
22 | */
23 | public boolean isSupportGitLog = true;
24 |
25 | public SendWeixinGroupParams() {
26 |
27 | }
28 |
29 | public SendWeixinGroupParams(String webHookUrl, String msgtype, boolean isAtAll, String contentTitle, String contentText) {
30 | this.webHookUrl = webHookUrl;
31 | this.msgtype = msgtype;
32 | this.isAtAll = isAtAll;
33 | this.contentText = contentText;
34 | this.contentTitle = contentTitle;
35 | }
36 |
37 | public static SendWeixinGroupParams getWeixinGroupConfig(Project project) {
38 | SendWeixinGroupParams extension = project.getExtensions().findByType(SendWeixinGroupParams.class);
39 | if (extension == null) {
40 | extension = new SendWeixinGroupParams();
41 | }
42 | return extension;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/SendFeishuParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * Created by Android-ZX
7 | * 2021/9/3.
8 | *
9 | * 发送到飞书的消息参数
10 | */
11 | public class SendFeishuParams {
12 |
13 | public String webHookHostUrl;
14 | public String contentTitle;
15 | public String contentText;
16 | public String msgtype = "post";
17 | public boolean isAtAll = false;
18 | public String clickTxt = "点我进行下载";
19 | /**
20 | * 是否支持发送git记录
21 | */
22 | public boolean isSupportGitLog = true;
23 |
24 | public SendFeishuParams() {
25 |
26 | }
27 |
28 | public SendFeishuParams(String webHookHostUrl, String contentTitle, String contentText, String msgtype, boolean isAtAll, String clickTxt) {
29 | this.webHookHostUrl = webHookHostUrl;
30 | this.contentText = contentText;
31 | this.contentTitle = contentTitle;
32 | this.msgtype = msgtype;
33 | this.isAtAll = isAtAll;
34 | this.clickTxt = clickTxt;
35 | }
36 |
37 | public static SendFeishuParams getFeishuParamsConfig(Project project) {
38 | SendFeishuParams extension = project.getExtensions().findByType(SendFeishuParams.class);
39 | if (extension == null) {
40 | extension = new SendFeishuParams();
41 | }
42 | return extension;
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/UploadFirImParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * Created by Android-ZX
7 | *
8 | * fir.im上传参数设置
9 | */
10 | public class UploadFirImParams {
11 |
12 | //App 的 bundleId(发布新应用时必填)
13 | public String bundleId;
14 | //长度为 32, 用户在 fir 的 api_token
15 | public String apiToken;
16 | //应用名称(上传 ICON 时不需要)
17 | public String appName;
18 | //版本号(上传 ICON 时不需要)
19 | public String appVersion;
20 | //Build 号(上传 ICON 时不需要)
21 | public String buildCode;
22 | //更新日志(上传 ICON 时不需要)
23 | public String changelogText;
24 |
25 | public UploadFirImParams() {
26 |
27 | }
28 |
29 | public UploadFirImParams(String bundleId, String apiToken, String appName, String appVersion, String buildCode, String changelogText) {
30 | this.bundleId = bundleId;
31 | this.apiToken = apiToken;
32 | this.appName = appName;
33 | this.appVersion = appVersion;
34 | this.buildCode = buildCode;
35 | this.changelogText = changelogText;
36 | }
37 |
38 | public static UploadFirImParams getConfig(Project project) {
39 | UploadFirImParams extension = project.getExtensions().findByType(UploadFirImParams.class);
40 | if (extension == null) {
41 | extension = new UploadFirImParams();
42 | }
43 | return extension;
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/feishu/ElementsDTO.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model.feishu;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by center
9 | * Time:2022-09-03.
10 | * Desc:
11 | */
12 | public class ElementsDTO {
13 |
14 | @SerializedName("tag")
15 | private String tag;
16 | @SerializedName("text")
17 | private TextDTO text;
18 | @SerializedName("type")
19 | private String type;
20 | @SerializedName("url")
21 | private String url;
22 | @SerializedName("actions")
23 | private List actions;
24 |
25 | public String getTag() {
26 | return tag;
27 | }
28 |
29 | public void setTag(String tag) {
30 | this.tag = tag;
31 | }
32 |
33 | public TextDTO getText() {
34 | return text;
35 | }
36 |
37 | public void setText(TextDTO text) {
38 | this.text = text;
39 | }
40 |
41 | public String getType() {
42 | return type;
43 | }
44 |
45 | public void setType(String type) {
46 | this.type = type;
47 | }
48 |
49 | public String getUrl() {
50 | return url;
51 | }
52 |
53 | public void setUrl(String url) {
54 | this.url = url;
55 | }
56 |
57 | public List getActions() {
58 | return actions;
59 | }
60 |
61 | public void setActions(List actions) {
62 | this.actions = actions;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/SendDingParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * Created by Android-ZX
7 | * 2021/9/3.
8 | *
9 | * 发送到钉钉的消息参数
10 | */
11 | public class SendDingParams {
12 |
13 | public String accessToken;
14 | public String contentText;
15 | public String contentTitle;
16 | public String msgtype = "link";
17 | public boolean isAtAll = false;
18 | public String clickTxt = "点我进行下载";
19 | /**
20 | * 是否支持发送git记录
21 | */
22 | public boolean isSupportGitLog = true;
23 |
24 | public SendDingParams() {
25 |
26 | }
27 |
28 | public SendDingParams(String accessToken) {
29 | this(accessToken, "", "测试包版本:");
30 | }
31 |
32 | public SendDingParams(String accessToken, String contentText, String contentTitle) {
33 | this(accessToken, contentText, contentTitle, "link", false);
34 | }
35 |
36 | public SendDingParams(String accessToken, String contentText, String contentTitle, String msgtype, boolean isAtAll) {
37 | this.accessToken = accessToken;
38 | this.contentText = contentText;
39 | this.contentTitle = contentTitle;
40 | this.msgtype = msgtype;
41 | this.isAtAll = isAtAll;
42 | }
43 |
44 | public static SendDingParams getDingParamsConfig(Project project) {
45 | SendDingParams extension = project.getExtensions().findByType(SendDingParams.class);
46 | if (extension == null) {
47 | extension = new SendDingParams();
48 | }
49 | return extension;
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/helper/CmdHelper2.kt:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.helper
2 |
3 | import java.io.BufferedReader
4 | import java.io.InputStreamReader
5 | import java.nio.charset.StandardCharsets
6 |
7 | /**
8 | * Created by 钟新
9 | * Time:2022/9/1.
10 | * Desc:
11 | */
12 | object CmdHelper2 {
13 | private const val LOG_MAX_COUNT = 50
14 | private const val LOG_MIN_COUNT = 10
15 | private const val GIT_LOG_BASIC_CMD = "git log --oneline --pretty=format:\"%an:%s\" --no-merges"
16 | const val gitLogCmd = GIT_LOG_BASIC_CMD + " --since=\"2022-8-30\" --until=\"2022-10-1\""
17 |
18 | /**
19 | * %ai 是时间,格式:2022-08-31 23:18:48 +0800
20 | */
21 | const val gitLogCmd2 = "git log --oneline --pretty=format:\"%ai,%an:%s\" --no-merges --since=2days"
22 | const val gitLogCmd3 = GIT_LOG_BASIC_CMD + " --max-count=10"
23 | fun getGitLogByTimeAndCount(logDayTime: Int, logMaxCount: Int): String {
24 | var logMaxCount = logMaxCount
25 | val logBuilder = StringBuilder(GIT_LOG_BASIC_CMD)
26 | if (logDayTime >= 1) {
27 | logBuilder.append(" --since=").append(logDayTime).append("days")
28 | logMaxCount = LOG_MAX_COUNT
29 | } else {
30 | if (logMaxCount <= 0) {
31 | logMaxCount = LOG_MIN_COUNT
32 | } else if (logMaxCount > LOG_MAX_COUNT) {
33 | logMaxCount = LOG_MAX_COUNT
34 | }
35 | }
36 | logBuilder.append(" --max-count=").append(logMaxCount)
37 | return exeCmd(logBuilder.toString())
38 | }
39 |
40 | @JvmStatic
41 | fun main(args: Array) {
42 | exeCmd(gitLogCmd)
43 | }
44 |
45 | fun exeCmd(commandStr: String?): String {
46 | val p = Runtime.getRuntime().exec(commandStr)
47 | val ret = BufferedReader(InputStreamReader(p.inputStream, StandardCharsets.UTF_8)).useLines { it.mapIndexed { i, s -> "$i. $s" }.joinToString("\n") }
48 | println("ExeCmd result:\n$ret")
49 | return ret
50 | }
51 | }
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/task/BuildAndUploadTask.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.task;
2 |
3 |
4 | import com.android.build.gradle.api.BaseVariantOutput;
5 |
6 | import net.center.upload_plugin.params.UploadPgyParams;
7 |
8 | import org.gradle.api.GradleException;
9 | import org.gradle.api.tasks.TaskAction;
10 |
11 | import java.io.File;
12 | import java.util.Objects;
13 |
14 | /**
15 | * Created by Android-ZX
16 | * 2021/9/3.
17 | */
18 | public class BuildAndUploadTask extends BaseTask {
19 |
20 | @TaskAction
21 | public void uploadToPGY() {
22 | for (BaseVariantOutput output : mVariant.getOutputs()) {
23 | File apkDir = output.getOutputFile();
24 | if (apkDir == null || !apkDir.exists()) {
25 | throw new GradleException("The compiled APK file to upload does not exist!");
26 | }
27 | System.out.println("ApkDir path: " + apkDir.getAbsolutePath());
28 | File apk = null;
29 | if (apkDir.getName().endsWith(".apk")) {
30 | apk = apkDir;
31 | } else {
32 | if (apkDir.listFiles() != null) {
33 | for (int i = Objects.requireNonNull(apkDir.listFiles()).length - 1; i >= 0; i--) {
34 | File apkFile = Objects.requireNonNull(apkDir.listFiles())[i];
35 | if (apkFile != null && apkFile.exists() && apkFile.getName().endsWith(".apk")) {
36 | apk = apkFile;
37 | break;
38 | }
39 | }
40 | }
41 | }
42 | if (apk == null || !apk.exists()) {
43 | throw new GradleException("The compiled APK file to upload does not exist!");
44 | }
45 | System.out.println("Final upload apk path: " + apk.getAbsolutePath());
46 | UploadPgyParams params = UploadPgyParams.getConfig(mTargetProject);
47 | // uploadPgyAndSendMessage(params.apiKey, params.appName, params.buildInstallType
48 | // , params.buildPassword, params.buildUpdateDescription
49 | // , params.buildInstallDate, params.buildChannelShortcut, apk);
50 | uploadPgyQuickWay(params.apiKey, params.appName, params.buildInstallType
51 | , params.buildPassword, params.buildUpdateDescription
52 | , params.buildInstallDate, params.buildChannelShortcut, apk);
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/PgyCOSTokenResult.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by center
7 | * 2021-09-03.
8 | * 调用蒲公英getCOSToken接口后返回的数据
9 | *
10 | */
11 | public class PgyCOSTokenResult extends BasePgyResult {
12 |
13 |
14 | @SerializedName("data")
15 | private DataDTO data;
16 |
17 | public DataDTO getData() {
18 | return data;
19 | }
20 |
21 | public void setData(DataDTO data) {
22 | this.data = data;
23 | }
24 |
25 | public static class DataDTO {
26 | @SerializedName("params")
27 | private ParamsDTO params;
28 | @SerializedName("key")
29 | private String key;
30 | @SerializedName("endpoint")
31 | private String endpoint;
32 |
33 | public ParamsDTO getParams() {
34 | return params;
35 | }
36 |
37 | public void setParams(ParamsDTO params) {
38 | this.params = params;
39 | }
40 |
41 | public String getKey() {
42 | return key;
43 | }
44 |
45 | public void setKey(String key) {
46 | this.key = key;
47 | }
48 |
49 | public String getEndpoint() {
50 | return endpoint;
51 | }
52 |
53 | public void setEndpoint(String endpoint) {
54 | this.endpoint = endpoint;
55 | }
56 |
57 | public static class ParamsDTO {
58 | @SerializedName("signature")
59 | private String signature;
60 | @SerializedName("x-cos-security-token")
61 | private String xcossecuritytoken;
62 | @SerializedName("key")
63 | private String key;
64 |
65 | public String getSignature() {
66 | return signature;
67 | }
68 |
69 | public void setSignature(String signature) {
70 | this.signature = signature;
71 | }
72 |
73 | public String getXcossecuritytoken() {
74 | return xcossecuritytoken;
75 | }
76 |
77 | public void setXcossecuritytoken(String xcossecuritytoken) {
78 | this.xcossecuritytoken = xcossecuritytoken;
79 | }
80 |
81 | public String getKey() {
82 | return key;
83 | }
84 |
85 | public void setKey(String key) {
86 | this.key = key;
87 | }
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/task/OnlyUploadTask.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.task;
2 |
3 |
4 | import net.center.upload_plugin.PluginUtils;
5 | import net.center.upload_plugin.params.UploadPgyParams;
6 |
7 | import org.gradle.api.GradleException;
8 | import org.gradle.api.tasks.TaskAction;
9 |
10 | import java.io.File;
11 | import java.util.Objects;
12 |
13 | /**
14 | * Created by Android-ZX
15 | * 2021/9/3.
16 | */
17 | public class OnlyUploadTask extends BaseTask {
18 |
19 | @TaskAction
20 | public void uploadToPGY() {
21 | UploadPgyParams params = UploadPgyParams.getConfig(mTargetProject);
22 | if (PluginUtils.isEmpty(params.uploadApkFilePath)) {
23 | System.out.println("The configured APK upload path (uploadApkFilePath) is empty");
24 | throw new GradleException("The configured APK upload path (uploadApkFilePath) is empty!");
25 | // return;
26 | }
27 | File apkDir = new File(params.uploadApkFilePath);
28 | if (!apkDir.exists()) {
29 | throw new GradleException("The configured APK upload file does not exist!");
30 | }
31 | System.out.println("ApkDir path: " + apkDir.getAbsolutePath());
32 | File apk = null;
33 | if (apkDir.getName().endsWith(".apk")) {
34 | apk = apkDir;
35 | } else {
36 | if (apkDir.listFiles() != null) {
37 | for (int i = Objects.requireNonNull(apkDir.listFiles()).length - 1; i >= 0; i--) {
38 | File apkFile = Objects.requireNonNull(apkDir.listFiles())[i];
39 | if (apkFile != null && apkFile.exists() && apkFile.getName().endsWith(".apk")) {
40 | apk = apkFile;
41 | break;
42 | }
43 | }
44 | }
45 | }
46 | if (apk == null || !apk.exists()) {
47 | throw new GradleException("The configured APK upload file does not exist!");
48 | }
49 | System.out.println("Final upload apk path: " + apk.getAbsolutePath());
50 | // uploadPgyAndSendMessage(params.apiKey, params.appName, params.buildInstallType
51 | // , params.buildPassword, params.buildUpdateDescription
52 | // , params.buildInstallDate, params.buildChannelShortcut, apk);
53 | uploadPgyQuickWay(params.apiKey, params.appName, params.buildInstallType
54 | , params.buildPassword, params.buildUpdateDescription
55 | , params.buildInstallDate, params.buildChannelShortcut, apk);
56 | }
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/params/UploadPgyParams.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.params;
2 |
3 | import org.gradle.api.Project;
4 |
5 | /**
6 | * Created by Android-ZX
7 | * 2021/9/3.
8 | *
9 | * 蒲公英上传参数设置
10 | */
11 | public class UploadPgyParams {
12 |
13 | //(必填) API Key 点击获取_api_key
14 | public String apiKey;
15 | public String appName;
16 | public String buildTypeName;//非蒲公英参数,用于控制打包release还是debug,默认1是release,2是debug
17 | //(选填)应用安装方式,值为(1,2,3,默认为1 公开安装)。1:公开安装,2:密码安装,3:邀请安装
18 | public int buildInstallType = 1;
19 | //(选填) 设置App安装密码,密码为空时默认公开安装
20 | public String buildPassword;
21 | //(选填) 版本更新描述,请传空字符串,或不传。
22 | public String buildUpdateDescription;
23 | //(选填)是否设置安装有效期,值为:1 设置有效时间, 2 长期有效,如果不填写不修改上一次的设置
24 | public int buildInstallDate = 2;
25 | //(选填)所需更新的指定渠道的下载短链接,只可指定一个渠道,字符串型,如:abcd
26 | public String buildChannelShortcut;
27 |
28 | public String uploadApkFilePath;
29 |
30 | public UploadPgyParams() {
31 |
32 | }
33 |
34 | public UploadPgyParams(String apiKey) {
35 | this(apiKey, "Release");
36 | }
37 |
38 | public UploadPgyParams(String apiKey, String buildTypeName) {
39 | this(apiKey, "", buildTypeName, 1, "");
40 | }
41 |
42 | public UploadPgyParams(String apiKey, String appName, String buildTypeName, int buildInstallType, String buildPassword) {
43 | this(apiKey, appName, buildTypeName, buildInstallType, buildPassword, "");
44 | }
45 |
46 | public UploadPgyParams(String apiKey, String appName, String buildTypeName, int buildInstallType, String buildPassword, String buildUpdateDescription) {
47 | this(apiKey, appName, buildTypeName, buildInstallType, buildPassword, buildUpdateDescription, 2, "");
48 | }
49 |
50 | public UploadPgyParams(String apiKey, String appName, String buildTypeName, int buildInstallType, String buildPassword, String buildUpdateDescription, int buildInstallDate, String buildChannelShortcut) {
51 | this.apiKey = apiKey;
52 | this.appName = appName;
53 | this.buildTypeName = buildTypeName;
54 | this.buildInstallType = buildInstallType;
55 | this.buildPassword = buildPassword;
56 | this.buildUpdateDescription = buildUpdateDescription;
57 | this.buildInstallDate = buildInstallDate;
58 | this.buildChannelShortcut = buildChannelShortcut;
59 | }
60 |
61 | public static UploadPgyParams getConfig(Project project) {
62 | UploadPgyParams extension = project.getExtensions().findByType(UploadPgyParams.class);
63 | if (extension == null) {
64 | extension = new UploadPgyParams();
65 | }
66 | return extension;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/helper/CmdHelper.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.helper;
2 |
3 | import net.center.upload_plugin.params.GitLogParams;
4 |
5 | import org.gradle.api.Project;
6 |
7 | import java.io.BufferedReader;
8 | import java.io.IOException;
9 | import java.io.InputStreamReader;
10 | import java.nio.charset.StandardCharsets;
11 |
12 | /**
13 | * Created by 钟新
14 | * Time:2022/9/1.
15 | * Desc:
16 | */
17 | public class CmdHelper {
18 | private static final int LOG_MAX_COUNT = 50;
19 | private static final int LOG_MIN_COUNT = 10;
20 | private static final String GIT_LOG_BASIC_CMD = "git log --oneline --pretty=format:\"%an—>%s\" --no-merges";
21 | public static final String gitLogCmd = GIT_LOG_BASIC_CMD + " --since=\"2022-8-30\" --until=\"2022-9-1\"";
22 | /**
23 | * %ai 是时间,格式:2022-08-31 23:18:48 +0800
24 | */
25 | public static final String gitLogCmd2 = "git log --oneline --pretty=format:\"%ai,%an:%s\" --no-merges --since=2days";
26 | public static final String gitLogCmd3 = GIT_LOG_BASIC_CMD + " --max-count=10";
27 |
28 | public static String checkGetGitParamsWithLog(Project project) {
29 | GitLogParams gitLogParams = GitLogParams.getGitParamsConfig(project);
30 | if (gitLogParams == null) {
31 | return "";
32 | }
33 | return getGitLogByTimeAndCount(gitLogParams.gitLogHistoryDayTime, gitLogParams.gitLogMaxCount);
34 | }
35 |
36 | public static String getGitLogByTimeAndCount(int logDayTime, int logMaxCount) {
37 | StringBuilder logBuilder = new StringBuilder(GIT_LOG_BASIC_CMD);
38 | if (logDayTime >= 1) {
39 | logBuilder.append(" --since=").append(logDayTime).append("days");
40 | logMaxCount = LOG_MAX_COUNT;
41 | } else {
42 | if (logMaxCount <= 0) {
43 | logMaxCount = LOG_MIN_COUNT;
44 | } else if (logMaxCount > LOG_MAX_COUNT) {
45 | logMaxCount = LOG_MAX_COUNT;
46 | }
47 | }
48 | logBuilder.append(" --max-count=").append(logMaxCount);
49 | return exeCmd(logBuilder.toString());
50 | }
51 |
52 | public static String exeCmd(String commandStr) {
53 | BufferedReader bufferedReader = null;
54 | Process p = null;
55 | try {
56 | p = Runtime.getRuntime().exec(commandStr);
57 | //Charset.forName("UTF-8")
58 | bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
59 | StringBuilder stringBuilder = new StringBuilder();
60 | String line;
61 | int count = 0;
62 | while ((line = bufferedReader.readLine()) != null) {
63 | ++count;
64 | stringBuilder.append(count).append(". ").append(line).append("\n ");
65 | }
66 | System.out.println("ExeCmd result:\n" + stringBuilder);
67 | return stringBuilder.toString();
68 | } catch (Exception e) {
69 | e.printStackTrace();
70 | System.out.println(e.getMessage());
71 | } finally {
72 | if (bufferedReader != null) {
73 | try {
74 | bufferedReader.close();
75 | } catch (IOException e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | if (p != null) {
80 | try {
81 | p.waitFor();
82 | } catch (InterruptedException e) {
83 | e.printStackTrace();
84 | }
85 | }
86 | }
87 | return "";
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/UploadApkPlugin.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin;
2 |
3 | import com.android.build.gradle.AppExtension;
4 | import com.android.build.gradle.api.ApplicationVariant;
5 |
6 | import net.center.upload_plugin.params.GitLogParams;
7 | import net.center.upload_plugin.params.SendDingParams;
8 | import net.center.upload_plugin.params.SendFeishuParams;
9 | import net.center.upload_plugin.params.SendWeixinGroupParams;
10 | import net.center.upload_plugin.params.UploadPgyParams;
11 | import net.center.upload_plugin.task.BuildAndUploadTask;
12 | import net.center.upload_plugin.task.OnlyUploadTask;
13 |
14 | import org.gradle.api.DomainObjectSet;
15 | import org.gradle.api.Plugin;
16 | import org.gradle.api.Project;
17 |
18 | /**
19 | * Created by Android-ZX
20 | * 2021/9/3.
21 | */
22 | public class UploadApkPlugin implements Plugin {
23 |
24 | @Override
25 | public void apply(Project project) {
26 | UploadPgyParams uploadParams = project.getExtensions().create(PluginConstants.UPLOAD_PARAMS_NAME, UploadPgyParams.class);
27 | createParams(project);
28 | dependsOnOnlyUploadTask(uploadParams, project);
29 | // UploadPgyParams ext = (UploadPgyParams) project.property(PluginConstants.UPLOAD_PARAMS_NAME);
30 | // System.out.println("apkfile path1: " + uploadParams.uploadApkFilePath);
31 | // System.out.println("apkfile path2: " + ext.uploadApkFilePath);
32 | project.afterEvaluate(project1 -> {
33 | AppExtension appExtension = ((AppExtension) project1.getExtensions().findByName(PluginConstants.ANDROID_EXTENSION_NAME));
34 | if (appExtension == null) {
35 | return;
36 | }
37 | DomainObjectSet appVariants = appExtension.getApplicationVariants();
38 | for (ApplicationVariant applicationVariant : appVariants) {
39 | if (applicationVariant.getBuildType() != null) {
40 | dependsOnTask(applicationVariant, uploadParams, project1);
41 | }
42 | }
43 | });
44 | }
45 |
46 | private void createParams(Project project) {
47 | project.getExtensions().create(PluginConstants.GIT_LOG_PARAMS_NAME, GitLogParams.class);
48 | project.getExtensions().create(PluginConstants.DING_PARAMS_NAME, SendDingParams.class);
49 | project.getExtensions().create(PluginConstants.FEISHU_PARAMS_NAME, SendFeishuParams.class);
50 | project.getExtensions().create(PluginConstants.WEIXIN_GROUP_PARAMS_NAME, SendWeixinGroupParams.class);
51 | }
52 |
53 |
54 | private void dependsOnTask(ApplicationVariant applicationVariant, UploadPgyParams uploadParams, Project project1) {
55 | String variantName =
56 | applicationVariant.getName().substring(0, 1).toUpperCase() + applicationVariant.getName().substring(1);
57 | if (PluginUtils.isEmpty(variantName)) {
58 | variantName = PluginUtils.isEmpty(uploadParams.buildTypeName) ? "Release" : uploadParams.buildTypeName;
59 | }
60 | //创建我们,上传到蒲公英的task任务
61 | BuildAndUploadTask uploadTask = project1.getTasks()
62 | .create(PluginConstants.TASK_EXTENSION_NAME + variantName, BuildAndUploadTask.class);
63 | uploadTask.init(applicationVariant, project1);
64 |
65 | //依赖关系 。上传依赖打包,打包依赖clean。
66 | applicationVariant.getAssembleProvider().get().dependsOn(project1.getTasks().findByName("clean"));
67 | uploadTask.dependsOn(applicationVariant.getAssembleProvider().get());
68 | }
69 |
70 | private void dependsOnOnlyUploadTask(UploadPgyParams uploadParams, Project project1) {
71 | //创建我们,上传到蒲公英的task任务
72 | OnlyUploadTask uploadTask = project1.getTasks()
73 | .create(PluginConstants.TASK_EXTENSION_NAME_ONLY_UPLOAD, OnlyUploadTask.class);
74 | uploadTask.init(null, project1);
75 |
76 | // //依赖关系 。上传依赖打包,打包依赖clean。
77 | // applicationVariant.getAssembleProvider().get().dependsOn(project1.getTasks().findByName("clean"));
78 | // uploadTask.dependsOn(applicationVariant.getAssembleProvider().get());
79 | }
80 | }
81 |
82 |
83 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/WXGroupRequestBean.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by center
9 | * 企业微信发送消息请求实体类
10 | */
11 | public class WXGroupRequestBean {
12 |
13 | @SerializedName("msgtype")
14 | private String msgtype;
15 |
16 | @SerializedName("text")
17 | private TextDTO text;
18 |
19 | @SerializedName("markdown")
20 | private MarkdownDTO markdown;
21 |
22 | @SerializedName("news")
23 | private NewsDTO news;
24 |
25 |
26 | public String getMsgtype() {
27 | return msgtype;
28 | }
29 |
30 | public void setMsgtype(String msgtype) {
31 | this.msgtype = msgtype;
32 | }
33 |
34 | public TextDTO getText() {
35 | return text;
36 | }
37 |
38 | public void setText(TextDTO text) {
39 | this.text = text;
40 | }
41 |
42 | public MarkdownDTO getMarkdown() {
43 | return markdown;
44 | }
45 |
46 | public void setMarkdown(MarkdownDTO markdown) {
47 | this.markdown = markdown;
48 | }
49 |
50 | public NewsDTO getNews() {
51 | return news;
52 | }
53 |
54 | public void setNews(NewsDTO news) {
55 | this.news = news;
56 | }
57 |
58 | public static class NewsDTO {
59 | @SerializedName("articles")
60 | private List articles;
61 |
62 | public List getArticles() {
63 | return articles;
64 | }
65 |
66 | public void setArticles(List articles) {
67 | this.articles = articles;
68 | }
69 |
70 | public static class ArticlesDTO {
71 | @SerializedName("title")
72 | private String title;
73 | @SerializedName("description")
74 | private String description;
75 | @SerializedName("url")
76 | private String url;
77 | @SerializedName("picurl")
78 | private String picurl;
79 |
80 | public String getTitle() {
81 | return title;
82 | }
83 |
84 | public void setTitle(String title) {
85 | this.title = title;
86 | }
87 |
88 | public String getDescription() {
89 | return description;
90 | }
91 |
92 | public void setDescription(String description) {
93 | this.description = description;
94 | }
95 |
96 | public String getUrl() {
97 | return url;
98 | }
99 |
100 | public void setUrl(String url) {
101 | this.url = url;
102 | }
103 |
104 | public String getPicurl() {
105 | return picurl;
106 | }
107 |
108 | public void setPicurl(String picurl) {
109 | this.picurl = picurl;
110 | }
111 | }
112 | }
113 |
114 | /**
115 | * "content": "实时新增用户反馈132例,请相关同事注意。\n
116 | * >类型:用户反馈
117 | * >普通用户反馈:117例
118 | * >VIP用户反馈:15例"
119 | *
120 | * [这是一个链接](http://work.weixin.qq.com/api/doc)
121 | *
122 | * 绿色
123 | * 灰色
124 | * 橙红色
125 | */
126 | public static class MarkdownDTO {
127 | @SerializedName("content")
128 | private String content;
129 |
130 | public String getContent() {
131 | return content;
132 | }
133 |
134 | public void setContent(String content) {
135 | this.content = content;
136 | }
137 | }
138 |
139 | /**
140 | * {
141 | * "msgtype": "text",
142 | * "text": {
143 | * "content": "广州今日天气:29度,大部分多云,降雨概率:60%",
144 | * "mentioned_list":["wangqing","@all"],
145 | * "mentioned_mobile_list":["13800001111","@all"]
146 | * }
147 | * }
148 | */
149 | public static class TextDTO {
150 | @SerializedName("content")
151 | private String content;
152 | @SerializedName("mentioned_list")
153 | private List mentioned_list;
154 | @SerializedName("mentioned_mobile_list")
155 | private List mentioned_mobile_list;
156 |
157 |
158 | public String getContent() {
159 | return content;
160 | }
161 |
162 | public void setContent(String content) {
163 | this.content = content;
164 | }
165 |
166 |
167 | public List getMentioned_list() {
168 | return mentioned_list;
169 | }
170 |
171 | public void setMentioned_list(List mentioned_list) {
172 | this.mentioned_list = mentioned_list;
173 | }
174 |
175 | public List getMentioned_mobile_list() {
176 | return mentioned_mobile_list;
177 | }
178 |
179 | public void setMentioned_mobile_list(List mentioned_mobile_list) {
180 | this.mentioned_mobile_list = mentioned_mobile_list;
181 | }
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UploadApkPlugin
2 |
3 | 我们有这样的场景,在项目开发测试阶段,经常会将apk打包后,上传到蒲公英等三方平台,然后再发给公司其他人员进行测试、体验。每次发包的时候要去进行上传、上传完后通知相关人员,导致有点繁琐,浪费时间。此插件为了解决这个问题。
4 |
5 | Gradle插件,依赖进项目工程,编译APK,使用Task命令一键上传apk到三方平台,如:蒲公英。(目前暂时只支持蒲公英,可以进行扩展)。
6 | 上传成功后,如果你需要提醒其他人员进行版本更新,如:钉钉群、飞书群、企业微信群等(还可扩展其他),配置相关参数,自动发送更新消息到群里。
7 |
8 | ## 更新记录:
9 |
10 | 2022-08-22:
11 | 蒲公英上传接口做了调整,原有接口将废弃:https://www.pgyer.com/doc/view/api#fastUploadApp插件已根据文档做升级。
12 | 修复版本v1.0.3
13 |
14 | 2022-09-03:
15 | (1)修复发送消息到飞书出现msg_type参数错误问题;
16 | (2)新增Git提交日志参数,用于发送消息时携带Git日志;
17 | (3)完善飞书、钉钉、微信发送消息的类型并添加Git日志
18 | 修复版本v1.0.6
19 |
20 | 2022-10-30:
21 |
22 | 【新增】根据配置(uploadApkFilePath)要上传的APK文件路径,通过Task直接上传Apk。v1.0.7
23 | 这样减少编译流程和支持上传自己加固后的包。
24 |
25 | 2023-07-01:
26 | 【新增】发送消息内容,title部分新加Flavor信息。
27 | ## 使用步骤
28 |
29 | 1、在项目工程跟目录,工程的build.gradle dependencies中添加:
30 |
31 | `classpath 'com.github.centerzx:UploadApkPlugin:v***'`
32 | 目前版本为:
33 |
34 | `classpath 'com.github.centerzx:UploadApkPlugin:v1.0.7'`
35 |
36 | repositories中添加:
37 |
38 | maven { url "[https://jitpack.io](https://links.jianshu.com/go?to=https%3A%2F%2Fjitpack.io)"}
39 |
40 | 2、在app目录(需要打包上传的APK的Module)的build.gradle中添加引用插件:
41 |
42 | `apply plugin: 'center.uploadpgy.plugin'`
43 |
44 | **引入后,配置自己的相关平台参数:**
45 |
46 | ### (1)上传到蒲公英的相关配置参数
47 |
48 | ```
49 | uploadPgyParams {
50 | apiKey = "替换为自己蒲公英账户的apiKey"
51 | // apiKey = readProperties("PgyApiKey")
52 | //暂时无用
53 | appName = "TestGradlePlugin"
54 | buildTypeName = "Release"
55 | buildInstallType = 2
56 | buildPassword = "zx"
57 |
58 | uploadApkFilePath = "E:\\Desktop\\release\\app_name-debug.apk"
59 | }
60 | ```
61 |
62 | ### (2)发送消息到钉钉的相关配置参数
63 |
64 | ```
65 | buildDingParams {
66 | accessToken = "替换为自己钉钉的token"
67 | // accessToken = readProperties("DingAccessToken")
68 | contentText = "最新开发测试包已经上传至蒲公英, 可以下载使用了"
69 | contentTitle = "开发测试包"
70 | //link类型(link)、markdown类型(markdown)、整体跳转ActionCard类型(actionCard),默认link
71 | msgtype = "actionCard"
72 | //如果使用markdown类型可添加参数是否@全体群人员,默认false:isAtAll = true。其他类型不支持
73 | isAtAll = true
74 | //存在点击时按钮的文案(link类型无)
75 | clickTxt = "点击进行下载"
76 | //是否单独支持发送Git记录数据,在配置了buildGitLogParams前提下有效,默认为true。link字数问题,无法支持
77 | isSupportGitLog = true
78 | }
79 | ```
80 |
81 | ### (3)发送消息到飞书的相关配置参数
82 |
83 | ```
84 | buildFeiShuParams {
85 | webHookHostUrl = "https://open.feishu.cn/open-apis/bot/v2/hook/************"
86 | // webHookHostUrl = readProperties("FeiShuWebHookHostUrl")
87 | contentTitle = "开发测试包"
88 | contentText = "最新开发测试包已经上传至蒲公英, 可以下载使用了"
89 | //富文本消息(post)、消息卡片(interactive),默认post
90 | msgtype = "post"
91 | //是否@全体群人员,默认false:isAtAll = true
92 | isAtAll = true
93 | clickTxt = "点击进行下载"
94 | //是否单独支持发送Git记录数据,在配置了buildGitLogParams前提下有效,默认为true
95 | isSupportGitLog = true
96 | }
97 | ```
98 |
99 | ### (4)发送消息到企业微信群的相关配置参数
100 |
101 | ```
102 | buildWeixinGroupParams {
103 | // webHookHostUrl = readProperties("WeixinWebHookUrl")
104 | webHookUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=************"
105 | //文本(text)、markdown(markdown)、图文(news),默认 markdown。由于字数限制,只有markdown支持携带Git记录
106 | msgtype = "markdown"
107 | //如果使用文本类型(text)可添加参数是否@全体群人员,默认true:isAtAll = true。其他类型不支持
108 | //isAtAll = true
109 | contentTitle = "开发测试包"
110 | contentText = "最新开发测试包已经上传至蒲公英, 可以下载使用了"
111 | //是否单独支持发送Git记录数据,在配置了buildGitLogParams前提下有效,默认为true。只有markdown类型支持
112 | isSupportGitLog = true
113 | }
114 | ```
115 |
116 | ### (5)发送消息时携带Git提交记录相关配置参数
117 |
118 | ```
119 | buildGitLogParams {
120 | //是否发送消息是携带Git记录日志,如果配置了这块参数才会携带Git记录,消息里面可以单独设置是否携带Git日志数据
121 |
122 | //获取以当前时间为基准至N天之前的Git记录(限定时间范围),不填或小于等于0为全部记录,会结合数量进行获取
123 | gitLogHistoryDayTime = 3
124 | //显示Git记录的最大数量,值范围1~50,不填默认是10条,最大数量50条
125 | gitLogMaxCount = 20
126 | }
127 | ```
128 |
129 | 其中各个参数体的名称不能变,否则编译会报错,参数key不能修改,对于的值可以根据自己情况修改。
130 | 参数中的“***************”号是根据你的蒲公英、钉钉、飞书、企业微信群等情况进行配置。
131 | 由于key、token等信息都需要保密,万一泄漏,可能被别有用心的人乱使用,故可以将相关关键信息保存在工程的:local.properties文件里面,此文件一般是根据自己本地进行配置的,不会上传到git。然后进行数据读取,如:readProperties("
132 | PgyApiKey")
133 |
134 | 将密钥存在本地 防止泄露 local.properties 在Git的时候不会被上传
135 |
136 | ```
137 | def readProperties(key) {
138 | File file = rootProject.file('local.properties')
139 | if (file.exists()) {
140 | InputStream inputStream = file.newDataInputStream()
141 | Properties properties = new Properties()
142 | properties.load(inputStream)
143 | if (properties.containsKey(key)) {
144 | return properties.getProperty(key)
145 | }
146 | }
147 | }
148 | ```
149 |
150 | 3、配置完备,进行编译: 此时在studio的右边,tasks里面会新增一个publishToThirdPlatform
151 | 命令组,里面会有3个task:ApkBuildUploadPlatformDebug、ApkBuildUploadPlatformRelease、OnlyUploadApkToPlatform,其中OnlyUploadApkToPlatform为直接上传APK操作,配置uploadApkFilePath路径后有效。gradlew或者点击运行组里面的task命令,则可直接进行编译、打包、传送、发消息等一些列操作。
152 | 在执行task命令时,studio的run窗口会展示执行情况,包括蒲公英上传情况、钉钉飞书等消息发送情况,一目了然。
153 |
154 | 注意:由于这样会导致app的gradle看着很臃肿,因此可以单独新建一个gradle文件进行配置,然后再在app的gradle文件中apply from: "../******.gradle"
155 | 这个新建gradle就行。
156 |
157 |
158 |
159 | 
160 |
161 | 在执行task命令时,studio的run窗口会展示执行情况,包括蒲公英上传情况、钉钉飞书等消息发送情况,一目了然。
162 |
163 | 
164 |
165 | 
166 |
167 | **钉钉link类型消息提醒**
168 |
169 | 
170 |
171 | **钉钉markdown类型消息提醒**
172 |
173 | 
174 |
175 | **钉钉actionCard类型消息提醒**
176 |
177 | 
178 | **飞书post类型消息提醒**
179 |
180 | 
181 |
182 | **飞书interactive类型消息提醒**
183 |
184 | 
185 |
186 | **企业微信群消息**
187 |
188 |
189 | ## 后期展望:
190 |
191 | ```
192 | 1、使用kotlin
193 | 2、扩展新增firim上传APK包形式(来自:https://github.com/D-zy 建议)
194 | 3、扩展新增发送的消息中自动携带Git的提交记录描述(已完成。来自 https://github.com/alizhijun 建议)
195 | 4、扩展新增多渠道打包(来自:https://github.com/alizhijun 建议)
196 | 5、扩展新增Apk加固(来自:https://github.com/j-gin 建议)——方案:由于每个公司或者项目组可能用的加固方案不同,故使用配置上传APK路径(加固后的APK路径)形式达到目的。
197 | ```
198 |
199 | 大概情况是这样,如有不足和错误的地方,欢迎大家讨论指正和提建议!感谢来个star。
200 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/PgyUploadResult.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | /**
6 | * Created by center
7 | * 2021-09-03.
8 | * 蒲公英上传成功后的数据model
9 | *
10 | * buildKey String Build Key是唯一标识应用的索引ID
11 | * buildType Integer 应用类型(1:iOS; 2:Android)
12 | * buildIsFirst Integer 是否是第一个App(1:是; 2:否)
13 | * buildIsLastest Integer 是否是最新版(1:是; 2:否)
14 | * buildFileSize Integer App 文件大小
15 | * buildName String 应用名称
16 | * buildVersion String 版本号, 默认为1.0 (是应用向用户宣传时候用到的标识,例如:1.1、8.2.1等。)
17 | * buildVersionNo String 上传包的版本编号,默认为1 (即编译的版本号,一般来说,编译一次会变动一次这个版本号, 在 Android 上叫 Version Code。对于 iOS 来说,是字符串类型;对于 Android 来说是一个整数。例如:1001,28等。)
18 | * buildBuildVersion Integer 蒲公英生成的用于区分历史版本的build号
19 | * buildIdentifier String 应用程序包名,iOS为BundleId,Android为包名
20 | * buildIcon String 应用的Icon图标key,访问地址为 https://www.pgyer.com/image/view/app_icons/[应用的Icon图标key]
21 | * buildDescription String 应用介绍
22 | * buildUpdateDescription String 应用更新说明
23 | * buildScreenShots String 应用截图的key,获取地址为 https://www.pgyer.com/image/view/app_screenshots/[应用截图的key]
24 | * buildShortcutUrl String 应用短链接
25 | * buildQRCodeURL String 应用二维码地址
26 | * buildCreated String 应用上传时间
27 | * buildUpdated String 应用更新时间
28 | */
29 | public class PgyUploadResult extends BasePgyResult {
30 |
31 | @SerializedName("data")
32 | private DataDTO data;
33 |
34 | public DataDTO getData() {
35 | return data;
36 | }
37 |
38 | public void setData(DataDTO data) {
39 | this.data = data;
40 | }
41 |
42 | public static class DataDTO {
43 | @SerializedName("buildKey")
44 | private String buildKey;
45 | @SerializedName("buildType")
46 | private String buildType;
47 | @SerializedName("buildIsFirst")
48 | private String buildIsFirst;
49 | @SerializedName("buildIsLastest")
50 | private String buildIsLastest;
51 | @SerializedName("buildFileKey")
52 | private String buildFileKey;
53 | @SerializedName("buildFileName")
54 | private String buildFileName;
55 | @SerializedName("buildFileSize")
56 | private String buildFileSize;
57 | @SerializedName("buildName")
58 | private String buildName;
59 | @SerializedName("buildVersion")
60 | private String buildVersion;
61 | @SerializedName("buildVersionNo")
62 | private String buildVersionNo;
63 | @SerializedName("buildBuildVersion")
64 | private String buildBuildVersion;
65 | @SerializedName("buildIdentifier")
66 | private String buildIdentifier;
67 | @SerializedName("buildIcon")
68 | private String buildIcon;
69 | @SerializedName("buildDescription")
70 | private String buildDescription;
71 | @SerializedName("buildUpdateDescription")
72 | private String buildUpdateDescription;
73 | @SerializedName("buildScreenshots")
74 | private String buildScreenshots;
75 | @SerializedName("buildShortcutUrl")
76 | private String buildShortcutUrl;
77 | @SerializedName("buildCreated")
78 | private String buildCreated;
79 | @SerializedName("buildUpdated")
80 | private String buildUpdated;
81 | @SerializedName("buildQRCodeURL")
82 | private String buildQRCodeURL;
83 |
84 |
85 | public String getBuildKey() {
86 | return buildKey;
87 | }
88 |
89 | public void setBuildKey(String buildKey) {
90 | this.buildKey = buildKey;
91 | }
92 |
93 | public String getBuildType() {
94 | return buildType;
95 | }
96 |
97 | public void setBuildType(String buildType) {
98 | this.buildType = buildType;
99 | }
100 |
101 | public String getBuildIsFirst() {
102 | return buildIsFirst;
103 | }
104 |
105 | public void setBuildIsFirst(String buildIsFirst) {
106 | this.buildIsFirst = buildIsFirst;
107 | }
108 |
109 | public String getBuildIsLastest() {
110 | return buildIsLastest;
111 | }
112 |
113 | public void setBuildIsLastest(String buildIsLastest) {
114 | this.buildIsLastest = buildIsLastest;
115 | }
116 |
117 | public String getBuildFileKey() {
118 | return buildFileKey;
119 | }
120 |
121 | public void setBuildFileKey(String buildFileKey) {
122 | this.buildFileKey = buildFileKey;
123 | }
124 |
125 | public String getBuildFileName() {
126 | return buildFileName;
127 | }
128 |
129 | public void setBuildFileName(String buildFileName) {
130 | this.buildFileName = buildFileName;
131 | }
132 |
133 | public String getBuildFileSize() {
134 | return buildFileSize;
135 | }
136 |
137 | public void setBuildFileSize(String buildFileSize) {
138 | this.buildFileSize = buildFileSize;
139 | }
140 |
141 | public String getBuildName() {
142 | return buildName;
143 | }
144 |
145 | public void setBuildName(String buildName) {
146 | this.buildName = buildName;
147 | }
148 |
149 | public String getBuildVersion() {
150 | return buildVersion;
151 | }
152 |
153 | public void setBuildVersion(String buildVersion) {
154 | this.buildVersion = buildVersion;
155 | }
156 |
157 | public String getBuildVersionNo() {
158 | return buildVersionNo;
159 | }
160 |
161 | public void setBuildVersionNo(String buildVersionNo) {
162 | this.buildVersionNo = buildVersionNo;
163 | }
164 |
165 | public String getBuildBuildVersion() {
166 | return buildBuildVersion;
167 | }
168 |
169 | public void setBuildBuildVersion(String buildBuildVersion) {
170 | this.buildBuildVersion = buildBuildVersion;
171 | }
172 |
173 | public String getBuildIdentifier() {
174 | return buildIdentifier;
175 | }
176 |
177 | public void setBuildIdentifier(String buildIdentifier) {
178 | this.buildIdentifier = buildIdentifier;
179 | }
180 |
181 | public String getBuildIcon() {
182 | return buildIcon;
183 | }
184 |
185 | public void setBuildIcon(String buildIcon) {
186 | this.buildIcon = buildIcon;
187 | }
188 |
189 | public String getBuildDescription() {
190 | return buildDescription;
191 | }
192 |
193 | public void setBuildDescription(String buildDescription) {
194 | this.buildDescription = buildDescription;
195 | }
196 |
197 | public String getBuildUpdateDescription() {
198 | return buildUpdateDescription;
199 | }
200 |
201 | public void setBuildUpdateDescription(String buildUpdateDescription) {
202 | this.buildUpdateDescription = buildUpdateDescription;
203 | }
204 |
205 | public String getBuildScreenshots() {
206 | return buildScreenshots;
207 | }
208 |
209 | public void setBuildScreenshots(String buildScreenshots) {
210 | this.buildScreenshots = buildScreenshots;
211 | }
212 |
213 | public String getBuildShortcutUrl() {
214 | return buildShortcutUrl;
215 | }
216 |
217 | public void setBuildShortcutUrl(String buildShortcutUrl) {
218 | this.buildShortcutUrl = buildShortcutUrl;
219 | }
220 |
221 | public String getBuildCreated() {
222 | return buildCreated;
223 | }
224 |
225 | public void setBuildCreated(String buildCreated) {
226 | this.buildCreated = buildCreated;
227 | }
228 |
229 | public String getBuildUpdated() {
230 | return buildUpdated;
231 | }
232 |
233 | public void setBuildUpdated(String buildUpdated) {
234 | this.buildUpdated = buildUpdated;
235 | }
236 |
237 | public String getBuildQRCodeURL() {
238 | return buildQRCodeURL;
239 | }
240 |
241 | public void setBuildQRCodeURL(String buildQRCodeURL) {
242 | this.buildQRCodeURL = buildQRCodeURL;
243 | }
244 | }
245 | }
246 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/DingDingRequestBean.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by center
9 | * 2021-09-04.
10 | *
11 | * 目前只支持markdown语法的子集,具体支持的元素如下:
12 | *
13 | * 标题
14 | * # 一级标题
15 | * ## 二级标题
16 | * ### 三级标题
17 | * #### 四级标题
18 | * ##### 五级标题
19 | * ###### 六级标题
20 | *
21 | * 引用
22 | * > A man who stands for nothing will fall for anything.
23 | *
24 | * 文字加粗、斜体
25 | * **bold**
26 | * *italic*
27 | *
28 | * 链接
29 | * [this is a link](http://name.com)
30 | *
31 | * 图片
32 | * 
33 | *
34 | * 无序列表
35 | * - item1
36 | * - item2
37 | *
38 | * 有序列表
39 | * 1. item1
40 | * 2. item2
41 | */
42 | public class DingDingRequestBean {
43 |
44 |
45 | @SerializedName("msgtype")
46 | private String msgtype;
47 |
48 | /**
49 | * link类型的消息
50 | */
51 | @SerializedName("link")
52 | private LinkDTO link;
53 |
54 | /**
55 | * markdown 类型的消息
56 | */
57 | @SerializedName("markdown")
58 | private MarkDownDTO markdown;
59 | @SerializedName("at")
60 | private AtDTO at;
61 |
62 | /**
63 | * 整体跳转ActionCard类型和独立跳转ActionCard类型
64 | */
65 | @SerializedName("actionCard")
66 | private ActionCardDTO actionCard;
67 |
68 |
69 | public String getMsgtype() {
70 | return msgtype;
71 | }
72 |
73 | public void setMsgtype(String msgtype) {
74 | this.msgtype = msgtype;
75 | }
76 |
77 | public LinkDTO getLink() {
78 | return link;
79 | }
80 |
81 | public void setLink(LinkDTO link) {
82 | this.link = link;
83 | }
84 |
85 | public MarkDownDTO getMarkdown() {
86 | return markdown;
87 | }
88 |
89 | public void setMarkdown(MarkDownDTO markdown) {
90 | this.markdown = markdown;
91 | }
92 |
93 | public AtDTO getAt() {
94 | return at;
95 | }
96 |
97 | public void setAt(AtDTO at) {
98 | this.at = at;
99 | }
100 |
101 | public ActionCardDTO getActionCard() {
102 | return actionCard;
103 | }
104 |
105 | public void setActionCard(ActionCardDTO actionCard) {
106 | this.actionCard = actionCard;
107 | }
108 |
109 | public static class LinkDTO {
110 | @SerializedName("text")
111 | private String text;
112 | @SerializedName("title")
113 | private String title;
114 | @SerializedName("picUrl")
115 | private String picUrl;
116 | @SerializedName("messageUrl")
117 | private String messageUrl;
118 |
119 | public String getText() {
120 | return text;
121 | }
122 |
123 | public void setText(String text) {
124 | this.text = text;
125 | }
126 |
127 | public String getTitle() {
128 | return title;
129 | }
130 |
131 | public void setTitle(String title) {
132 | this.title = title;
133 | }
134 |
135 | public String getPicUrl() {
136 | return picUrl;
137 | }
138 |
139 | public void setPicUrl(String picUrl) {
140 | this.picUrl = picUrl;
141 | }
142 |
143 | public String getMessageUrl() {
144 | return messageUrl;
145 | }
146 |
147 | public void setMessageUrl(String messageUrl) {
148 | this.messageUrl = messageUrl;
149 | }
150 | }
151 |
152 | /**
153 | * "markdown": {
154 | * "title":"杭州天气",
155 | * "text": "#### 杭州天气 @150XXXXXXXX \n > 9度,西北风1级,空气良89,相对温度73%\n > \n > ###### 10点20分发布 [天气](https://www.dingtalk.com) \n"
156 | * },
157 | */
158 | public static class MarkDownDTO {
159 | /**
160 | * markdown格式的消息。
161 | */
162 | @SerializedName("text")
163 | private String text;
164 | @SerializedName("title")
165 | private String title;
166 |
167 | public String getText() {
168 | return text;
169 | }
170 |
171 | public void setText(String text) {
172 | this.text = text;
173 | }
174 |
175 | public String getTitle() {
176 | return title;
177 | }
178 |
179 | public void setTitle(String title) {
180 | this.title = title;
181 | }
182 | }
183 |
184 | /**
185 | * "at": {
186 | * "atMobiles": [
187 | * "150XXXXXXXX"
188 | * ],
189 | * "atUserIds": [
190 | * "user123"
191 | * ],
192 | * "isAtAll": false
193 | * }
194 | */
195 | public static class AtDTO {
196 | @SerializedName("atMobiles")
197 | private List atMobiles;
198 | @SerializedName("atUserIds")
199 | private List atUserIds;
200 | @SerializedName("isAtAll")
201 | private boolean isAtAll;
202 |
203 | public List getAtMobiles() {
204 | return atMobiles;
205 | }
206 |
207 | public void setAtMobiles(List atMobiles) {
208 | this.atMobiles = atMobiles;
209 | }
210 |
211 | public List getAtUserIds() {
212 | return atUserIds;
213 | }
214 |
215 | public void setAtUserIds(List atUserIds) {
216 | this.atUserIds = atUserIds;
217 | }
218 |
219 | public boolean isAtAll() {
220 | return isAtAll;
221 | }
222 |
223 | public void setIsAtAll(boolean atAll) {
224 | isAtAll = atAll;
225 | }
226 |
227 | }
228 |
229 | /**
230 | * "actionCard": {
231 | * "title": "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
232 | * "text": "
233 | * ### 乔布斯 20 年前想打造的苹果咖啡厅
234 | * Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
235 | * "btnOrientation": "0",
236 | * "singleTitle" : "阅读全文",
237 | * "singleURL" : "https://www.dingtalk.com/"
238 | * },
239 | *
240 | *
241 | * "actionCard": {
242 | * "title": "我 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
243 | * "text": " \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
244 | * "btnOrientation": "0",
245 | * "btns": [{
246 | * "title": "内容不错",
247 | * "actionURL": "https://www.dingtalk.com/"
248 | * },
249 | * {
250 | * "title": "不感兴趣",
251 | * "actionURL": "https://www.dingtalk.com/"
252 | * }
253 | * ]
254 | * }
255 | */
256 | public static class ActionCardDTO {
257 | @SerializedName("title")
258 | private String title;
259 | @SerializedName("text")
260 | private String text;
261 | @SerializedName("btnOrientation")
262 | private String btnOrientation;
263 |
264 | /**
265 | * 整体跳转ActionCard类型 使用
266 | */
267 | @SerializedName("singleTitle")
268 | private String singleTitle;
269 | @SerializedName("singleURL")
270 | private String singleURL;
271 |
272 | /**
273 | * 独立跳转ActionCard类型 使用
274 | */
275 | @SerializedName("btns")
276 | private List btns;
277 |
278 | public static class BtnsDTO {
279 | @SerializedName("title")
280 | private String title;
281 | @SerializedName("actionURL")
282 | private String actionURL;
283 |
284 | public String getTitle() {
285 | return title;
286 | }
287 |
288 | public void setTitle(String title) {
289 | this.title = title;
290 | }
291 |
292 | public String getActionURL() {
293 | return actionURL;
294 | }
295 |
296 | public void setActionURL(String actionURL) {
297 | this.actionURL = actionURL;
298 | }
299 | }
300 |
301 | public String getTitle() {
302 | return title;
303 | }
304 |
305 | public void setTitle(String title) {
306 | this.title = title;
307 | }
308 |
309 | public String getText() {
310 | return text;
311 | }
312 |
313 | public void setText(String text) {
314 | this.text = text;
315 | }
316 |
317 | public String getBtnOrientation() {
318 | return btnOrientation;
319 | }
320 |
321 | public void setBtnOrientation(String btnOrientation) {
322 | this.btnOrientation = btnOrientation;
323 | }
324 |
325 | public String getSingleTitle() {
326 | return singleTitle;
327 | }
328 |
329 | public void setSingleTitle(String singleTitle) {
330 | this.singleTitle = singleTitle;
331 | }
332 |
333 | public String getSingleURL() {
334 | return singleURL;
335 | }
336 |
337 | public void setSingleURL(String singleURL) {
338 | this.singleURL = singleURL;
339 | }
340 |
341 | public List getBtns() {
342 | return btns;
343 | }
344 |
345 | public void setBtns(List btns) {
346 | this.btns = btns;
347 | }
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/model/feishu/FeiShuRequestBean.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.model.feishu;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * Created by center
9 | * 2021-09-04.
10 | */
11 | public class FeiShuRequestBean {
12 |
13 | @SerializedName("msg_type")
14 | private String msg_type;
15 | @SerializedName("content")
16 | private ContentDTO content;
17 | @SerializedName("card")
18 | private CardDTO card;
19 |
20 | public String getMsg_type() {
21 | return msg_type;
22 | }
23 |
24 | public void setMsg_type(String msg_type) {
25 | this.msg_type = msg_type;
26 | }
27 |
28 | public ContentDTO getContent() {
29 | return content;
30 | }
31 |
32 | public void setContent(ContentDTO content) {
33 | this.content = content;
34 | }
35 |
36 | public CardDTO getCard() {
37 | return card;
38 | }
39 |
40 | public void setCard(CardDTO card) {
41 | this.card = card;
42 | }
43 |
44 | public static class ContentDTO {
45 | @SerializedName("post")
46 | private PostDTO post;
47 |
48 | public PostDTO getPost() {
49 | return post;
50 | }
51 |
52 | public void setPost(PostDTO post) {
53 | this.post = post;
54 | }
55 |
56 | public static class PostDTO {
57 | @SerializedName("zh_cn")
58 | public ZhCnDTO zh_cn;
59 |
60 | public ZhCnDTO getZh_cn() {
61 | return zh_cn;
62 | }
63 |
64 | public void setZh_cn(ZhCnDTO zh_cn) {
65 | this.zh_cn = zh_cn;
66 | }
67 |
68 | public static class ZhCnDTO {
69 | @SerializedName("title")
70 | private String title;
71 | @SerializedName("content")
72 | private List> content;
73 |
74 | public String getTitle() {
75 | return title;
76 | }
77 |
78 | public void setTitle(String title) {
79 | this.title = title;
80 | }
81 |
82 | public List> getContent() {
83 | return content;
84 | }
85 |
86 | public void setContent(List> content) {
87 | this.content = content;
88 | }
89 |
90 | public static class ContentBean {
91 | @SerializedName("tag")
92 | private String tag;
93 | @SerializedName("text")
94 | private String text;
95 | @SerializedName("href")
96 | private String href;
97 | @SerializedName("user_id")
98 | private String user_id;
99 |
100 | public String getTag() {
101 | return tag;
102 | }
103 |
104 | public void setTag(String tag) {
105 | this.tag = tag;
106 | }
107 |
108 | public String getText() {
109 | return text;
110 | }
111 |
112 | public void setText(String text) {
113 | this.text = text;
114 | }
115 |
116 | public String getHref() {
117 | return href;
118 | }
119 |
120 | public void setHref(String href) {
121 | this.href = href;
122 | }
123 |
124 | public String getUser_id() {
125 | return user_id;
126 | }
127 |
128 | public void setUser_id(String user_id) {
129 | this.user_id = user_id;
130 | }
131 | }
132 | }
133 | }
134 |
135 | }
136 |
137 | public static class CardDTO {
138 | @SerializedName("config")
139 | private ConfigDTO config;
140 | @SerializedName("header")
141 | private HeaderDTO header;
142 | @SerializedName("elements")
143 | private List elements;
144 |
145 | public ConfigDTO getConfig() {
146 | return config;
147 | }
148 |
149 | public void setConfig(ConfigDTO config) {
150 | this.config = config;
151 | }
152 |
153 | public HeaderDTO getHeader() {
154 | return header;
155 | }
156 |
157 | public void setHeader(HeaderDTO header) {
158 | this.header = header;
159 | }
160 |
161 | public List getElements() {
162 | return elements;
163 | }
164 |
165 | public void setElements(List elements) {
166 | this.elements = elements;
167 | }
168 |
169 | public static class PostDTO {
170 | @SerializedName("zh_cn")
171 | public ZhCnDTO zh_cn;
172 |
173 | public ZhCnDTO getZh_cn() {
174 | return zh_cn;
175 | }
176 |
177 | public void setZh_cn(ZhCnDTO zh_cn) {
178 | this.zh_cn = zh_cn;
179 | }
180 |
181 | public static class ZhCnDTO {
182 | @SerializedName("title")
183 | private String title;
184 | @SerializedName("content")
185 | private List> content;
186 |
187 | public String getTitle() {
188 | return title;
189 | }
190 |
191 | public void setTitle(String title) {
192 | this.title = title;
193 | }
194 |
195 | public List> getContent() {
196 | return content;
197 | }
198 |
199 | public void setContent(List> content) {
200 | this.content = content;
201 | }
202 |
203 | public static class ContentBean {
204 | @SerializedName("tag")
205 | private String tag;
206 | @SerializedName("text")
207 | private String text;
208 | @SerializedName("href")
209 | private String href;
210 | @SerializedName("user_id")
211 | private String user_id;
212 |
213 | public String getTag() {
214 | return tag;
215 | }
216 |
217 | public void setTag(String tag) {
218 | this.tag = tag;
219 | }
220 |
221 | public String getText() {
222 | return text;
223 | }
224 |
225 | public void setText(String text) {
226 | this.text = text;
227 | }
228 |
229 | public String getHref() {
230 | return href;
231 | }
232 |
233 | public void setHref(String href) {
234 | this.href = href;
235 | }
236 |
237 | public String getUser_id() {
238 | return user_id;
239 | }
240 |
241 | public void setUser_id(String user_id) {
242 | this.user_id = user_id;
243 | }
244 | }
245 | }
246 | }
247 |
248 | public static class ConfigDTO {
249 | @SerializedName("wide_screen_mode")
250 | private boolean wide_screen_mode;
251 | @SerializedName("enable_forward")
252 | private boolean enable_forward;
253 |
254 | public boolean isWide_screen_mode() {
255 | return wide_screen_mode;
256 | }
257 |
258 | public void setWide_screen_mode(boolean wide_screen_mode) {
259 | this.wide_screen_mode = wide_screen_mode;
260 | }
261 |
262 | public boolean isEnable_forward() {
263 | return enable_forward;
264 | }
265 |
266 | public void setEnable_forward(boolean enable_forward) {
267 | this.enable_forward = enable_forward;
268 | }
269 | }
270 |
271 | public static class HeaderDTO {
272 | @SerializedName("title")
273 | private TextDTO title;
274 | /**
275 | * 颜色值
276 | *
277 | * blue
278 | * wathet
279 | * turquoise
280 | * green
281 | * yellow
282 | * orange
283 | * red
284 | * carmine
285 | * violet
286 | * purple
287 | * indigo
288 | * grey
289 | */
290 | @SerializedName("template")
291 | private String template;
292 |
293 | public TextDTO getTitle() {
294 | return title;
295 | }
296 |
297 | public void setTitle(TextDTO title) {
298 | this.title = title;
299 | }
300 |
301 | public String getTemplate() {
302 | return template;
303 | }
304 |
305 | public void setTemplate(String template) {
306 | this.template = template;
307 | }
308 | }
309 |
310 |
311 | }
312 |
313 | }
314 |
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/task/BaseTask.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.task;
2 |
3 |
4 | import com.android.build.gradle.api.BaseVariant;
5 | import com.google.gson.Gson;
6 |
7 | import net.center.upload_plugin.PluginConstants;
8 | import net.center.upload_plugin.PluginUtils;
9 | import net.center.upload_plugin.helper.CmdHelper;
10 | import net.center.upload_plugin.helper.HttpHelper;
11 | import net.center.upload_plugin.helper.SendMsgHelper;
12 | import net.center.upload_plugin.model.PgyCOSTokenResult;
13 | import net.center.upload_plugin.model.PgyUploadResult;
14 |
15 | import org.gradle.api.DefaultTask;
16 | import org.gradle.api.Project;
17 |
18 | import java.io.File;
19 | import java.util.Map;
20 | import java.util.concurrent.TimeUnit;
21 |
22 | import okhttp3.FormBody;
23 | import okhttp3.HttpUrl;
24 | import okhttp3.MediaType;
25 | import okhttp3.MultipartBody;
26 | import okhttp3.Request;
27 | import okhttp3.RequestBody;
28 | import okhttp3.Response;
29 |
30 | /**
31 | * Created by Android-ZX
32 | * 2021/9/3.
33 | */
34 | public class BaseTask extends DefaultTask {
35 |
36 | protected BaseVariant mVariant;
37 | protected Project mTargetProject;
38 |
39 | public void init(BaseVariant variant, Project project) {
40 | this.mVariant = variant;
41 | this.mTargetProject = project;
42 | setDescription(PluginConstants.TASK_DES);
43 | setGroup(PluginConstants.TASK_GROUP_NAME);
44 | }
45 |
46 | /**
47 | * 本接口上传速度很慢,即将废弃,强烈建议您使用 快速上传App 中的方式来替代。
48 | * https://www.pgyer.com/doc/view/api#fastUploadApp
49 | *
50 | * @param apiKey
51 | * @param appName
52 | * @param installType
53 | * @param buildPassword
54 | * @param buildUpdateDescription
55 | * @param buildInstallDate
56 | * @param buildChannelShortcut
57 | * @param apkFile
58 | */
59 | public void uploadPgyAndSendMessage(String apiKey, String appName, int installType, String buildPassword, String buildUpdateDescription, int buildInstallDate, String buildChannelShortcut, File apkFile) {
60 | //builder
61 | MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
62 | bodyBuilder.addFormDataPart("_api_key", apiKey);
63 | if (!PluginUtils.isEmpty(buildUpdateDescription)) {
64 | bodyBuilder.addFormDataPart("buildUpdateDescription", buildUpdateDescription);
65 | }
66 | if (installType != 1) {
67 | bodyBuilder.addFormDataPart("buildInstallType", installType + "");
68 | }
69 | if (installType == 2 && !PluginUtils.isEmpty(buildPassword)) {
70 | bodyBuilder.addFormDataPart("buildPassword", buildPassword);
71 | }
72 | bodyBuilder.addFormDataPart("buildInstallDate", buildInstallDate + "");
73 | if (!PluginUtils.isEmpty(buildChannelShortcut)) {
74 | bodyBuilder.addFormDataPart("buildChannelShortcut", buildChannelShortcut);
75 | }
76 | //add file
77 | bodyBuilder.addFormDataPart("file", apkFile.getName(), RequestBody
78 | .create(MediaType.parse("*/*"), apkFile));
79 | //request
80 | Request request = getRequestBuilder()
81 | .url("https://www.pgyer.com/apiv2/app/upload")
82 | .post(bodyBuilder.build())
83 | .build();
84 | try {
85 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
86 | if (response.isSuccessful() && response.body() != null) {
87 | String result = response.body().string();
88 | System.out.println("upload pgy result: " + result);
89 | if (!PluginUtils.isEmpty(result)) {
90 | PgyUploadResult uploadResult = new Gson().fromJson(result, PgyUploadResult.class);
91 | if (uploadResult.getCode() != 0) {
92 | System.out.println("upload pgy result error msg: " + uploadResult.getMessage());
93 | return;
94 | }
95 | if (uploadResult.getData() != null) {
96 | String url = "https://www.pgyer.com/" + uploadResult.getData().getBuildShortcutUrl();
97 | System.out.println("上传成功,应用链接: " + url);
98 | String gitLog = CmdHelper.checkGetGitParamsWithLog(mTargetProject);
99 | SendMsgHelper.sendMsgToDingDing(mVariant, mTargetProject, uploadResult.getData(), gitLog);
100 | SendMsgHelper.sendMsgToFeishu(mVariant, mTargetProject, uploadResult.getData(), gitLog);
101 | SendMsgHelper.sendMsgToWeiXinGroup(mVariant, mTargetProject, uploadResult.getData(), gitLog);
102 | } else {
103 | System.out.println("upload pgy result error : data is empty");
104 | }
105 | }
106 | } else {
107 | System.out.println("upload pgy failure");
108 | }
109 | System.out.println("******************* upload finish *******************");
110 | } catch (Exception e) {
111 | System.out.println("upload pgy failure " + e);
112 | }
113 | }
114 |
115 | /**
116 | * 快速上传方式 获取上传的 token
117 | *
118 | * @param apiKey
119 | * @param appName
120 | * @param installType
121 | * @param buildPassword
122 | * @param buildUpdateDescription
123 | * @param buildInstallDate
124 | * @param buildChannelShortcut
125 | * @param apkFile
126 | */
127 | public void uploadPgyQuickWay(String apiKey, String appName, int installType, String buildPassword, String buildUpdateDescription, int buildInstallDate, String buildChannelShortcut, File apkFile) {
128 | //builder
129 | MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
130 | bodyBuilder.addFormDataPart("_api_key", apiKey);
131 | bodyBuilder.addFormDataPart("buildType", "android");
132 | if (!PluginUtils.isEmpty(buildUpdateDescription)) {
133 | bodyBuilder.addFormDataPart("buildUpdateDescription", buildUpdateDescription);
134 | }
135 | if (installType != 1) {
136 | bodyBuilder.addFormDataPart("buildInstallType", installType + "");
137 | }
138 | if (installType == 2 && !PluginUtils.isEmpty(buildPassword)) {
139 | bodyBuilder.addFormDataPart("buildPassword", buildPassword);
140 | }
141 | bodyBuilder.addFormDataPart("buildInstallDate", buildInstallDate + "");
142 | if (!PluginUtils.isEmpty(buildChannelShortcut)) {
143 | bodyBuilder.addFormDataPart("buildChannelShortcut", buildChannelShortcut);
144 | }
145 | System.out.println("upload pgy --- 快速上传方式接口:Start getCOSToken");
146 | Request request = getRequestBuilder()
147 | .url("https://www.pgyer.com/apiv2/app/getCOSToken")
148 | .post(bodyBuilder.build())
149 | .build();
150 | try {
151 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
152 | if (response.isSuccessful() && response.body() != null) {
153 | String result = response.body().string();
154 | System.out.println("upload pgy --- getCOSToken result: " + result);
155 | if (!PluginUtils.isEmpty(result)) {
156 | PgyCOSTokenResult pgyCOSTokenResult = new Gson().fromJson(result, PgyCOSTokenResult.class);
157 | if (pgyCOSTokenResult.getCode() != 0 || pgyCOSTokenResult.getData() == null) {
158 | System.out.println("upload pgy --- getCOSToken result error msg: " + pgyCOSTokenResult.getMessage());
159 | return;
160 | }
161 | uploadFileToPgy(pgyCOSTokenResult, apkFile, apiKey);
162 | }
163 | } else {
164 | System.out.println("upload pgy ---- request getCOSToken call failed");
165 | }
166 | System.out.println("******************* getCOSToken: finish *******************");
167 | } catch (Exception e) {
168 | System.out.println("upload pgy ---- request getCOSToken call failed " + e);
169 | }
170 | }
171 |
172 | /**
173 | * 上传文件到第上一步获取的 URL
174 | *
175 | * @param tokenResult
176 | * @param apkFile
177 | * @param apiKey
178 | */
179 | private void uploadFileToPgy(PgyCOSTokenResult tokenResult, File apkFile, String apiKey) {
180 | if (PluginUtils.isEmpty(tokenResult.getData().getEndpoint())) {
181 | System.out.println("upload pgy --- endpoint url is empty");
182 | return;
183 | }
184 | if (tokenResult.getData().getParams() == null) {
185 | System.out.println("upload pgy --- endpoint params is empty");
186 | return;
187 | }
188 | //builder
189 | MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
190 | bodyBuilder.addFormDataPart("key", tokenResult.getData().getParams().getKey());
191 | bodyBuilder.addFormDataPart("signature", tokenResult.getData().getParams().getSignature());
192 | bodyBuilder.addFormDataPart("x-cos-security-token", tokenResult.getData().getParams().getXcossecuritytoken());
193 | //add file
194 | bodyBuilder.addFormDataPart("file", apkFile.getName(), RequestBody
195 | .create(MediaType.parse("*/*"), apkFile));
196 | System.out.println("upload pgy --- Start endpoint : " + tokenResult.getData().getEndpoint());
197 | Request request = getRequestBuilder()
198 | .url(tokenResult.getData().getEndpoint())
199 | .post(bodyBuilder.build())
200 | .build();
201 | try {
202 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
203 | System.out.println("upload pgy --- endpoint: upload apkFile to pgy response: " + response.isSuccessful());
204 | if (response.isSuccessful() && response.body() != null) {
205 | String result = response.body().string();
206 | System.out.println("upload pgy --- endpoint: upload apkFile to pgy result: " + result);
207 | // if (!PluginUtils.isEmpty(result)) {
208 | // BasePgyResult uploadResult = new Gson().fromJson(result, BasePgyResult.class);
209 | // if (uploadResult.getCode() != 204) {
210 | // System.out.println("endpoint: upload apkFile to pgy result error msg: " + uploadResult.getMessage());
211 | // return;
212 | // }
213 | // checkPgyUploadBuildInfo(apiKey, tokenResult.getData().getKey());
214 | // }
215 | checkPgyUploadBuildInfo(apiKey, tokenResult.getData().getKey());
216 | } else {
217 | System.out.println("upload pgy --- endpoint: upload apkFile to pgy result failure");
218 | }
219 | System.out.println("******************* endpoint: finish *******************");
220 | } catch (Exception e) {
221 | System.out.println("upload pgy --- endpoint: upload apkFile to pgy result failure " + e);
222 | }
223 | }
224 |
225 | /**
226 | * 检测应用是否发布完成,并获取发布应用的信息
227 | *
228 | * @param apiKey
229 | * @param buildKey 发布成功失败返回数据
230 | * code Integer 错误码,1216 应用发布失败
231 | * message String 信息提示
232 | *
233 | * 正在发布返回数据
234 | * code Integer 错误码,1246 应用正在发布中
235 | * message String 信息提示
236 | * 如果返回 code = 1246 ,可间隔 3s ~ 5s 重新调用 URL 进行检测,直到返回成功或失败。
237 | *
238 | * buildInfo: upload pgy buildInfo result: {"code":1247,"message":"App is uploded, please wait"}
239 | */
240 | private void checkPgyUploadBuildInfo(String apiKey, String buildKey) {
241 | // Map paramsMap = new HashMap<>(2);
242 | // paramsMap.put("_api_key", apiKey);
243 | // paramsMap.put("buildKey", buildKey);
244 | // String url = "https://www.pgyer.com/apiv2/app/buildInfo";
245 | // System.out.println("upload pgy --- Start buildInfo");
246 | // //request
247 | // Request request = getRequestBuilder("get", url, paramsMap)
248 | // .build();
249 | String url = "https://www.pgyer.com/apiv2/app/buildInfo?_api_key=" + apiKey + "&buildKey=" + buildKey;
250 | System.out.println("upload pgy --- Start buildInfo : " + url);
251 | Request request = getRequestBuilder()
252 | .url(url)
253 | .get()
254 | .build();
255 | try {
256 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
257 | if (response.isSuccessful() && response.body() != null) {
258 | String result = response.body().string();
259 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo result: " + result);
260 | if (!PluginUtils.isEmpty(result)) {
261 | PgyUploadResult uploadResult = new Gson().fromJson(result, PgyUploadResult.class);
262 | if (uploadResult.getCode() == 0) {
263 | if (uploadResult.getData() != null) {
264 | String apkDownUrl = "https://www.pgyer.com/" + uploadResult.getData().getBuildShortcutUrl();
265 | System.out.println("上传成功,应用链接: " + apkDownUrl);
266 | String gitLog = CmdHelper.checkGetGitParamsWithLog(mTargetProject);
267 | SendMsgHelper.sendMsgToDingDing(mVariant, mTargetProject, uploadResult.getData(), gitLog);
268 | SendMsgHelper.sendMsgToFeishu(mVariant, mTargetProject, uploadResult.getData(), gitLog);
269 | SendMsgHelper.sendMsgToWeiXinGroup(mVariant, mTargetProject, uploadResult.getData(), gitLog);
270 | } else {
271 | System.out.println("upload pgy --- buildInfo: upload pgy result error : data is empty");
272 | }
273 | } else if (uploadResult.getCode() == 1246 || uploadResult.getCode() == 1247) {
274 | //正在发布返回数据
275 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo code( " + uploadResult.getCode() + "):" + uploadResult.getMessage());
276 | // checkPgyUploadBuildInfo(apiKey, buildKey);
277 | pgyUploadBuildInfoTimer(apiKey, buildKey);
278 | } else {
279 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo result error msg: " + uploadResult.getMessage());
280 | }
281 | }
282 | } else {
283 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo result failure");
284 | }
285 | System.out.println("******************* buildInfo: finish *******************");
286 | } catch (Exception e) {
287 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo result failure " + e);
288 | }
289 | }
290 |
291 | private void pgyUploadBuildInfoTimer(String apiKey, String buildKey) {
292 | System.out.println("upload pgy --- buildInfo: upload pgy buildInfo request again(pgyUploadBuildInfoTimer)");
293 | // if (executorService == null) {
294 | // executorService = new ScheduledThreadPoolExecutor(1);
295 | // }
296 | // executorService.scheduleWithFixedDelay(() -> {
297 | // try {
298 | // checkPgyUploadBuildInfo(apiKey, buildKey);
299 | // } catch (Exception e) {
300 | // e.printStackTrace();
301 | // }
302 | // }, 0, 3, TimeUnit.SECONDS);
303 |
304 | // if (mTimer == null) {
305 | // mTimer = new Timer();
306 | // }
307 | // mTimer.schedule(new TimerTask() {
308 | // @Override
309 | // public void run() {
310 | // try {
311 | // System.out.println("buildInfo: upload pgy buildInfo request again");
312 | // checkPgyUploadBuildInfo(apiKey, buildKey);
313 | // } catch (Exception e) {
314 | // e.printStackTrace();
315 | // }
316 | // }
317 | // }, 3000);
318 | try {
319 | TimeUnit.SECONDS.sleep(3);
320 | // Thread.sleep(3000);
321 | checkPgyUploadBuildInfo(apiKey, buildKey);
322 | } catch (InterruptedException e) {
323 | e.printStackTrace();
324 | }
325 | }
326 |
327 |
328 | private Request.Builder getRequestBuilder() {
329 | return new Request.Builder()
330 | .addHeader("Connection", "Keep-Alive")
331 | .addHeader("Charset", "UTF-8");
332 | }
333 |
334 |
335 | private Request.Builder getRequestBuilder(String method, String url, Map params) {
336 | HttpUrl httpUrl = HttpUrl.parse(url);
337 | if (httpUrl == null) {
338 | return new Request.Builder();
339 | }
340 | HttpUrl.Builder httpBuilder = httpUrl.newBuilder();
341 | if (params != null) {
342 | for (Map.Entry param : params.entrySet()) {
343 | httpBuilder.addQueryParameter(param.getKey(), param.getValue());
344 | }
345 | }
346 | return new Request.Builder()
347 | .url(httpBuilder.build())
348 | .method(method, new FormBody.Builder().build())
349 | .addHeader("Connection", "Keep-Alive")
350 | .addHeader("Charset", "UTF-8");
351 | }
352 | }
--------------------------------------------------------------------------------
/app/src/main/java/net/center/upload_plugin/helper/SendMsgHelper.java:
--------------------------------------------------------------------------------
1 | package net.center.upload_plugin.helper;
2 |
3 | import com.android.build.gradle.api.BaseVariant;
4 |
5 | import net.center.upload_plugin.PluginUtils;
6 | import net.center.upload_plugin.model.DingDingRequestBean;
7 | import net.center.upload_plugin.model.PgyUploadResult;
8 | import net.center.upload_plugin.model.WXGroupRequestBean;
9 | import net.center.upload_plugin.model.feishu.ElementsDTO;
10 | import net.center.upload_plugin.model.feishu.FeiShuRequestBean;
11 | import net.center.upload_plugin.model.feishu.TextDTO;
12 | import net.center.upload_plugin.params.SendDingParams;
13 | import net.center.upload_plugin.params.SendFeishuParams;
14 | import net.center.upload_plugin.params.SendWeixinGroupParams;
15 |
16 | import org.gradle.api.Project;
17 |
18 | import java.util.ArrayList;
19 | import java.util.List;
20 |
21 | import groovy.json.JsonOutput;
22 | import okhttp3.MediaType;
23 | import okhttp3.Request;
24 | import okhttp3.RequestBody;
25 | import okhttp3.Response;
26 |
27 | public class SendMsgHelper {
28 |
29 | private static final String defaultTitle = "测试包";
30 | private static final String defaultText = "最新开发测试包已上传 ";
31 | private static final String defaultClickText = "点我进行下载";
32 | private static final String defaultLogTitle = "更新内容:\n ";
33 |
34 | /**
35 | * 发送消息到钉钉
36 | *
37 | * @param project
38 | * @param dataDTO
39 | */
40 | public static void sendMsgToDingDing(BaseVariant variant, Project project, PgyUploadResult.DataDTO dataDTO, String gitLog) {
41 | SendDingParams dingParams = SendDingParams.getDingParamsConfig(project);
42 | if (PluginUtils.isEmpty(dingParams.accessToken)) {
43 | System.out.println("send to Dingding failure:accessToken is empty");
44 | return;
45 | }
46 | String flavorStr = getFlavorInfo(variant);
47 | DingDingRequestBean requestBean = new DingDingRequestBean();
48 | String title = dingParams.contentTitle;
49 | if (PluginUtils.isEmpty(title)) {
50 | title = defaultTitle;
51 | }
52 | StringBuilder titleStr = new StringBuilder(dataDTO.getBuildName()).append(" V").append(dataDTO.getBuildVersion()).append(flavorStr).append(" ").append(title);
53 | String text = dingParams.contentText;
54 | if (PluginUtils.isEmpty(text)) {
55 | text = defaultText;
56 | }
57 | if ("markdown".equals(dingParams.msgtype)) {
58 | requestBean.setMsgtype("markdown");
59 | DingDingRequestBean.MarkDownDTO markDownBean = new DingDingRequestBean.MarkDownDTO();
60 | markDownBean.setTitle(titleStr.toString());
61 | StringBuilder contentStr = new StringBuilder("**").append(titleStr).append("** \n ").append(text).append(" ");
62 | contentStr.append("*").append(dataDTO.getBuildCreated()).append("*").append("\n");
63 | String clickTxt = dingParams.clickTxt;
64 | if (PluginUtils.isEmpty(clickTxt)) {
65 | clickTxt = defaultClickText;
66 | }
67 | contentStr.append("[").append(clickTxt).append("](https://www.pgyer.com/").append(dataDTO.getBuildShortcutUrl()).append(")\n");
68 | contentStr.append(".append(dataDTO.getBuildQRCodeURL()).append(")\n");
69 | if (!PluginUtils.isEmpty(gitLog) && dingParams.isSupportGitLog) {
70 | contentStr.append("### ").append(defaultLogTitle).append(gitLog);
71 | }
72 | markDownBean.setText(contentStr.toString());
73 | DingDingRequestBean.AtDTO atBean = new DingDingRequestBean.AtDTO();
74 | atBean.setIsAtAll(dingParams.isAtAll);
75 | requestBean.setAt(atBean);
76 | requestBean.setMarkdown(markDownBean);
77 | } else if ("actionCard".equals(dingParams.msgtype)) {
78 | requestBean.setMsgtype("actionCard");
79 | DingDingRequestBean.ActionCardDTO actionCardBean = new DingDingRequestBean.ActionCardDTO();
80 | actionCardBean.setTitle(titleStr.toString());
81 | StringBuilder contentStr = new StringBuilder("**").append(titleStr).append("** \n ").append(text).append(" ");
82 | contentStr.append("*").append(dataDTO.getBuildCreated()).append("*").append("\n");
83 | contentStr.append(".append(dataDTO.getBuildQRCodeURL()).append(")\n");
84 | if (!PluginUtils.isEmpty(gitLog) && dingParams.isSupportGitLog) {
85 | contentStr.append("### ").append(defaultLogTitle).append(gitLog);
86 | }
87 | actionCardBean.setText(contentStr.toString());
88 | //0:按钮竖直排列 1:按钮横向排列
89 | actionCardBean.setBtnOrientation("0");
90 | String clickTxt = dingParams.clickTxt;
91 | if (PluginUtils.isEmpty(clickTxt)) {
92 | clickTxt = defaultClickText;
93 | }
94 | actionCardBean.setSingleTitle(clickTxt);
95 | actionCardBean.setSingleURL("https://www.pgyer.com/" + dataDTO.getBuildShortcutUrl());
96 | requestBean.setActionCard(actionCardBean);
97 | } else {
98 | requestBean.setMsgtype("link");
99 | DingDingRequestBean.LinkDTO linkBean = new DingDingRequestBean.LinkDTO();
100 | StringBuilder contentStr = new StringBuilder(text).append(dataDTO.getBuildCreated());
101 | if (!PluginUtils.isEmpty(gitLog) && dingParams.isSupportGitLog) {
102 | contentStr.append("\n ").append(defaultLogTitle).append(gitLog);
103 | }
104 | linkBean.setText(contentStr.toString());
105 | linkBean.setTitle(titleStr.toString());
106 | linkBean.setPicUrl(dataDTO.getBuildQRCodeURL());
107 | linkBean.setMessageUrl("https://www.pgyer.com/" + dataDTO.getBuildShortcutUrl());
108 | requestBean.setLink(linkBean);
109 | }
110 |
111 |
112 | String json = JsonOutput.toJson(requestBean);
113 | System.out.println("send to Dingding request json:" + json);
114 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), json);
115 | Request request = new Request.Builder()
116 | .addHeader("Connection", "Keep-Alive")
117 | .addHeader("Charset", "UTF-8")
118 | .url("https://oapi.dingtalk.com/robot/send?access_token=" + dingParams.accessToken)
119 | .post(requestBody)
120 | .build();
121 | try {
122 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
123 | if (response.isSuccessful() && response.body() != null) {
124 | String result = response.body().string();
125 | System.out.println("send to Dingding result:" + result);
126 | } else {
127 | System.out.println("send to Dingding failure");
128 | }
129 | System.out.println("*************** sendMsgToDing finish ***************");
130 | } catch (Exception e) {
131 | System.out.println("send to Dingding failure " + e);
132 | }
133 | }
134 |
135 | /**
136 | * 发送消息到飞书
137 | *
138 | * @param project
139 | * @param dataDTO
140 | */
141 | public static void sendMsgToFeishu(BaseVariant variant, Project project, PgyUploadResult.DataDTO dataDTO, String gitLog) {
142 | SendFeishuParams feishuParams = SendFeishuParams.getFeishuParamsConfig(project);
143 | String webHookHostUrl = feishuParams.webHookHostUrl;
144 | if (PluginUtils.isEmpty(webHookHostUrl)) {
145 | System.out.println("send to feishu failure:webHookHostUrl is empty");
146 | return;
147 | }
148 | String flavorStr = getFlavorInfo(variant);
149 | String title = feishuParams.contentTitle;
150 | if (PluginUtils.isEmpty(title)) {
151 | title = defaultTitle;
152 | }
153 | StringBuilder titleStr = new StringBuilder(dataDTO.getBuildName()).append(" V").append(dataDTO.getBuildVersion()).append(flavorStr).append(" ").append(title);
154 | String text = feishuParams.contentText;
155 | if (PluginUtils.isEmpty(text)) {
156 | text = defaultText;
157 | }
158 | StringBuilder textStr = new StringBuilder("**").append(text).append("** ").append(dataDTO.getBuildCreated()).append(" \n");
159 | FeiShuRequestBean feiShuRequestBean = new FeiShuRequestBean();
160 | if ("interactive".equals(feishuParams.msgtype)) {
161 | FeiShuRequestBean.CardDTO cardDTO = new FeiShuRequestBean.CardDTO();
162 |
163 | feiShuRequestBean.setMsg_type("interactive");
164 | FeiShuRequestBean.CardDTO.ConfigDTO cardConfigBean = new FeiShuRequestBean.CardDTO.ConfigDTO();
165 | cardConfigBean.setWide_screen_mode(true);
166 | cardConfigBean.setEnable_forward(true);
167 | cardDTO.setConfig(cardConfigBean);
168 | FeiShuRequestBean.CardDTO.HeaderDTO cardHeaderBean = new FeiShuRequestBean.CardDTO.HeaderDTO();
169 | cardHeaderBean.setTemplate("green");
170 | TextDTO cardHeaderTitleBean = new TextDTO();
171 | cardHeaderTitleBean.setTag("plain_text");
172 | cardHeaderTitleBean.setContent("\uD83D\uDE18 " + titleStr);
173 | cardHeaderBean.setTitle(cardHeaderTitleBean);
174 | cardDTO.setHeader(cardHeaderBean);
175 | List elementsDTOList = new ArrayList<>();
176 | ElementsDTO elements1 = new ElementsDTO();
177 | elements1.setTag("div");
178 | TextDTO elements1TextBean = new TextDTO();
179 | elements1TextBean.setTag("lark_md");
180 | textStr.append("[").append(PluginUtils.isEmpty(feishuParams.clickTxt) ? defaultClickText : feishuParams.clickTxt)
181 | .append("]").append("(https://www.pgyer.com/").append(dataDTO.getBuildShortcutUrl()).append(")").append(" ");
182 | textStr.append("[查看下载二维码]").append("(").append(dataDTO.getBuildQRCodeURL()).append(")");
183 | if (feishuParams.isAtAll) {
184 | textStr.append(" \n").append("");
185 | }
186 | elements1TextBean.setContent(textStr.toString());
187 | elements1.setText(elements1TextBean);
188 | elementsDTOList.add(elements1);
189 | ElementsDTO elements2 = new ElementsDTO();
190 | elements2.setTag("hr");
191 | elementsDTOList.add(elements2);
192 | if (!PluginUtils.isEmpty(gitLog) && feishuParams.isSupportGitLog) {
193 | ElementsDTO elements3 = new ElementsDTO();
194 | elements3.setTag("div");
195 | TextDTO elements3TextBean = new TextDTO();
196 | elements3TextBean.setTag("lark_md");
197 | StringBuilder logStrBuilder = new StringBuilder("**").append(defaultLogTitle).append("**").append(gitLog);
198 | elements3TextBean.setContent(logStrBuilder.toString());
199 | elements3.setText(elements3TextBean);
200 | elementsDTOList.add(elements3);
201 | ElementsDTO elements4 = new ElementsDTO();
202 | elements4.setTag("hr");
203 | elementsDTOList.add(elements4);
204 | }
205 | ElementsDTO elements5 = new ElementsDTO();
206 | elements5.setTag("action");
207 | List actionsList = new ArrayList<>();
208 | ElementsDTO actionBtnDownBtn = new ElementsDTO();
209 | actionBtnDownBtn.setTag("button");
210 | actionBtnDownBtn.setType("primary");
211 | actionBtnDownBtn.setUrl("https://www.pgyer.com/" + dataDTO.getBuildShortcutUrl());
212 | TextDTO actionDownBtnText = new TextDTO();
213 | actionDownBtnText.setTag("plain_text");
214 | actionDownBtnText.setContent(PluginUtils.isEmpty(feishuParams.clickTxt) ? defaultClickText : feishuParams.clickTxt);
215 | actionBtnDownBtn.setText(actionDownBtnText);
216 | actionsList.add(actionBtnDownBtn);
217 |
218 | ElementsDTO actionBtnQRCodeBtn = new ElementsDTO();
219 | actionBtnQRCodeBtn.setTag("button");
220 | actionBtnQRCodeBtn.setType("primary");
221 | actionBtnQRCodeBtn.setUrl(dataDTO.getBuildQRCodeURL());
222 | TextDTO actionQRCodeBtnText = new TextDTO();
223 | actionQRCodeBtnText.setTag("plain_text");
224 | actionQRCodeBtnText.setContent("查看下载二维码");
225 | actionBtnQRCodeBtn.setText(actionQRCodeBtnText);
226 | actionsList.add(actionBtnQRCodeBtn);
227 | elements5.setActions(actionsList);
228 | elementsDTOList.add(elements5);
229 | cardDTO.setElements(elementsDTOList);
230 | feiShuRequestBean.setCard(cardDTO);
231 | } else {
232 | FeiShuRequestBean.ContentDTO contentDTO = new FeiShuRequestBean.ContentDTO();
233 |
234 | feiShuRequestBean.setMsg_type("post");
235 | FeiShuRequestBean.ContentDTO.PostDTO postDTO = new FeiShuRequestBean.ContentDTO.PostDTO();
236 |
237 | FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean contentBeanText = new FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean();
238 | contentBeanText.setTag("text");
239 | contentBeanText.setText(textStr.toString());
240 | FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean contentBeanA = new FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean();
241 | contentBeanA.setTag("a");
242 | contentBeanA.setText(PluginUtils.isEmpty(feishuParams.clickTxt) ? defaultClickText : feishuParams.clickTxt);
243 | contentBeanA.setHref("https://www.pgyer.com/" + dataDTO.getBuildShortcutUrl());
244 | List contentBeans = new ArrayList<>();
245 | contentBeans.add(contentBeanText);
246 | contentBeans.add(contentBeanA);
247 | if (feishuParams.isAtAll) {
248 | FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean contentBeanAt = new FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean();
249 | contentBeanAt.setTag("at");
250 | contentBeanAt.setUser_id("all");
251 | contentBeans.add(contentBeanAt);
252 | }
253 | List> zhCnContentList = new ArrayList<>();
254 | zhCnContentList.add(contentBeans);
255 | if (!PluginUtils.isEmpty(gitLog) && feishuParams.isSupportGitLog) {
256 | List contentGitLogBeans = new ArrayList<>();
257 | FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean contentGitLogBeanText = new FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO.ContentBean();
258 | contentGitLogBeanText.setTag("text");
259 | contentGitLogBeanText.setText("** " + defaultLogTitle + gitLog);
260 | contentGitLogBeans.add(contentGitLogBeanText);
261 | zhCnContentList.add(contentGitLogBeans);
262 | }
263 |
264 | FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO zhCnDTO = new FeiShuRequestBean.ContentDTO.PostDTO.ZhCnDTO();
265 | zhCnDTO.setTitle(titleStr.toString());
266 | zhCnDTO.setContent(zhCnContentList);
267 | postDTO.setZh_cn(zhCnDTO);
268 | contentDTO.setPost(postDTO);
269 | feiShuRequestBean.setContent(contentDTO);
270 | }
271 |
272 |
273 | /**
274 | * text 文本
275 | * post 富文本 发送富文本消息
276 | * image 图片 上传图片
277 | * share_chat 分享群名片 群名片
278 | * interactive 消息卡片 消息卡片消息
279 | */
280 | String json = JsonOutput.toJson(feiShuRequestBean);
281 | System.out.println("send to feishu request json:" + json);
282 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), json);
283 | Request request = new Request.Builder()
284 | .addHeader("Connection", "Keep-Alive")
285 | .addHeader("Charset", "UTF-8")
286 | .url(webHookHostUrl)
287 | .post(requestBody)
288 | .build();
289 | try {
290 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
291 | if (response.isSuccessful() && response.body() != null) {
292 | String result = response.body().string();
293 | System.out.println("send to feishu result:" + result);
294 | } else {
295 | System.out.println("send to feishu failure");
296 | }
297 | System.out.println("*************** sendMsgToFeishu finish ***************");
298 | } catch (Exception e) {
299 | System.out.println("send to feishu failure " + e);
300 | }
301 | }
302 |
303 | /**
304 | * 发送消息到微信群
305 | *
306 | * @param project
307 | * @param dataDTO
308 | */
309 | public static void sendMsgToWeiXinGroup(BaseVariant variant, Project project, PgyUploadResult.DataDTO dataDTO, String gitLog) {
310 | SendWeixinGroupParams weixinGroupParams = SendWeixinGroupParams.getWeixinGroupConfig(project);
311 | String webHookUrl = weixinGroupParams.webHookUrl;
312 | if (PluginUtils.isEmpty(webHookUrl)) {
313 | System.out.println("send to weixin group failure:webHookUrl is empty");
314 | return;
315 | }
316 | String flavorStr = getFlavorInfo(variant);
317 | String contentTitle = weixinGroupParams.contentTitle;
318 | if (PluginUtils.isEmpty(contentTitle)) {
319 | contentTitle = defaultTitle;
320 | }
321 | String contentText = weixinGroupParams.contentText;
322 | if (PluginUtils.isEmpty(contentText)) {
323 | contentText = defaultText;
324 | }
325 | WXGroupRequestBean wxGroupRequestBean = new WXGroupRequestBean();
326 | StringBuilder markStr = new StringBuilder();
327 | if ("text".equals(weixinGroupParams.msgtype)) {
328 | wxGroupRequestBean.setMsgtype("text");
329 | WXGroupRequestBean.TextDTO textDTO = new WXGroupRequestBean.TextDTO();
330 | markStr.append(dataDTO.getBuildName()).append(" V").append(dataDTO.getBuildVersion());
331 | markStr.append(flavorStr).append(contentTitle).append("\n").append("下载链接:https://www.pgyer.com/")
332 | .append(dataDTO.getBuildShortcutUrl()).append("\n").append(contentText);
333 | textDTO.setContent(markStr.toString());
334 | if (weixinGroupParams.isAtAll) {
335 | List mentionedList = new ArrayList<>();
336 | mentionedList.add("@all");
337 | textDTO.setMentioned_list(mentionedList);
338 | textDTO.setMentioned_mobile_list(mentionedList);
339 | }
340 | wxGroupRequestBean.setText(textDTO);
341 | } else if ("news".equals(weixinGroupParams.msgtype)) {
342 | wxGroupRequestBean.setMsgtype("news");
343 | WXGroupRequestBean.NewsDTO newsDTO = new WXGroupRequestBean.NewsDTO();
344 | WXGroupRequestBean.NewsDTO.ArticlesDTO articlesDTO = new WXGroupRequestBean.NewsDTO.ArticlesDTO();
345 | markStr.append(dataDTO.getBuildName()).append(" V").append(dataDTO.getBuildVersion());
346 | markStr.append(flavorStr).append(" ").append(dataDTO.getBuildCreated());
347 | articlesDTO.setTitle(markStr.toString());
348 | String desStr = "最新开发测试包已上传,请下载测试吧! ";
349 | if (!PluginUtils.isEmpty(contentTitle) && !PluginUtils.isEmpty(contentText)) {
350 | desStr = contentTitle + " \n" + contentText;
351 | } else if (!PluginUtils.isEmpty(contentTitle)) {
352 | desStr = contentTitle;
353 | } else if (!PluginUtils.isEmpty(contentText)) {
354 | desStr = contentText;
355 | }
356 | articlesDTO.setDescription(desStr);
357 | articlesDTO.setUrl("https://www.pgyer.com/" + dataDTO.getBuildShortcutUrl());
358 | articlesDTO.setPicurl(dataDTO.getBuildQRCodeURL());
359 | List articlesDTOList = new ArrayList<>();
360 | articlesDTOList.add(articlesDTO);
361 | newsDTO.setArticles(articlesDTOList);
362 | wxGroupRequestBean.setNews(newsDTO);
363 | } else {
364 | wxGroupRequestBean.setMsgtype("markdown");
365 | WXGroupRequestBean.MarkdownDTO markdownDTO = new WXGroupRequestBean.MarkdownDTO();
366 | markStr.append("**").append(dataDTO.getBuildName()).append("** V").append(dataDTO.getBuildVersion())
367 | .append(flavorStr).append(" ").append(dataDTO.getBuildCreated()).append(" \n")
368 | .append(contentTitle).append(" \n").append(contentText).append(" \n")
369 | .append("[下载链接,点击下载](https://www.pgyer.com/")
370 | .append(dataDTO.getBuildShortcutUrl()).append(")");
371 | if (!PluginUtils.isEmpty(gitLog) && weixinGroupParams.isSupportGitLog) {
372 | markStr.append(" \n").append("**").append(defaultLogTitle).append("**").append(gitLog);
373 | }
374 | markdownDTO.setContent(markStr.toString());
375 | wxGroupRequestBean.setMarkdown(markdownDTO);
376 | }
377 | String json = JsonOutput.toJson(wxGroupRequestBean);
378 | System.out.println("send to WeiXin group request json:" + json);
379 | RequestBody requestBody = RequestBody.create(MediaType.parse("application/json;charset=UTF-8"), json);
380 | Request request = new Request.Builder()
381 | .addHeader("Connection", "Keep-Alive")
382 | .addHeader("Charset", "UTF-8")
383 | .url(webHookUrl)
384 | .post(requestBody)
385 | .build();
386 | try {
387 | Response response = HttpHelper.getOkHttpClient().newCall(request).execute();
388 | if (response.isSuccessful() && response.body() != null) {
389 | String result = response.body().string();
390 | System.out.println("send to WeiXin group result:" + result);
391 | } else {
392 | System.out.println("send to WeiXin group failure");
393 | }
394 | System.out.println("*************** sendMsgToWeiXinGroup finish ***************");
395 | } catch (Exception e) {
396 | System.out.println("send to WeiXin group failure " + e);
397 | }
398 |
399 | }
400 |
401 | private static String getFlavorInfo(BaseVariant variant) {
402 | String flavor = PluginUtils.isEmpty(variant.getName()) ? variant.getFlavorName() : variant.getName();
403 | return PluginUtils.isEmpty(flavor) ? "" : "(FlavorName:" + flavor + ")";
404 | }
405 | }
406 |
--------------------------------------------------------------------------------