Monday, February 09, 2015

A Method to Get NDK Building on AndroidStudio 1.0.2

Android Studio version 1.0 was apparently released without NDK support - at least there was nothing from the documentation. However, just because it's not there doesn't mean we can't build projects with C files. I remember getting this to work when this was in beta mode by Googling around but I keep forgetting how to recreate the steps when creating a new project so I'm leaving this here as a note-to-self until AndroidStudio NDK support becomes official. I believe there are more than one way to get around this but this is the way I managed to get it to work.

First, I create my NDK files as I would for building on Eclipse or building from Command Line. This would require an Android.mk and my c (.c) and relevant header (.h) files.

Now in the side explorer, set the view to Project rather than Android view. This got me stumped too many times as the Android view will hide your c-files and it won't actually show you the actual folder structure but more so the way the Android App is structured.

The build.gradle file will have to be edited as well. Add the following line to the gradle for the app. This will prevent Gradle from trying to build the C files and generating its own Android.mk files during build.

sourceSets.main.jni.srcDirs = []

Also, add the following to let Gradle know that I'll be linking to a compiled library file with the name of my JNI module.

    ndk {
        moduleName "ndkmodule"
    }

At any time Android Studio asks me to sync, just sync. My completed build.gradle now looks like:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.1"
    sourceSets.main.jni.srcDirs = []

    defaultConfig {
        applicationId "test.tso.ndkandroidstudio102"
        minSdkVersion 15
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "ndkmodule"
        }
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.2'
}

Now I need to create a bash script that will perform an ndk build. If I was to execute {ndk-path}/ndk-build in the project directory of this current Android app, it will compile the JNI/C libraries using the supplied Android.mk make file. I then can move these .so files into a /jniLibs folder of the project directory for the Java side to use. The following script facilitates this. I don't remember where I Googled this from but it's a very trivial script. Save this file anywhere in your project. I would prefer /app/src/main to keep it clean.

PROJECTDIR="/PATH/TO/YOUR/PROJECT/app/src/main"
NDKDIR="/PATH/TO/YOUR/android-ndk-r9c"

pushd ${PROJECTDIR}

(
export NDK_OUT="$PROJECTDIR/../../build/jni-obj";
export NDK_LIBS_OUT="$PROJECTDIR/jniLibs";
${NDKDIR}/ndk-build -C ${PROJECTDIR} $1
)

popd

Lastly, I spent a good hour clicking around Android Studio and finally figured out how to execute an external script and do so before the app builds. It makes a huge difference if you don't put it before, otherwise your edits to your c files will not go into the app build unless you build twice everytime. First, I'll need to install BashSupport plugin. File > Settings > Plugins > Browse Repository > BashSupport. Install, restart Android Studio.

On the top toolbar there should be a dropdown with an Android logo and text that says "app" (default, unless you've changed it). Select that and choose Edit Configurations.

In the edit configurations prompt, top left, click Add (the plus symbol) and select Bash.

Name it "ndkbuild.sh" and in the script, enter your full file path to the ndkbuild.sh script. Press Apply.

I needed to close this window and open it again in order for other configurations to see this new ndkbuild.sh configuration. In the same dialog window, select "app" under "Android Application" on the left and scroll the right settings down to the bottom until "Before launch: Gradle-aware Make" section is visible.

Click the plus symbol > Run another configuration. And in that prompt asking to choose configuration, select ndkbuild.sh. Select okay. And I have to make sure that "Run 'ndkbuild.sh'" is listed on top of "Gradle-aware Make". If not, select Run 'ndkbuild.sh' and move it up by pressing the up arrow button.

This tells the build configuration to run the ndkbuild.sh script before running the Gradle make on the app so that the app will use the newest build ndk library files that's in the jniLibs directory. That should be all the steps to get ndk to build properly. When you're running the builds, make sure the run configuration dropdown selects "app" rather than "ndk-build.sh" on the top toolbar of the main screen. Selecting "ndk-build.sh" will only run the shell script and that's it.

One major down side to using this is that Android Studio does not check ndk build error and halt the build. The ndk-build output flashes briefly build bottom panel message area before moving on to debug view. So you have to manually switch over to see the ndkbuild.sh output tab to catch any ndk-build failures.

No comments :

Post a Comment