Migrate a Library in Android Studio

This was then …

For our technology we have a portfolio of c programs working in Windows (VisualStudio), iOS (Xcode), Android (Android Studio).

They are available as SDKs in form of linkable libraries for iOS and for Android development (using the respective audio interface, especially, recording from the devices’ microphone(s).)

Everything worked out nicely, and for Windows and iOS there was no problem migrating said libraries into 64-bit code with the advent of iOS 10 and newer devices, say, starting with iPod Touch gen.6.

It became a bit of work with Android…

In the earlier days with Android Studio (before that we had Eclipse with the Android development enhancements)  we were using the model plugin supported in gradle-experimental for the NDK and JNI features.  Everything was working fine, using Android Studio 2.3.3 and gradle-experimental:0.9.3, and earlier.


But then it turned out we could not build our c programs to 64-bit code (using abifiltersARM64-8a”), due to missing hooks:
Known limitations for the Gradle component “model” implementation: “No support for using a NDK modules like cpu_features” and “No Support for integrating external build systems”.


OK, so I started updating the Android projects to (now) Android Studio 3.4.1.   However, to my dismay, using the latest gradle-experimental:0.11.1 I got pages of exceptions reports during Gradle sync!  The offending line: calling the model plugin.

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

I filed Google issue # 133092980.

Nevertheless, between reporting a problem and eventually getting a solution could mean … well,  days?  Months?  Never?

Even though the Gradle blog “State and future of the Gradle Software Model” suggests work is being done, but that blog is as of August 2017, and Google is actually encouraging to migrate away from the model plugin, and none of the often great Android sample projects make use of “model”.

This is now …

So I started my “happy migration” project from Android Studio 2.3.3 with gradle:2.3.3 and gradle-experimental:0.9.3 to Android Studio 3.4.1 with gradle:3.4.1.  I encountered somewhat documented syntax and structural changes for the build.gradle scripts.  And some trial-and-error ones.  

A good starting point is the documentation from the Google Android team: “Android Studio Project, Experimental Plugin User Guide”.

As the Android team wrote so nicely,  “There are significant changes to the DSL of the plugin.  We understand that many of the changes are frustrating and seem unnecessary, and our goal is to remove some of these current changes to minimize the migration process from the traditional plugin in the future.”

(BTW, Gradle is now on release 5.4.1 as of April 2019; the one used with Android Studio is 3.4.1.)


To now get the C/C++ programs compiled using JNI and NDK I created CMake and, alternatively, NDK-Build script files, for kicks.   Right:  Gradle without the “model” plugin does not call and build directly the JNI modules.  The make files need to be separately created and called through either CMake or NDK-Build within build.gradle!

The modifications in detail …

app / build.gradle 

(from gradle:2.3.3 to gradle:3.4.1)

  1. remove ending semicolons (;), now flagged as unnecessary
      
  2. rename all compile entries in dependencies { } block to implementation, provided to compileOnly
    (just a few of the many Gradle syntax changes…)
      
  3. add line:
                flavorDimensions 'vox'
      
  4. add to each selection in productFlavors blocks the line:
                dimension 'vox'
      
  5. change
                variant.outputs.every
    to
                variant.outputs.all
      
  6. declare following
                def relativeRootDir = output.packageApplication.outputDirectory.toPath(). relativize(rootDir.toPath()).toFile()
      
    and instead of
                output.outputFile = new File( output.outputFile.parent, output.outputFile.name.replace("app-voxDigits", apkNameVoxDigits()) )
      
    now use
                output.outputFileName = new File( "$relativeRootDir"+"/"+"app", output.outputFileName.replace("app-voxDigits", apkNameVoxDigits()) )
       

wavvoxlibrary / build.gradle 

(from gradle:2.3.3 / gradle-experimental:0.9.3
to gradle:3.4.1)

  1. remove ending semicolons (;), now flagged as unnecessary
      
  2. rename all compile entries in dependencies { } block to implementation, provided to compileOnly
    (just a few of the many Gradle syntax changes…)
      
  3.  convert gradle-experimental to gradle syntax
      
    • change
      apply plugin: 'com.android.model.library'
      to
      apply plugin: 'com.android.library'  
        
    • remove outside wrapped  model {  } block
        
  4. revert all changes marked in red per “Android Studio Project, Experimental Plugin User Guide
      
  5. rewrite the  ndk { } block without CFlags and platformVersion; remove sources { } or sourceSets { } block
      
  6. add externalNativeBuild { } blocks to specify external  build systems and their respective make files
      
    • cmake:  
      src/main/jni/CMakeLists.txt  (build.gradle)
        
    • ndkBuild:     
      src/main/jni/Android.mk (build.gradle) +  
      src/main/jni/Application.mk (implicitly called)
        
  7. create said make file(s), also include CPU / ABI model(s) and compiler options as desired
       

What’s left …

The Build — Signed .. APK is working as hoped with linking of the compiled “.so” library files (here, both for “armeabi-v7aandarm64-v8a”). The app runs in 32-bit environments (say, Nexus 7 with Android 6) as well as in 64-bit environments (say, Xaomi M1 with Android 9).

To create the “.aar” library (I haven’t gotten that to work automagically as with the earlier Android Studio 2 versions, yet), you’ll need to explicitly execute the Gradle task:
wavvoxlibrary / Tasks / build / assemble 

The Android libraries are then available at
./wavvoxlibrary/build/outputs/aar/…
and can be used and linked to other apps .

What’s available …

On github you’ll find the following samples.

  • ./wavvoxengine/build.gradle
        
    • for Android Studio 2.3.3 (before) – using the component model syntax
          
    • for Android Studio 3.4.1 (after) – set buildKind() to either “cmake” or “ndkBuild”
          
  • ./wavvoxlibrary/src/main/jni/
        
    • CMakeLists.txt  — “cmake”
          
    • Android.mk  +  Application.mk  — “ndkBuild”      
          
  • This document …


Enjoy,
jm.

San José, California
19-June-2019


Computers help you solve problems, you wouldn’t have without them!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert