vxh.viet
5/19/2016 - 10:49 AM

How to set up Android NDK

How to set up Android NDK

Source: ph0b, froger, gitHub, sitePoint, []

Question: How to add NDK support to current project without upgrading current very complexed build.gradle?

Answer: Mixing both stable and experimental gradle plugin

  1. Download NDK from here (version 11 atm).
  2. Extract the folder to anywhere you want. In Android studio, put the path to app -> F4 -> SDK Location -> Android NDK location
  3. We don’t want to mess in our app code so we need to create external module with C++/JNI code. Add new Android Library Module:

File -> New -> New Module... -> Android Library

Here is the project structure with with all important directories and files:

ShuttaPro
├── app
|   ├── src
|   |   └── main
|   |       └── java
|   |
|   └── build.gradle
|
├── MyFFmpegPlayer
|   ├── src
|   |   └── main
|   |       ├── java
|   |       |    └── co.shutta.myffmpegplayer
|   |       |          └──HelloJNI.java
|   |       └── jni
|   |            └──MyFFmpegPlayer.c
|   |
|   └── build.gradle
|
├── build.gradle
|
  1. To use both stable and experimental gradle plugin in the top level ./build.gradle we add:
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0'
        classpath 'com.android.tools.build:gradle-experimental:0.7.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
  1. Because we only want to use the exprimental plugin with our MyFFmpegPlayer module, we only need to update MyFFmpegPlayer/build.gradle to the new DSL. See ph0b for further explaination. Sample build.gradle with new DSL:
apply plugin: 'com.android.model.library'

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.3"

        defaultConfig {
            minSdkVersion.apiLevel = 16
            targetSdkVersion.apiLevel = 23
            versionCode = 1
            versionName = "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file('proguard-android.txt'))
            }
        }

        ndk {
            moduleName = 'MyFFmpegPlayer'
            toolchain = 'clang'
            CFlags.addAll(['-Wall'])
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}
  1. To activate the C++/NDK support inside Android Studio, you only need to have a NDK module declared inside your application or library build.gradle:
model {
    android {
    //...
    ndk {
        moduleName "MyFFmpegPlayer"
    }
  }
}
  1. Once it’s done, you can go to your Java sources, create a method prefixed with the native keyword, and press ALT+Enter to generate its C implementation. Sample HelloJNI.java:
package co.shutta.myffmpegplayer;

public class HelloJNI {

    static {
        System.loadLibrary("MyFFmpegPlayer");
    }

    public static native String helloJNI();
}
  1. The implementation will be added under jni, inside an existing C file if there is one, or inside a new one. Sample MyFFmpegPlayer.c:
#include <jni.h>

JNIEXPORT jstring JNICALL
Java_co_shutta_myffmpegplayer_HelloJNI_helloJNI(JNIEnv *env, jclass type) {
    return (*env)->NewStringUTF(env, "Hello from JNI");
}

In order to get started with NDK modules, you can have a look at all the samples that have been ported to use the new gradle-experimental plugin: GitHub