Gradle Custom Plugin Enviar Notificação Dingding

No artigo anterior, apresentamos como usar o plug-in Gradle, reforço de apk e upload para o Dandelion.

Este artigo é principalmente para melhorar ainda mais o processo, através do plug-in Gradle para alcançar: empacotamento - reforço - upload dandelion - enviar mensagem DingTalk , para alcançar a automação completa.

Introdução aos artigos anteriores:

Gradle Custom Plugin Introdução

Gradle Custom Plugin Upload APK para Dandelion

Reforço Gradle Custom Plugin 360

A seguir, vamos ver o processo simples de envio de notificações do DingTalk:

  • Crie um robô DingTalk. Obtenha credenciais para enviar mensagens.
  • Chame a API de acordo com o formato de dados exigido pelas credenciais e DingTalk

A documentação da API do DingTalk contém descrições detalhadas do processo, portanto não entrarei em detalhes aqui.

Desenvolver mensagem DingTalk Fluxo de tarefa da tarefa:

1. Crie um robô DingTalk

Para enviar mensagens DingTalk, precisamos criar um bot DingTalk no grupo DingTalk. Após criar o robô DingTalk, envie mensagens para o grupo DingTalk através do Webhook e segredo do robô.

1. Clique no assistente de grupo inteligente do grupo

insira a descrição da imagem aqui

2. Clique em Criar Robô

Clique para adicionar um robô (permissão pode ser necessária). Isso requer operação do computador. Depois de criar o robô, você obterá o Webhook e o segredo.
Esses dois parâmetros são o que precisamos para enviar dados.

insira a descrição da imagem aqui
Após a criação do robô, obtivemos o webhook e o secret, que são as credenciais para envio de mensagens DingTalk.
insira a descrição da imagem aqui

Após criar o robô, podemos chamar a API através das credenciais de acordo com a documentação da API do DingTalk . Aqui eu não uso o SDK oficial, mas envio mensagens pelo OKHttp de acordo com o formato do documento.

2. Crie uma tarefa Tarefa para enviar mensagens DingTalk

De acordo com a documentação, sabemos que para enviar o DingTalk, devemos passar os parâmetros: webhook, secret .
Em seguida, selecione diferentes parâmetros de acordo com o tipo de mensagem que enviamos, aqui usamos o tipo de link para enviar mensagens:

{
    "msgtype": "link", 
    "link": {
        "text": "这个即将发布的新版本,创始人xx称它为“红树林”。
而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是“红树林”?", 
        "title": "时代的火车向前开", 
        "picUrl": "", 
        "messageUrl": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI"
    }
}

Aqui vemos que precisamos fazer o upload: text, title, picUrl, messageUrl , os quatro parâmetros
picUrl, link messageUrl, devem ser obtidos após o upload para o Dandelion.

Nesse caso, precisamos que Extension adicione 4 parâmetros: webhook, secret, text, title . Os outros dois parâmetros (picUrl, messageUrl) precisam ser obtidos após o upload do Dandelion com sucesso.

Depois que os parâmetros acima estiverem prontos, precisamos apenas chamar a API por meio de OKHttp para concluir.

As preparações incluem:

  • Crie uma classe de modelo que atenda às necessidades do DingTalk
  • Adicionar parâmetros à extensão (os quatro parâmetros analisados ​​acima)
  • Obtenha o parâmetro Url após o upload do Dandelion com sucesso
  • Analisando os parâmetros da extensão
  • API de chamada para enviar mensagem DingTalk

1. Construa uma classe Model que atenda às necessidades do DingTalk

O envio do DingTalk é entregue através do Json, primeiro construímos o modelo que ele precisa

public static class DingTalkModel {

        public String picUrl;
        public String messageUrl;
        public String title;
        public String text;
    }

    public static class DingTalkRequest {

        public String msgtype = "link";
        public DingTalkModel link;

        public DingTalkRequest(DingTalkModel link) {
            this.link = link;
        }
    }

2. Adicione parâmetros à extensão

Existem principalmente quatro parâmetros aqui: credenciais de upload (webhook e segredo), parâmetros de envio de mensagem (título, conteúdo).

Adicione parâmetros à classe Extension.

public class Extension {


  public String uKey;
  public String apiKey;
  public String appName;

  //==========加固相关的信息
//指向加固的jar包
  public File reinforceJarFile;
  //登陆用户名
  public String reinforceUsername;
  //登陆密码
  public String reinforcePassword;
  //输出apk的目录
  public File outputFile;

  //dingding
  public String dingWebhook;
  public String dingSecret;
  public String title;
  public String content;

  public Extension() {
  }

  public Extension(String uKey, String apiKey, String appName, File reinforceJarFile,
      String reinforceUsername, String reinforcePassword, File outputFile,
      String dingWebhook, String dingSecret, String title, String content) {
    this.uKey = uKey;
    this.apiKey = apiKey;
    this.appName = appName;
    this.reinforceJarFile = reinforceJarFile;
    this.reinforceUsername = reinforceUsername;
    this.reinforcePassword = reinforcePassword;
    this.outputFile = outputFile;
    this.dingWebhook = dingWebhook;
    this.dingSecret = dingSecret;
    this.title = title;
    this.content = content;
  }

  public Extension(String uKey, String apiKey, String appName, File reinforceJarFile,
      String reinforceUsername, String reinforcePassword, File outputFile) {
    this.uKey = uKey;
    this.apiKey = apiKey;
    this.appName = appName;
    this.reinforceJarFile = reinforceJarFile;
    this.reinforceUsername = reinforceUsername;
    this.reinforcePassword = reinforcePassword;
    this.outputFile = outputFile;
  }
  public Extension(String appName, String uKey, String apiKey) {
    this.uKey = uKey;
    this.apiKey = apiKey;
    this.appName = appName;
  }
  public static Extension getConfig(Project project) {
    Extension extension = project.getExtensions().findByType(Extension.class);
    if (extension == null) {
      extension = new Extension();
    }
    return extension;
  }

}


3. Obtenha o parâmetro Url após fazer o upload do Dandelion com sucesso

Definimos propriedades estáticas na tarefa DingTalk. Quando a tarefa de upload do Dandelion for concluída, chame o método setData() para passar os parâmetros.

public class DingTalkTask extends DefaultTask {

    private static String sShotcutUrl, sQRCodeURL;
	...

    public static void setData(String shortcutUrl, String qrUrl) {
        sShotcutUrl = shortcutUrl;
        sQRCodeURL = qrUrl;
    }
}

4. Analisar os parâmetros da Extensão

Aqui está a preparação dos parâmetros antes da rede. Precisamos analisar os parâmetros necessários aqui e colocá-los na classe do modelo.

   private DingTalkModel initModel() {
        DingTalkModel model = new DingTalkModel();
        model.picUrl = sQRCodeURL;
        model.messageUrl = "http://www.pgyer.com/" + sShotcutUrl;
        Extension extension =Extension.getConfig(mTargetProject);
        model.title = extension.title;
        model.text = extension.content;

        mWebhook = extension.dingWebhook;
        mSecret = extension.dingSecret;
        return model;
    }

Crie aqui o modelo requerido pelo DingTalk e obtenha todos os parâmetros correspondentes.

5. Chame a API para enviar a mensagem DingTalk

Isso, chame diretamente usando OKHttp


    @TaskAction
    public void sendDingtalk() {
        DingTalkModel model = initModel();

        String url = createDingUrl();

        OkHttpClient okHttpClient = new OkHttpClient();
        Gson gson = new Gson();
        String json = gson.toJson(new DingTalkRequest(model));
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
            , json);
        Request request = new Request.Builder()
            .url(url)
            .post(requestBody)
            .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            System.out.println("send message result: " + response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * create dingtalk  url
     */
    private String createDingUrl() {
        Long timestamp = System.currentTimeMillis();
        return mWebhook + "&timestamp=" + timestamp + "&sign=" + createSign(timestamp, mSecret);
    }

   private String createSign(Long timestamp, String secret) {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = null;
        try {
            mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }


Neste ponto, nossa Tarefa DingTalk é criada. Poste o código completo.


public class DingTalkTask extends DefaultTask {

    private static String sShotcutUrl, sQRCodeURL;
    private BaseVariant mVariant;
    private Project mTargetProject;

    private String mWebhook;
    private String mSecret;

    public static class DingTalkModel {

        public String picUrl;
        public String messageUrl;
        public String title;
        public String text;
    }

    public static class DingTalkRequest {

        public String msgtype = "link";
        public DingTalkModel link;

        public DingTalkRequest(DingTalkModel link) {
            this.link = link;
        }
    }

    public void init(BaseVariant variant, Project project) {
        this.mVariant = variant;
        this.mTargetProject = project;
        setDescription("send message to ding talk");
        setGroup(TestJavaPlugin.PLUGIN_EXTENSION_NAME);
    }

    @TaskAction
    public void sendDingtalk() {
        DingTalkModel model = initModel();

        String url = createDingUrl();

        OkHttpClient okHttpClient = new OkHttpClient();
        Gson gson = new Gson();
        String json = gson.toJson(new DingTalkRequest(model));
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
            , json);
        Request request = new Request.Builder()
            .url(url)
            .post(requestBody)
            .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            System.out.println("send message result: " + response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * create dingtalk  url
     */
    private String createDingUrl() {
        Long timestamp = System.currentTimeMillis();
        return mWebhook + "&timestamp=" + timestamp + "&sign=" + createSign(timestamp, mSecret);
    }

    private DingTalkModel initModel() {
        DingTalkModel model = new DingTalkModel();
        model.picUrl = sQRCodeURL;
        model.messageUrl = "http://www.pgyer.com/" + sShotcutUrl;
        Extension extension =Extension.getConfig(mTargetProject);
        model.title = extension.title;
        model.text = extension.content;

        mWebhook = extension.dingWebhook;
        mSecret = extension.dingSecret;
        return model;
    }

    private String createSign(Long timestamp, String secret) {
        String stringToSign = timestamp + "\n" + secret;
        Mac mac = null;
        try {
            mac = Mac.getInstance("HmacSHA256");
            mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
            byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
            return URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static void setData(String shortcutUrl, String qrUrl) {
        sShotcutUrl = shortcutUrl;
        sQRCodeURL = qrUrl;
    }
}

3. Modifique e carregue a tarefa Dandelion Task

Conforme mencionado acima, após a conclusão do upload, precisamos passar a URL para a tarefa DingTalk Task.

public class PGYUploadTask extends DefaultTask {

    private BaseVariant mVariant;
    private Project mTargetProject;

    public static class PGYRequest {

        public String uKey;
        public String apiKey;
        //1,install by public 2,install by password 3,install by invite
        public String installType;
    }

    public void init(BaseVariant variant, Project project) {
        this.mVariant = variant;
        this.mTargetProject = project;
        setDescription("upload to pgy");
        setGroup(TestJavaPlugin.PLUGIN_EXTENSION_NAME);
    }

    @TaskAction
    public void uploadToPGY() {
        Extension extension = Extension.getConfig(mTargetProject);

        PGYRequest request = new PGYRequest();
        request.apiKey = extension.apiKey;
        request.uKey = extension.uKey;
        File apkDir = extension.outputFile;
        if (apkDir == null || !apkDir.exists()) {
            upload(request);
        } else {
            File[] files = apkDir.listFiles();
            if (files != null && files.length > 0) {
                upload(request.uKey, request.apiKey, files[0]);
            } else {
                upload(request);
            }
        }
    }

    private void upload(PGYRequest request) {
        for (BaseVariantOutput output : mVariant.getOutputs()) {
            File file = output.getOutputFile();
            if (file == null || !file.exists()) {
                throw new GradleException("apk file is not exist!");
            }
            upload(request.uKey, request.apiKey, file);
        }
    }

    private void upload(String ukey, String apiKey, File apkFile) {
        //builder
        MultipartBody.Builder bodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
        //add part
        bodyBuilder.addFormDataPart("uKey", ukey);
        bodyBuilder.addFormDataPart("_api_key", apiKey);
        //add file
        bodyBuilder.addFormDataPart("file", apkFile.getName(), RequestBody
            .create(MediaType.parse("*/*"), apkFile));

        //request

        Request request = new Request.Builder()
            .url("http://upload.pgyer.com/apiv1/app/upload")
            .post(bodyBuilder.build())
            .build();

        OkHttpClient client = new OkHttpClient();
        try {
            Response response = client.newCall(request).execute();
            String result = response.body().string();
            System.out.println("upload result: " + result);
            parseResult(result);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void parseResult(String result) {
        if (result == null || result.length() == 0) {
            throw new IllegalArgumentException("upload apk to PGY failed");
        }
        PGYResonpse data = new Gson().fromJson(result, PGYResonpse.class);
        if (data == null || data.code != 0) {
            throw new IllegalArgumentException("upload apk to PGY failed");
        }
        DingTalkTask.setData(data.data.appShortcutUrl, data.data.appQRCodeURL);
    }

    public static class PGYResonpse {

        public int code;
        public String message;
        public PGYDetail data;

        public static class PGYDetail {

            public String appShortcutUrl;
            public String appUpdated;
            public String appQRCodeURL;
            public String appVersion;
            public String appVersionNo;
            public String appIcon;

        }
    }

}

Aqui, primeiro crie a classe Model para os resultados retornados pelo Dandelion; depois de obter os resultados carregados do Dandelion, passe os dados para a tarefa DingTalk Task por meio do método DingTalkTask.setData().

Quarto, modifique as dependências das tarefas no plug-in Plugin

Aqui, é principalmente para modificar as dependências da tarefa no plug-in Plugin. Deixe a Tarefa do DingTalk depender da tarefa de upload do Dandelion, para que a notificação do DingTalk seja enviada após o upload ser bem-sucedido.

public class TestJavaPlugin implements Plugin<Project> {

    public static final String PLUGIN_EXTENSION_NAME = "uploadHelperJava";
    public static final String ANDROID_EXTENSION_NAME = "android";


    @Override
    public void apply(Project project) {
        project.getExtensions()
            .create(PLUGIN_EXTENSION_NAME, Extension.class);
        //项目编译完成后,回调
        project.afterEvaluate(new Action<Project>() {
            @Override
            public void execute(Project project) {
                DomainObjectSet<ApplicationVariant> appVariants = ((AppExtension) project
                    .getExtensions().findByName(ANDROID_EXTENSION_NAME)).getApplicationVariants();
                for (ApplicationVariant variant : appVariants) {
                    //release apk
                    if (variant.getBuildType().getName().equalsIgnoreCase("uploadRelease")) {
                        String variantName =
                            variant.getName().substring(0, 1).toUpperCase() + variant.getName()
                                .substring(1);

                        //create task
                        ReinforceTask reinforceTask = project.getTasks()
                            .create("reinforceFor" + variantName, ReinforceTask.class);
                        reinforceTask.init(variant, project);

                        PGYUploadTask uploadTask = project.getTasks()
                            .create("uploadJavaFor" + variantName, PGYUploadTask.class);
                        uploadTask.init(variant, project);

                        DingTalkTask talkTask = project.getTasks()
                            .create("dingTalkFor" + variantName, DingTalkTask.class);
                        talkTask.init(variant, project);

                        //depend on
                        variant.getAssembleProvider().get()
                            .dependsOn(project.getTasks().findByName("clean"));
                        reinforceTask.dependsOn(variant.getAssembleProvider().get());
                        uploadTask.dependsOn(reinforceTask);
                        talkTask.dependsOn(uploadTask);

                    }
                }
            }
        });
    }
}

Aqui, também criamos a Tarefa DingTalk. Em seguida, as dependências foram modificadas. Neste ponto, todo o nosso processo: empacotamento – fortalecimento – upload do Dandelion – envio de notificações do DingTalk está completo.

Cinco, ligue

O lançamento de plug-ins e a introdução de plug-ins foram mencionados em artigos anteriores (há um link no início), então não vou escrevê-los aqui.

Vejamos o build.gradle no módulo do aplicativo que precisa chamar o plug-in

apply plugin: 'com.android.application'

android {
    ......
    signingConfigs {
        release {
            storeFile file('xxx.jks')
            storePassword "xxx"
            keyAlias "xxx"
            keyPassword "xxx"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        uploadRelease {
            minifyEnabled false
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

......

apply plugin: 'com.liu.alone.plugin'
uploadHelperJava {
    appName = "测试APP"

    uKey = "xxxx"

    apiKey = "xxxx"

    //加固相关的信息
    reinforceJarFile = file("../libs/jiagu.jar")
    reinforceUsername = "18032793516"
    reinforcePassword = "san7758521"
    outputFile = file("${buildDir.getAbsolutePath()}\\jiagu")

    //钉钉,这里需要修改成自己的值
    dingWebhook = "https://oapi.dingtalk.com/robot/send?access_token=xxx"
    dingSecret= "xxx"
    title = "新版本APP上传完成"
    content="体验新版本APP,请到蒲公英下载"

}


Chamada de tarefa:

insira a descrição da imagem aqui

Resultado da impressão:

> Task :app:reinforceForUploadRelease
==============start JiaGu
....
任务完成_已签名


> Task :app:uploadJavaForUploadRelease
upload result: {"code":0,"message":"","data":{"appKey":"3e95fe0e7fa74e9f7a310bbdfbd139cc","userKey":"c9d2625c0cf221d8f4a98738f4c05e9a","appType":"2","appIsLastest":"2","appFileSize":"3264349","appName":"PluginTest","appVersion":"1.0","appVersionNo":"1","appBuildVersion":"4","appIdentifier":"com.liu.plugintest","appIcon":"9664daaa8a725f726bcb6018495f14a7","appDescription":"","appUpdateDescription":"","appScreenshots":"","appShortcutUrl":"DqmH","appCreated":"2020-01-03 12:21:24","appUpdated":"2020-01-03 12:21:24","appQRCodeURL":"http:\/\/www.pgyer.com\/app\/qrcodeHistory\/9c27fd62288ce774fafb622d8f6df0bbcd9f90cf0b9ba39846c1c6864c93b135"}}

> Task :app:dingTalkForUploadRelease
send message result: {"errcode":0,"errmsg":"ok"}

Aqui, vemos que três tarefas foram executadas sucessivamente: Task :app:reinforceForUploadRelease, Task :app:uploadJavaForUploadRelease, Task :app:dingTalkForUploadRelease

Finalmente, notificação DingTalk
insira a descrição da imagem aqui

Neste ponto, todo o nosso processo automatizado de lançamentos de teste: empacotamento — reforço — upload do Dandelion — envio de notificações DingTalk é realizado personalizando o plug-in Gradle.

outros documentos

plugin-build.gradle

apply plugin: 'java-library'
apply plugin: 'maven'
dependencies {
    compile gradleApi()
    compile localGroovy()
    compile 'com.android.tools.build:gradle:3.3.1'
    implementation("com.squareup.okhttp3:okhttp:3.8.1")
}
repositories {
    mavenCentral()

}

group = 'com.liu.alone.plugin'
version = '1.0.0'
archivesBaseName = 'java-plugin'
//
//upload
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: uri('../repo'))
        }
    }
}

Acho que você gosta

Origin blog.csdn.net/ecliujianbo/article/details/103818432
Recomendado
Clasificación