0

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.

James andresakis
  • 5,335
  • 9
  • 53
  • 88
  • "I can also see that the task runs a first time before anything gets set for my definition of apkLocation" how have you verified that? – Rene Groeschke Sep 23 '14 at 07:41
  • In general you should never call task#execute() as this is internal gradle api. instead you should define a task dependency using runApkSigTool#dependsOn(assembleDebug). Also use file() method to create file objects instead of new File() as file() always works relativ to your project directory an 'new File()' doesn't – Rene Groeschke Sep 23 '14 at 07:46
  • I use system.out.println to put messages in the console as the build runs so I can see my task run before the rest of the android build process takes place. Then since Im forcing the task to run again I see an error that is essentially the same as if I ran my task manually from a command line without adding arguments for the jar to execute on. Ive tried using the depends on but maybe Ill give it another shot to see if I can get the desired outcome – James andresakis Sep 23 '14 at 16:13
  • My final solution for this is here http://stackoverflow.com/questions/26048396/best-way-to-sign-an-apk-using-ant-in-a-build-gradle-file – James andresakis Sep 29 '14 at 18:36

0 Answers0