android插件开发,使用360加固自动多渠道打包
最近研究了一下安卓插件的开发,就以开发一个360加固自动打包插件为例,练了一下,本次使用android studio基于kotlin构建自动打包插件.
创建插件
-
新建一个module,选择java\kotlin,姑且叫 JiaGuPlugin
-
添加依赖
构建插件需要使用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: mml2015@126.com * 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 命令发布本地.
-
项目引用
发布本地成功以后,即可进行使用,在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任务
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" } }