Frequent packaging during the development and testing phase is too boring, and automatic packaging and release can free your hands. In the previous section, we analyzed the process of fastlane packaging and publishing. Well, it is a bit cumbersome in general, and Android uses fast lane to automatically package online materials. There are relatively few online materials, and it is quite difficult to solve problems after errors. So today we will use a simpler way to automatically package and publish.
1. Gradle automatically packages and releases Dandelion
Dandelion Upload Apk Official Documentation
apply from: './dingding.gradle'//引用钉钉通知方法
def apkFileName = "${
buildTime()}_test_v${rootProject.ext.android["versionName"]}_release.apk"
def apkFilePath = "${
projectDir.absolutePath}/build/outputs/apk/test/release/${
apkFileName}"
private def uploadPGY(String filePath) {
def stdout = new ByteArrayOutputStream()
exec {
executable = 'curl'
args = ['-F', "file=@${
filePath}", '-F', "_api_key=${rootProject.ext.pgy["apiKey"]}", rootProject.ext.pgy["uploadUrl"]]
standardOutput = stdout
}
String output = stdout.toString()
def parsedJson = new groovy.json.JsonSlurper().parseText(output)
println parsedJson.data.buildQRCodeURL
println "蒲公英上传完成 版本号:" + parsedJson.data.buildVersion
println "开始发送钉钉群通知"
def downloadUrl = "https://www.pgyer.com/" + parsedJson.data.buildShortcutUrl
postDingMsg(parsedJson.data.buildQRCodeURL, downloadUrl)
}
task uploadApk(dependsOn: '打包Task名称') {
//可以从Gradle的Task列表中选取,也可以点击查看Generate Signed Bundle/Apk执行的task是什么,复制出来就好了
group = "publish"//GradleTask列表中会生成一个publish的分组,里面包含uploadApk,后续只要点击这个uploadTask任务就可以自动打包发布了
doLast {
println "打包完成: ${
apkFilePath}"
println "开始上传蒲公英"
uploadPGY(apkFilePath)
}
}
Note: Remember to import this file in the app's build.gradle.
2. DingTalk group notification
Custom DingTalk Robot Documentation
1. Create a custom DingTalk robot
Click the setting button in the upper right corner of the group 打开群设置->智能群助手->添加机器人->自定义机器人->填写机器人名称和关键词
(when sending a DingTalk group message after the keyword here, the message content must contain the keyword, otherwise the sending will not be successful)
2. Access DingTalk group notification
import groovy.json.JsonBuilder
import groovy.json.JsonOutput
def dingDingUrl = "https://oapi.dingtalk.com/robot/send?access_token=${rootProject.ext.dingding["accessToken"]}"
ext.postDingMsg = {
String qrcodeUrl, String downloadUrl ->
String allTips =
"版本号:V${rootProject.ext.android["versionName"]}\n" +
"下载地址:${
downloadUrl}\n"
postAll(dingDingUrl, allTips, qrcodeUrl, downloadUrl)
}
//发送到群,@所有人
def postAll(url, tips, qrcodeUrl, downloadUrl) {
JsonBuilder builder = new JsonBuilder()
builder {
msgtype 'link'
link {
title '新版本发布提醒'
text tips
messageUrl downloadUrl
picUrl qrcodeUrl
}
at {
isAtAll false //@所有人(只有text,markdown,actioncard这三种消息类型支持@功能)
}
}
String data = JsonOutput.prettyPrint(builder.toString())
postDingDing(url, data)
}
//调用接口,发送消息
def postDingDing(urlString, msg) {
if (msg == null) {
return
}
HttpURLConnection conn = null
OutputStream outputStream = null
try {
if (conn == null) {
URL url = new URL(urlString)
conn = (HttpURLConnection) url.openConnection()
}
if (conn != null) {
conn.setReadTimeout(15000)
conn.setConnectTimeout(15000)
conn.setDoOutput(true)
conn.setUseCaches(false)
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8")
}
if (conn == null) {
return null
}
if (msg != null && msg.length() > 0) {
DataOutputStream dataOutputStream = new DataOutputStream(conn.getOutputStream())
byte[] t = msg.getBytes("utf-8")
dataOutputStream.write(t)
dataOutputStream.flush()
dataOutputStream.close()
int res = conn.getResponseCode()
if (res == 200) {
//成功
InputStream input = conn.getInputStream()
StringBuffer sb = new StringBuffer()
int ss
while ((ss = input.read()) != -1) {
sb.append((char) ss)
}
println "发送消息成功: ${
sb.toString()}"
} else {
println("发送消息失败: " + conn.getResponseCode())
}
}
} catch (EOFException e) {
e.printStackTrace()
} catch (IOException e) {
e.printStackTrace()
} finally {
if (outputStream != null) {
try {
outputStream.close()
} catch (IOException e) {
e.printStackTrace()
}
}
if (conn != null) {
conn.disconnect()
}
}
}
Find the newly created robot and open
Copy Webhook地址
to see accessToken
the fields. Next, let's configure the parameters that need to be used.
群组消息类型
You can refer to the official documentation and adjust it according to your needs. Defaults to type in code link
.
3. Related configuration
Open build.gradle in the root directory and fill in the code:
ext {
android = [
versionCode: 1,
versionName: "1.0.0.0"
]
pgy = [
apiKey : "xxx",
uploadUrl : "https://www.pgyer.com/apiv2/app/upload"
]
dingding = [
accessToken: "xxx",
]
}
4. Effect picture:
5. SSL bug modification
Recently, I uploaded it to the computer (windows) OpenSSL
, and an error occurred in the automatic upload cur
call command.
curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x80092013)
problem causes:
The windows version curl
relies on WinSSL / WinTLS
(that is, Microsoft's Secure Channel, see https://msdn.microsoft.com/en-us/library/aa380123.aspx ) to provide https support, while the Linux version of curl relies on the openssl
version of the two. perform inconsistently.
Since the window was originally built-in ssh
, this time I installed OpenSSL again and guessed that there was a conflict between the two.
Solution:
Add --ssl-no-revoke
parameters and 关闭证书吊销检查
functions to curl, and the modified curl upload code is as follows:
private def uploadPGY(String filePath) {
def stdout = new ByteArrayOutputStream()
exec {
executable = 'curl'
args = ['--ssl-no-revoke','-F', "file=@${
filePath}", '-F', "_api_key=${rootProject.ext.pgy["apiKey"]}", rootProject.ext.pgy["uploadUrl"]]
standardOutput = stdout
}
String output = stdout.toString()
def parsedJson = new groovy.json.JsonSlurper().parseText(output)
println parsedJson.data.buildQRCodeURL
println "蒲公英上传完成 版本号:" + parsedJson.data.buildVersion
}
6. Dingding news @someone
Official document: https://open.dingtalk.com/document/group/robot-message-type-staff-information-in-an-enterprise
supports Dingding message @someone There are three message formats: text
, markdown
, actioncard
. Only one of them text
will be highlighted, the other two will not.
//发送到群,@所有人
def postAtSomeone(url, tips, qrcodeUrl, downloadUrl) {
//发送@某人消息
JsonBuilder atPersonBuilder = new JsonBuilder()
atPersonBuilder {
msgtype 'text'
text {
content "更新内容:\n${rootProject.ext.android["versionUpdateRemark"]}\n" +
"@zfndm1v81"
}
at {
isAtAll false //@所有人
atDingtalkIds (["zfndm1v81"])//打开钉钉群,找到要@的人,复制他的钉钉号即可
//atMobiles (["135********"])
}
}
String personData = JsonOutput.prettyPrint(atPersonBuilder.toString())
postDingDing(url, personData)
}
Note:
1. There are two ways to @someone in the official document, one is to configure this person 钉钉userid
, and the other is to configure this person 手机号
. The premise is to ensure that the configured userid or mobile phone number must be in this group, otherwise it will be invalid.
2. The configuration method of the user id in the official document is as atUserIds
follows. After testing, it is found that this configuration item is invalid, and it needs to be changed. atDingtalkIds
Maybe the document has been forgotten to be updated.
3. at
After configuring the information that requires @people in , it is required 在发送的消息中加上@xx
, otherwise @ is invalid.
text消息
:content
Splice @xx inmarkdown消息
|actionCard消息
:text
splice @xx in
4. atDingtalkIds
and atMobiles
can be configured at the same time.
5. Pay attention to the array configuration method in gradle ([])
. I don't understand the grammar of groovy very well. Students who want to know more about it can Baidu it themselves.