I have an android application that Im trying to sign an apk with a custom task after my build process runs. Ive gotten to the point where I have the task running after the fact but in the console I get the following error:
Error: Invalid command syntax
java -jar apksigtool.jar <apk-file> <private-key-file-der-format> <certificate-x509-file>
Now I can run this executable from the command line no problem but I havent been able to run the task after the apk files are generated by the build file.
What Im trying to accomplish using the build.gradle file is:
create an unsigned apk sign the apk with the jar file using my cert then have the build process sign and zipalign the apk
This is what I have so far
import java.text.SimpleDateFormat
import java.util.regex.Pattern
apply plugin: 'com.android.application'
def buildTime() {
def df = new SimpleDateFormat("yyyyMMdd'-'HHmm")
df.setTimeZone(TimeZone.getDefault())
return df.format(new Date())
}
def apkName = "MyApp"
def apkLocation
task (runApkSigTool , dependsOn: android, type: JavaExec) {
classpath files('apksigtool.jar')
main 'com.widevine.tools.android.apksigtool.ApkSigTool'
args[0] = apkLocation
args[1] = 'private_key.der'
args[2] = 'my.crt'
System.out.println(apkLocation);
}
android {
compileSdkVersion 19
buildToolsVersion "19.1.0"
signingConfigs{
debug{
storeFile file("debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
release{
storeFile file("debug.keystore")
storePassword "android"
keyAlias "androiddebugkey"
keyPassword "android"
}
}
buildTypes {
debug{
}
release {
signingConfig signingConfigs.release
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
assembleDebug.doLast{
runApkSigTool.execute()
}
zipAlign true
}
debug{
signingConfig signingConfigs.debug
runProguard false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
assembleDebug.doLast{
runApkSigTool.execute()
}
zipAlign false
}
android.applicationVariants.all { variant ->
def manifestFile = file("C:\\path\\app\\src\\main\\AndroidManifest.xml")
def pattern = Pattern.compile("versionName=\"(.+)\"")
def manifestText = manifestFile.getText()
def matcher = pattern.matcher(manifestText)
matcher.find()
def versionName = matcher.group(1)
pattern = Pattern.compile("versionCode=\"(.+)\"")
matcher = pattern.matcher(manifestText)
matcher.find()
def versionCode = matcher.group(1)
if (variant.zipAlign) {
variant.outputFile = new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime()+"-unaligned.apk");
variant.zipAlign.inputFile = variant.outputFile
variant.zipAlign.outputFile = new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime()+".apk");
} else {
apkLocation = "apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime()+".apk";
variant.outputFile = new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime()+".apk");
System.out.println("CREATED UNSIGNED APK---------------")
}
}
}
lintOptions {
abortOnError false
ignoreWarnings true
checkAllWarnings false
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.android.support:mediarouter-v7:20.0.0'
compile 'com.google.android.gms:play-services:5.0.89'
}
I can also see that the task runs a first time before anything gets set for my definition of apkLocation. Another thing is I have no idea if Im actually using the arguments correctly in my task to run the jar file in the first place. There really isnt any readily available documentation that just gets to the point of doing what I need to accomplish so hopefully some one can help.
UPDATE I found the root in my project where the apk files are ending up. But When I use the run button to just do debug builds I see that its trying to install the apk from the wrong path.
Second Update
Ive replaced some of the build file to this
if (variant.zipAlign) {
def buildTime = buildTime();
new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+"-unaligned.apk");
variant.outputFile = file("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+"-unaligned.apk");
variant.zipAlign.inputFile = variant.outputFile
new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+".apk");
variant.zipAlign.outputFile = file("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+".apk");
} else {
def buildTime = buildTime();
new File("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+".apk");
apkLocation = projectRoot+"apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+".apk";
variant.outputFile = file("apk/"+apkName+"-V"+versionName+"-"+versionCode+"-"+variant.name+"-"+buildTime+".apk");
System.out.println("CREATED UNSIGNED APK---------------")
}
This is giving me the exact outcome which allows me to create the apk and place it in the file within my projects root. That way when I use the play button to launch it onto a device studio has a context to the file path and doesnt use some wacky one that doesnt exist.