How can I codesign a 64-bit Android APK using the Gradle Experimental Plugin?

732 Views Asked by At

I am developing a Android apps using Open Frameworks, a C++ framework which supports Android. Its Android projects use the Gradle experimental plugin to allow C++. I have been able to get these to build unsigned APK's that run just fine (using Android Studio 2.3.2, 3.0, 3.5 or 3.5.1, Experimental Gradle Plugin 0.9.3, and Gradle distribution 3.3.0). But now I need to codesign them and include 64-bit versions to post them to the Android Store.

The Gradle Experimental Plugin has always required a specific single version of Gradle distribution for each of its own versions. And the current doc page for the plugin says that we can "keep using experimental plugin 0.11.0 with Android Studio 3.0 or later", but I seem to be blocked from code-signing by the above in Android Studio 3.5 and 3.5.1.

When I try to use the latest versions of Android Studio (version 3.5 or 3.5.1) to "Generate Signed APK", I get stopped by "Gradle version 4.1 is required.".

When I try to use older versions of Android Studio (version 2.3.2 or 3.0) to "Generate Signed APK", I can build 32-bit codesigned APKs, but I don't know how to build 64-bit APKs. The documentation I have found doesn't seem to apply to the Gradle files I have from Open Frameworks.

Notes on my attempts to get a handle on this:

(As I think I understand it, Gradle Plugin version is different from Gradle distribution version as mapped in this table.)

The only source I have found anywhere for what version of Gradle distribution to use with Gradle Experimental plugin 0.11.0, is this answer to a related question. I asked the answerer what version of Android Studio they were using and they said 3.1, but did not mention codesigning (I've now asked them about that).

It looks like the "Android Gradle Plugin" version is always the same as the Android Studio version, so there seems to be no way to run Android Gradle Plugin version 3.0 with Android Studio 3.5.1, correct?

So based on the above, I tried:

Android Studio (and therefore Gradle Plugin version) 2.3.2 with Experimental Gradle 0.9.3 using Gradle distribution 3.3.0 (codesigns 32-bit APKs - don't know how to do 64-bit)

Android Studio (and therefore Gradle Plugin version) 3.0.0 with Experimental Gradle 0.9.3 using Gradle distribution 3.3.0 (codesigns 32-bit APKs - don't know how to do 64-bit)

Android Studio (and therefore Gradle Plugin version) 3.0.0 with Experimental Gradle 0.11.0 using Gradle distribution 4.1.0 - I get a Gradle error:

*Gradle sync failed: Exception thrown while executing model rule: BaseComponentModelPlugin.Rules#createVariantData(ModelMap<AndroidBinaryInternal>, ModelMap<AndroidComponentSpec>, TaskManager) > afterEach()
    Consult IDE log for more details (Help | Show Log) (21s 58ms)*

I found supposed documentation of how to create 64-bit signed APKs with Gradle HERE, but the format suggested for listing ABI filters:

ndk.abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'

Resulted in an error, and Open Frameworks' project build.gradle tries to include all ABIs as seen in the android.productFlavors section near the bottom of the build.gradle as shown below:

def ofRoot(){ return '../../../' }

// Load common functions
apply from: ofRoot()+"libs/openFrameworksCompiled/project/android/common-functions.gradle"

buildscript {
    apply from: "../../../libs/openFrameworksCompiled/project/android/ndk-verify.gradle"

    repositories {
        jcenter()
    }
    dependencies {
        // Using the gradle-experimental version that supports c++
        classpath 'com.android.tools.build:gradle-experimental:0.9.3'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

apply plugin: 'com.android.model.application'

model {
    android {
        // openFrameworks currently only supports compiling against SDK 19
        compileSdkVersion = 23
        buildToolsVersion = "25.0.3"

        defaultConfig.with {
            minSdkVersion.apiLevel    = 23
            targetSdkVersion.apiLevel = 28
            versionCode     =  4
            versionName     = "0.1.1"
        }
    }

    android.ndk {
        moduleName = ofAppModuleName()
        toolchain  = buildToolchain()
        stl        = compilerStl()
        platformVersion = "21"
    }

    android.sources {
        main {
            jni {
                source {
                    srcDirs= appSrcDirs(ofRoot())

                    includes = srcIncludes(ofRoot())
                    excludes = srcExcludes(ofRoot())
                }

                // Link to openFrameworks
                dependencies {
                    project ":openFrameworksProject"  linkage "static"
                }
            }

            manifest {
                source {
                    srcDirs = [ "." ]
                }
            }
            res {
                source {
                    srcDirs = [ "res" ]
                }
            }
            java {
                source {
                    srcDirs = [ "srcJava" ]
                }
            }
            aidl {
                source{
                    srcDirs = ['srcJava']
                }
            }
            renderscript{
                source{
                    srcDirs = ['srcJava']
                }
            }
            jniLibs {
                source {
                    srcDirs = ['libs']
                }
            }
            assets {
                source {
                    srcDirs = ['bin/data'] + addonData(ofRoot())
                }
            }
        }
    }

    android.lintOptions {
        abortOnError  = false
    }

    android.buildTypes {
        release {
            minifyEnabled = false
        }
    }

    // Setup the different types of flavors (arm / x86),
    // and add linker flags based on that
    android.productFlavors {
        getAbis().each { abi ->
            create(getFlavorName(abi)) {
                ndk {
                    abiFilters.add(abi)

                    cppFlags.addAll(coreCppFlags(abi, ofRoot()))
                    cppFlags.addAll(addonCppFlags(abi, ofRoot()))

                    ldLibs.addAll(coreLdLibs(abi, ofRoot()))
                    ldLibs.addAll(addonLdLibs(abi, ofRoot()))

                    ldFlags.addAll(coreLdFlags(abi, ofRoot()))
                    ldFlags.addAll(addonLdFlags(abi, ofRoot()))
                }
            }
        }
    }
}


dependencies {
    addonJavaDependencies(ofRoot()).each { dep ->
        compile(project(path: dep[1] ))
    }
    compile project(path: ':ofAndroidLib')
}

But this results in only 32-bit Arm and 386 ABI options in the codesign APK wizard.

Can anyone tell me how to build a codesigned 64-bit APK using Android Studio (any version) for the Experimental plugin?

2

There are 2 best solutions below

0
On BEST ANSWER

I managed to eventually get it to work after many days of head-banging, with help on the Open Frameworks forum. It involved not just code-signing but using a version of OpenFrameworks that supports 64-bit builds, and a large number of specific settings and steps.

My notes on the steps, versions and settings that finally worked are here: https://forum.openframeworks.cc/t/notes-on-steps-i-took-to-successfully-get-a-64-bit-apk-published-to-the-google-app-store/33722

Meanwhile, if anyone has any other useful information the subject, please share it in an answer here. I'll give the bounty to the most useful/relevant answer other than mine.

1
On

There are tools to sign apk using the command prompt and using zipalign. Here's the Documentation

https://developer.android.com/studio/build/building-cmdline#sign_manually

I believe that zipaline will still work using the experimental. or you can use a 3rd party app that can sign 64-bit apps like this

https://github.com/patrickfav/uber-apk-signer

this plugin signs application with 64-bit architecture.