El empaquetado frecuente durante la fase de desarrollo y prueba es demasiado aburrido, y el empaquetado y lanzamiento automáticos pueden liberarle las manos. En la sección anterior, analizamos el proceso de empaquetado y publicación Fastlane. Bueno, es un poco engorroso en general, y Android usa Fast Lane para empaquetar automáticamente materiales en línea. Hay relativamente pocos materiales en línea y es bastante difícil de resolver. problemas después de errores. Así que hoy usaremos una forma más sencilla de empaquetar y publicar automáticamente.
1. Gradle empaqueta y lanza automáticamente Dandelion
Documentación oficial de Dandelion Upload Apk
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)
}
}
Nota: Recuerde importar este archivo en el archivo build.gradle de la aplicación.
2. Notificación de grupo DingTalk
Documentación personalizada del robot DingTalk
1. Cree un robot DingTalk personalizado
Haga clic en el botón de configuración en la esquina superior derecha del grupo 打开群设置->智能群助手->添加机器人->自定义机器人->填写机器人名称和关键词
(al enviar un mensaje de grupo DingTalk después de la palabra clave aquí, el contenido del mensaje debe contener la palabra clave; de lo contrario, el envío no se realizará correctamente)
2. Acceder a la notificación del grupo DingTalk
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()
}
}
}
Busque el robot recién creado y abra
Copiar Webhook地址
para ver accessToken
los campos. A continuación, configuremos los parámetros que deben usarse.
群组消息类型
Puede consultar la documentación oficial y ajustarla según sus necesidades. Valores predeterminados para escribir el código link
.
3. Configuración relacionada
Abra build.gradle en el directorio raíz y complete el código:
ext {
android = [
versionCode: 1,
versionName: "1.0.0.0"
]
pgy = [
apiKey : "xxx",
uploadUrl : "https://www.pgyer.com/apiv2/app/upload"
]
dingding = [
accessToken: "xxx",
]
}
4. Imagen de efecto:
5. Modificación de errores de SSL
Recientemente, lo subí a la computadora (Windows) OpenSSL
y ocurrió un error en el cur
comando de llamada de carga automática.
curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x80092013)
causas del problema:
La versión de Windows curl
se basa en WinSSL / WinTLS
(es decir, el canal seguro de Microsoft, consulte https://msdn.microsoft.com/en-us/library/aa380123.aspx) para brindar compatibilidad con https, mientras que la versión de Linux de curl se basa en la openssl
versión de los dos funcionan de manera inconsistente.
Dado que la ventana estaba originalmente integrada ssh
, esta vez instalé OpenSSL nuevamente y supuse que había un conflicto entre los dos.
Solución:
Agregue --ssl-no-revoke
parámetros y 关闭证书吊销检查
funciones a curl, y el código de carga de curl modificado es el siguiente:
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. Buenas noticias @alguien
Documento oficial: https://open.dingtalk.com/document/group/robot-message-type-staff-information-in-an-enterprise
admite el mensaje Dingding @someone Hay tres formatos de mensaje: text
, markdown
, actioncard
. Solo text
se resaltará uno de ellos, los otros dos no.
//发送到群,@所有人
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)
}
Nota:
1. Hay dos formas de @alguien en el documento oficial, una es configurar a esta persona 钉钉userid
y la otra es configurar a esta persona 手机号
. La premisa es garantizar que el ID de usuario configurado o el número de teléfono móvil debe estar en este grupo. , de lo contrario no será válido.
2. El método de configuración de la identificación de usuario en el documento oficial es el siguiente atUserIds
. Después de la prueba, se encuentra que este elemento de configuración no es válido y debe cambiarse. atDingtalkIds
Tal vez se olvidó actualizar el documento.
3. at
Después de configurar la información que requiere @personas en , es obligatorio 在发送的消息中加上@xx
, de lo contrario @ no es válido.
text消息
:content
Empalme @xx enmarkdown消息
|actionCard消息
:text
empalme @xx en
4. atDingtalkIds
y atMobiles
se puede configurar al mismo tiempo.
5. Preste atención al método de configuración de matriz en gradle ([])
. No entiendo muy bien la gramática de groovy. Los estudiantes que quieran saber más al respecto pueden Baidu ellos mismos.