Skip to content

Instantly share code, notes, and snippets.

@tprochazka
Last active January 17, 2019 11:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tprochazka/457c7eebd044c0210dcc8ba49301cda9 to your computer and use it in GitHub Desktop.
Save tprochazka/457c7eebd044c0210dcc8ba49301cda9 to your computer and use it in GitHub Desktop.
Custom sign task implementation for Android Build Plugin compatible with build plugin 3.3.0 (with app bundle support)
import com.android.annotations.NonNull
import com.android.build.api.artifact.BuildableArtifact
import com.android.build.gradle.api.ApkVariant
import com.android.build.gradle.api.ApkVariantOutput
import com.google.common.io.Files
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputFiles
import org.gradle.api.tasks.TaskAction
import java.security.SecureRandom
import java.util.concurrent.TimeUnit
class RemoteSignTask extends DefaultTask {
@InputFiles
BuildableArtifact inputFiles
Collection<String> originalInputNames = new HashSet<>()
@OutputFiles
Collection<File> outputFiles
ApkVariant applicationVariant
@TaskAction
void sign() {
inputFiles.files.each { File file ->
if (file.isDirectory()) {
applicationVariant.outputs.each { ApkVariantOutput output ->
File artifact = new File(file, output.outputFileName)
localFileSign(artifact, artifact)
outputFiles.add(artifact)
}
} else {
localFileSign(file, renameToSignedName(file))
}
}
}
void localFileSign(File inputFile, File outputFile) {
// custom remote sign implementation.
}
static File renameToSignedName(File file) {
new File(file.parent, renameToSignedName(file.name))
}
static String renameToSignedName(String fileName) {
return fileName.replaceFirst("[,-]unsigned", "")
}
/**
* Class responsible for sign task configuration
*/
static class ConfigAction implements Action<RemoteSignTask> {
private final BuildableArtifact artifact
private final ApkVariant variant
ConfigAction(ApkVariant variant, BuildableArtifact artifact) {
this.variant = variant
this.artifact = artifact
}
@Override
@TaskAction
void execute(@NonNull RemoteSignTask signTask) {
signTask.inputFiles = artifact
signTask.applicationVariant = variant
signTask.outputFiles = new HashSet<>()
variant.outputs.all { ApkVariantOutput output ->
signTask.originalInputNames.add(output.outputFileName)
// hack to keep proper final name also when assemble task will be skipped
output.outputFileName = renameToSignedName(output.outputFileName)
}
variant.outputsAreSigned = true
}
}
}
import com.android.build.gradle.api.ApplicationVariant
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.internal.scope.InternalArtifactType
import com.android.builder.model.ProductFlavor
import org.gradle.api.Project
public class SignConfigurator {
/**
* Entry point to setup remote sign.
**/
static void configureReleaseBuildSign(Project project) {
if (!RemoteSignTask.checkConfig(project)) {
project.getLogger().warn "Remote sign is not possible"
return
}
project.android.applicationVariants.whenObjectAdded { ApplicationVariant variant ->
if (!isReleaseBuildType(variant)) {
return
}
// Regular APK signing
def apk = variant.getFinalArtifact(InternalArtifactType.APK)
def signTask = project.tasks.register(
"remoteSign" + variant.name.capitalize() + "Apk", RemoteSignTask,
new RemoteSignTask.ConfigAction(variant, apk))
variant.assembleProvider.configure {
dependsOn(signTask)
}
// App bundle signing
def bundle = variant.getFinalArtifact(InternalArtifactType.BUNDLE)
def bundleSignTask = project.tasks.register(
"remoteSign" + variant.name.capitalize() + "Bundle", RemoteSignTask,
new RemoteSignTask.ConfigAction(variant, bundle))
variant.getVariantData().getTaskContainer().bundleTask.configure {
it.dependsOn(bundleSignTask)
}
if (variant.testVariant != null ) {
// Test APK signing
def testApk = variant.testVariant.getFinalArtifact(InternalArtifactType.APK)
def testSignTask = project.tasks.register(
"remoteSign" + variant.name.capitalize() + "AndroidTest", RemoteSignTask,
new RemoteSignTask.ConfigAction(variant.testVariant, testApk))
variant.testVariant.assembleProvider.configure {
dependsOn(testSignTask)
}
variant.testVariant.connectedInstrumentTestProvider.configure {
dependsOn(testSignTask)
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment