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: [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 命令發佈本地.
-
項目引用
發佈本地成功以後,即可進行使用,在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" } }