2

I have an Android Studio project and a C# script that makes a release build of this project: first I make an unsigned release APK using CMD.exe, and then I use jarsigner to sign the application(this is needed to build apk without even opening Android Studio and being able to change key store).

I have updated Android Studio lately and now when I generate signed APK right from the IDE there is one new option: Signature version - V1 (Jar Signature) and V2 (Full APK Signature). After this update if I build an APK using my C# script the APK file is not accepted by Google Play: it says that my APK is not optimized and I should use optimization instrument and re-upload. I believe these two changes are related.

My question is how do I choose Signature version using jarsigner? I have found no related options in jarsigner and gradlew help.

Here is my C# simplified code:

//assemble an unsigned APK
Process cmd = new Process()
cmd.StartInfo.FileName = "CMD.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.UseShellExecute = false;
cmd.Start();        
cmd.StandardInput.WriteLine(@"cd /d """ + Application.StartupPath + @"""");
cmd.StandardInput.WriteLine(@"gradlew assembleRelease");
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();

//sign the APK
string args = @"-keystore """ + keyPath + @""" -storepass " + alias + 
@" """ + Application.StartupPath + 
@"\app\build\outputs\apk\app-release-unsigned.apk"" " + aliasPas;
Process java = new Process();
java.StartInfo.FileName = Path.Combine(GetJavaInstallationPath(), "bin\\jarsigner.exe");
java.StartInfo.Arguments = args;
java.StartInfo.UseShellExecute = false;
java.Start();
java.WaitForExit();
Sam Stone
  • 477
  • 2
  • 10
  • 33

2 Answers2

2

I ended up using only Gradle instruments to build and sign a release APK (excluded separated Java jarsigner process from the pipeline).

Here is a new signing config in app-level build.gradle file:

signingConfigs {
    release {
        storeFile file(RELEASE_STORE_FILE)
        storePassword RELEASE_KEY
        keyAlias RELEASE_KEY_ALIAS
        keyPassword RELEASE_KEY_PASSWORD
        v1SigningEnabled true;
        v2SigningEnabled true;
    }
}

As you can see, I added v1SigningEnabled and v2SigningEnabled fields. Keystore information is taken from gradle.properties file as described in this topic, I just adjusted my script to change the file contents with what I need to change keystore. Now APK file is uploaded without any errors.

Sam Stone
  • 477
  • 2
  • 10
  • 33
1

At https://source.android.com/security/apksigning/ you can read about v1 and v2 signing scheme. Using jarsigner, you create the v1 signing scheme. jarsigner cannot do the v2 signing as far as I know.

I don't think the v1 signing is the reason for your problem, as it speaks about missing optimization, not about missing signature. I think this is just a coincidence.

Actually I don't know why you have a C# script at all, you can use the jarsigner from your Gradle build file just fine without the need to use any external wrapper script.

I suggest you review and fix your build script to do the proper signing and optimization instead of using some home-brew C# script. Maybe that could help already.

Vampire
  • 35,631
  • 4
  • 76
  • 102
  • Using external script is needed to provide a separate GUI application aside from Android Studio, and there are other preparations needed to be done before building(which cannot be done from Gradle). But I have just found new options for signingconfig `v1SigningEnabled` and `v2SigningEnabled`, which I can use for a Gradle task which can be called from my script. – Sam Stone Jun 19 '17 at 12:48
  • I don't see where your C# code is opening a GUI, but if it is for selecting the keystore, you can also open a GUI easily from a Gradle build script. Gradle build scripts are Groovy scripts, so you can easily use Groovys `SwingBuilder` to easily construct a simple GUI to get some user input. No need for Android Studio, just plain Gradle. And I'd say everything you can do from the C# code you can easily do too from within the Gradle script. – Vampire Jun 19 '17 at 13:26
  • And again, I don't think the missing v2 signing is the reason for Play rejecting your apk, as it is perfectly fine to only have a v1 signature. It is not as safe as having a v2 signature, but it should work perfectly fine. – Vampire Jun 19 '17 at 13:27
  • I never meant that missing v2 is the problem, I think the problem was using jarsigner. I fixed the problem and will now add an answer to explain my solution. – Sam Stone Jun 19 '17 at 14:01
  • You could also update my answer with the additional information – Vampire Jun 19 '17 at 14:04