1
+ import com.android.build.api.artifact.ArtifactTransformationRequest
2
+ import com.android.build.api.dsl.ApkSigningConfig
3
+ import com.android.builder.internal.packaging.IncrementalPackager
4
+ import com.android.tools.build.apkzlib.sign.SigningExtension
5
+ import com.android.tools.build.apkzlib.sign.SigningOptions
6
+ import com.android.tools.build.apkzlib.zfile.ZFiles
7
+ import com.android.tools.build.apkzlib.zip.ZFileOptions
8
+ import org.gradle.api.DefaultTask
9
+ import org.gradle.api.file.DirectoryProperty
10
+ import org.gradle.api.provider.Property
11
+ import org.gradle.api.tasks.Input
12
+ import org.gradle.api.tasks.InputFiles
13
+ import org.gradle.api.tasks.Internal
14
+ import org.gradle.api.tasks.OutputDirectory
15
+ import org.gradle.api.tasks.TaskAction
16
+ import java.io.File
17
+ import java.security.KeyStore
18
+ import java.security.cert.X509Certificate
19
+ import java.util.jar.JarFile
20
+
21
+ abstract class AddCommentTask : DefaultTask () {
22
+ @get:Input
23
+ abstract val comment: Property <String >
24
+
25
+ @get:Input
26
+ abstract val signingConfig: Property <ApkSigningConfig >
27
+
28
+ @get:InputFiles
29
+ abstract val apkFolder: DirectoryProperty
30
+
31
+ @get:OutputDirectory
32
+ abstract val outFolder: DirectoryProperty
33
+
34
+ @get:Internal
35
+ abstract val transformationRequest: Property <ArtifactTransformationRequest <AddCommentTask >>
36
+
37
+ @TaskAction
38
+ fun taskAction () = transformationRequest.get().submit(this ) { artifact ->
39
+ val inFile = File (artifact.outputFile)
40
+ val outFile = outFolder.file(inFile.name).get().asFile
41
+
42
+ val privateKey = signingConfig.get().getPrivateKey()
43
+ val signingOptions = SigningOptions .builder()
44
+ .setMinSdkVersion(0 )
45
+ .setV1SigningEnabled(true )
46
+ .setV2SigningEnabled(true )
47
+ .setKey(privateKey.privateKey)
48
+ .setCertificates(privateKey.certificate as X509Certificate )
49
+ .setValidation(SigningOptions .Validation .ASSUME_INVALID )
50
+ .build()
51
+ val options = ZFileOptions ().apply {
52
+ noTimestamps = true
53
+ autoSortFiles = true
54
+ }
55
+ outFile.parentFile?.mkdirs()
56
+ inFile.copyTo(outFile, overwrite = true )
57
+ ZFiles .apk(outFile, options).use {
58
+ SigningExtension (signingOptions).register(it)
59
+ it.eocdComment = comment.get().toByteArray()
60
+ it.get(IncrementalPackager .APP_METADATA_ENTRY_PATH )?.delete()
61
+ it.get(IncrementalPackager .VERSION_CONTROL_INFO_ENTRY_PATH )?.delete()
62
+ it.get(JarFile .MANIFEST_NAME )?.delete()
63
+ }
64
+
65
+ outFile
66
+ }
67
+
68
+ private fun ApkSigningConfig.getPrivateKey (): KeyStore .PrivateKeyEntry {
69
+ val keyStore = KeyStore .getInstance(storeType ? : KeyStore .getDefaultType())
70
+ storeFile!! .inputStream().use {
71
+ keyStore.load(it, storePassword!! .toCharArray())
72
+ }
73
+ val keyPwdArray = keyPassword!! .toCharArray()
74
+ val entry = keyStore.getEntry(keyAlias!! , KeyStore .PasswordProtection (keyPwdArray))
75
+ return entry as KeyStore .PrivateKeyEntry
76
+ }
77
+ }
0 commit comments