android插件开发,使用360加固自动多渠道打包

android插件开发,使用360加固自动多渠道打包

最近研究了一下安卓插件的开发,就以开发一个360加固自动打包插件为例,练了一下,本次使用android studio基于kotlin构建自动打包插件.

创建插件

  • 新建一个module,选择java\kotlin,姑且叫 JiaGuPlugin
    android插件开发,使用360加固自动多渠道打包_第1张图片

  • 添加依赖

    构建插件需要使用gradle依赖,build.gradle添加以下内容

     apply plugin: 'java-library'
    apply plugin: 'kotlin'
    apply plugin: 'groovy'
    
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
        implementation  gradleApi()
        implementation localGroovy()
        implementation 'com.android.tools.build:gradle:3.6.3'
    
    }
    tasks.withType(JavaCompile) {
        options.encoding = "UTF-8"
    }
    sourceCompatibility = "1.8"
    targetCompatibility = "1.8"
    
    //设置maven deployer,发布到指定目录
    apply plugin: 'maven'
    
    repositories {
        mavenCentral()
    }
    uploadArchives {
        repositories {
            mavenDeployer {
                //设置插件的GAV参数
                pom.groupId = 'com.mml.jiagu.plugin'
                pom.artifactId = '360'
                pom.version = '1.0.0'
                //文件发布到此模块repo下面目录
                repository(url: uri('repo'))
            }
        }
    }
    //发布到本地仓库
    apply plugin: 'maven-publish'
    publishing{
        publications{
            JiaGuPlugin(MavenPublication){
                 from components.java
                groupId 'com.mml.jiagu.plugin'
                artifactId '360'
                version '1.1'
            }
        }
    }
    
  • 创建一个配置扩展类

    用于存储360加固配置
    使用kotlin创建的bean 不能使用data class 创建,因为是final类型的,在实例化时将不能读取,故创建一个开放的普通类

    package com.mml.jiagu.plugin
    
    open class JiaGuPluginExtension {
    
        var jiaGuToolsPath: String? = null
        var username: String? = null
        var password: String? = null
        var keyStoreFile: String? = null
        var keyStorePassword: String? = null
        var keyAlias: String? = null
        var keyAliasPassword: String? = null
        var channelFile: String? = null
        var inputFile: String? = null
        var outputFile: String? = null
        var config:Array<String>? = null
    }
    
  • 创建 task

    创建执行的任务具体内容

    package com.mml.jiagu.plugin
    
    import org.gradle.api.DefaultTask
    import org.gradle.api.tasks.TaskAction
    import java.io.*
    import javax.inject.Inject
    
    /**
     * Author: Menglong Ma
     * Email: [email protected]
     * Date: 2020/4/24 18:30
     * Description: This is JiaGuTask
     * Package: com.mml.jiagu.plugin
     * Project: DeskTopPhotoView
     */
    //使用kotlin 需要声明类open
    open class JiaGuTask() : DefaultTask() {
        lateinit var apk: File
        lateinit var jiaGuPluginExtension: JiaGuPluginExtension
    	//@Inject task的入口
        @Inject
        constructor(apk: File, jiaGuPluginExtension: JiaGuPluginExtension) : this() {
            group = JiaGuPlugin.GROUP
            description = " 360 jiagu"
            this.apk = apk
            this.jiaGuPluginExtension = jiaGuPluginExtension
        }
    	//  @TaskAction 标注,双击执行这个任务时调用这个方法
        @TaskAction
        fun begin() {
        	//参照360加固文档编写相应的命令
            println("login 360 account")
            project.exec { execSpec ->
                execSpec.commandLine(
                    "java", "-jar", jiaGuPluginExtension.jiaGuToolsPath,
                    "-login", jiaGuPluginExtension.username, jiaGuPluginExtension.password
                )
            }
            println("import sign")
            project.exec { execSpec ->
                execSpec.commandLine(
                    "java",
                    "-jar",
                    jiaGuPluginExtension.jiaGuToolsPath,
                    "-importsign",
                    jiaGuPluginExtension.keyStoreFile,
                    jiaGuPluginExtension.keyStorePassword
                    ,
                    jiaGuPluginExtension.keyAlias,
                    jiaGuPluginExtension.keyAliasPassword
                )
            }
            jiaGuPluginExtension.channelFile?.let {
                println("import mulpkg")
                project.exec { execSpec ->
                    execSpec.commandLine(
                        "java", "-jar", jiaGuPluginExtension.jiaGuToolsPath,
                        "-importmulpkg", it
                    )
                }
            }
            jiaGuPluginExtension.config?.let {
                println("config ")
                project.exec { execSpec ->
                    execSpec.commandLine(
                        "java", "-jar", jiaGuPluginExtension.jiaGuToolsPath,
                        "--config", it
                    )
                }
            }
            println("origin apk.absolutePath:${apk.absolutePath}")
            println("source apk.absolutePath:${apk.parent}")
            project.exec { execSpec ->
                execSpec.commandLine(
                    "java", "-jar", jiaGuPluginExtension.jiaGuToolsPath,
                    "-jiagu",
                    jiaGuPluginExtension.inputFile ?: apk.absolutePath,
                    jiaGuPluginExtension.outputFile ?: apk.parent, "-autosign",
                    "${jiaGuPluginExtension.channelFile?.let { "-automulpkg" }}"
                )
            }
        }
    
    }
    
  • 创建plugin
    继承 Plugin 接口,实现apply方法
    main目录下创建插件配置,路径没有就创建,并且不可更改resources/META-INF/gradle-plugins/com.mml.jiagu.plugin.properties,其中com.mml.jiagu.plugin表示应用时的名字,如:apply plugin: 'com.mml.jiagu.plugin'

    //配置很简单,插件的全类名限定路径
     implementation-class=com.mml.jiagu.plugin.JiaGuPlugin
    
    //插件类
    package com.mml.jiagu.plugin
    
    
    import com.android.build.gradle.AppExtension
    import org.gradle.api.Plugin
    import org.gradle.api.Project
    
    
    public class JiaGuPlugin : Plugin<Project> {
        companion object {
            val GROUP = "JiaGu"
            //app build.gradle 中使用的名字 jiagu{xxx xxx}
            val EXTENSION_NAME = "jiagu"
        }
    
        private val taskMap = mutableMapOf<String,String>()
        override fun apply(project: Project) {
        //读取360加固配置
            val jiaGuPluginExtension = project.extensions
                .create(EXTENSION_NAME, JiaGuPluginExtension::class.java)
            val isResguard = project.plugins.hasPlugin("AndResGuard")
            project.afterEvaluate { project ->
                println("afterEvaluate ${jiaGuPluginExtension.jiaGuToolsPath}")
                val appExtension = project.extensions.getByType(AppExtension::class.java)
                appExtension.applicationVariants.all { applicationVariant ->
                    val flavorName= applicationVariant.flavorName
                    applicationVariant.outputs.all {
                        val outputFile = it.outputFile
                        //println("outputFile:${outputFile.absolutePath}")
                        val jiaGuName = "jiagu-${it.name}"
                        println("create task:$jiaGuName")
                        val jiaGuTask = project.tasks.create(
                            jiaGuName,
                            JiaGuTask::class.java,
                            outputFile,
                            jiaGuPluginExtension
                        )
                        val buildAndJiaGuName = "build-and-$jiaGuName"
                        println("create task:$buildAndJiaGuName")
                        taskMap[buildAndJiaGuName] = "assemble$flavorName"
                        val buildAndJiaGuTask = project.tasks.create(
                            buildAndJiaGuName,
                            JiaGuTask::class.java,
                            outputFile,
                            jiaGuPluginExtension
                        )
                        buildAndJiaGuTask.doFirst {
                            println("${it.name} doFirst")
                        }
                        buildAndJiaGuTask.doLast {
                            println("${it.name} doLast")
                        }
                        buildAndJiaGuTask.dependsOn("assemble$flavorName")
    
                    }
    
                }
            }
            project.tasks.whenTaskAdded {task ->
                println("whenTaskAdded:${task.name} dependsOn ${task.dependsOn}")
                val get=taskMap[task.name]
                get?.let {
                    println("task ${task.name} dependsOn $it")
                    task.dependsOn(it)
                }
    
            }
        }
    
    }
    
    

测试插件

  • 发布本地仓库

    编写完成插件,可在gradle命令集中发现以下命令publishing和upload,分别对应build.gradle里的两个发布本地任务,执行gradle 命令发布本地.
    android插件开发,使用360加固自动多渠道打包_第2张图片android插件开发,使用360加固自动多渠道打包_第3张图片
    android插件开发,使用360加固自动多渠道打包_第4张图片

  • 项目引用
    发布本地成功以后,即可进行使用,在project build.gradle中引用

       repositories {
            google()
            jcenter()
            //本地仓库
            mavenLocal()
            //指定仓库
            maven {
                url uri("JiaGuPlugin/repo")
            }
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:3.6.3'
            classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
            //引用相应仓库中的包
           // classpath 'com.mml.jiagu.plugin:360:1.0.0'
            classpath 'com.mml.jiagu.plugin:360:1.1'
    
        }
    
  • 在app build.gradle中使用插件
    添加以下带,构建完成以后会在项目任务集中发现jiagu任务
    android插件开发,使用360加固自动多渠道打包_第5张图片

    apply plugin: 'com.mml.jiagu.plugin'
    
    String os = "${project.rootDir.absolutePath}/BaseWheelsByKotlin/JiaGuPlugin/tools/${getJiaguJarFilePathByOs()}"
    jiagu {
        jiaGuToolsPath "${os}/jiagu.jar"
        username "XXX"
        password "XXX"
        keyStoreFile android.signingConfigs.release.storeFile.absolutePath
        keyStorePassword android.signingConfigs.release.storePassword
        keyAlias android.signingConfigs.release.keyAlias
        keyAliasPassword android.signingConfigs.release.keyPassword
        inputFile //"${buildDir.getAbsolutePath()}\\outputs\\apk\\release\\app-release.apk"
        outputFile //"${buildDir.getAbsolutePath()}\\jiagu" //这里指定的是输出文件夹
        config '-so', '-data', '-assets', '-string_obfus', '-so_private'
        channelFile "${os}/多渠道模板.txt"
    }
    
    String getJiaguJarFilePathByOs(){
        String osName = org.gradle.internal.os.OperatingSystem.current().getName();
        String osVersion = org.gradle.internal.os.OperatingSystem.current().getVersion();
        println "*** $osName $osVersion was detected."
    
        if (org.gradle.internal.os.OperatingSystem.current().isLinux()) {
            println("Linux")
            return "linux"+File.separator+"jiagu"
        } else if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
            println("Windows")
            return "windows"+File.separator+"jiagu"
        } else if (org.gradle.internal.os.OperatingSystem.current().isMacOsX()) {
            println("OSX")
            return "mac"+File.separator+"jiagu"
        }
    }
    

最后,放上demo链接

  • JiaGuPlugin

你可能感兴趣的:(Android,开发)