The document provides an agenda for a talk on mastering the Android NDK with Android Studio 2.0+. It discusses the history of Android Studio support for the NDK, current capabilities, migrating to the gradle-experimental plugin, and configuring NDK projects. Demo sections cover NDK code editing and debugging in Android Studio. Solutions covered for using the NDK include the gradle plugin, manual NDK builds, and mixing gradle plugins.
2. #droidconIT
Mastering the NDK - Agenda
The Android NDK
Brief history of Android Studio support of the NDK
What we can do now with Android Studio
Migrating to the gradle-experimental plugin
Configuring your projects
Q&A
7. #droidconIT
use and return Java primitives and objects
jint xxx(JNIEnv* env, jclass cls, …)
use a specific function name:
Java_com_example_hellojni_MainActivity_method
or do a manual registration using
JNIEnv->RegisterNatives()
Mapping C/C++ implementations to Java methods
8. Uses Android.mk and Application.mk Makefiles.
The NDK will generate optimized code for all target ABIs
You can also pass APP_ABI variable to ndk-build, and specify each ABI:
ndk-build APP_ABI=x86
all32 and all64 are also possible values.
ndk-build(.cmd) – the historical tool
Build ARM64 libs
Build x86_64 libs
Build mips64 libs
Build ARMv7a libs
Build ARMv5 libs
Build x86 libs
Build mips libs
9. #droidconIT
Classic* execution flow
1. .so files loaded in memory by System.loadLibrary()
1. C/C++ functions Java native methods
2. DVM/ART encounters a call to a native method
1. its C/C++ implementation is executed
2. then, Java code execution goes on
* android.app.NativeActivity/ native_activity.h allow
to develop without having Java code inside the app.
11. #droidconIT
Android Studio and the NDK – a brief history
• December 2013: gradle 0.7.3 – “sort of” support for the NDK
• December 2014: Eclipse ADT no longer in development
• May 2015: Integration of CLion announced at Google I/O
• July 2015: first availability, with a lot of limitations
• Since April 7th (yesterday night!): first stable version of the experimental
plugin available, and everything is awesome !!
18. #droidconIT
Solutions to use the NDK with gradle/AS
• gradle(-stable) plugin, deprecated Android NDK support
• gradle(-stable) plugin, manual call to NDK build
• gradle(-experimental) plugin, experimental but stable since yesterday
• mixing gradle-stable and –experimental plugins
20. #droidconIT
gradle(-stable) plugin, manual call to NDK build
+ stable
+ most configurable solution (using Android.mk/Application.mk)
+ supports generating split APKs with proper version codes
~ C/C++ code editing inside Android Studio
- No C/C++ code debugging inside Android Studio
21. #droidconIT
gradle(-experimental) plugin, built-in NDK support
+ full code editing/debugging within Android Studio
+ good support for native dependencies since 0.6.0-alpha1
- it’s experimental and the documentation barely exists yet
- can’t generate split APKs with proper version codes
- Many incompatible plugins.
22. #droidconIT
Mixing gradle-stable and gradle-experimental plugins
+ full code editing/debugging support within Android Studio
+ good support for native dependencies since 0.6.0
+ can generate split APKs with proper version codes
+ all the plugins are supported
- it’s experimental and the documentation barely exists yet
23. #droidconIT
Using the right versions
Android Studio 1.5 2.0 2.1-preview5
gradle 2.8 2.10 2.10
gradle plugin 1.5.0 2.0.0 2.1.0-alpha5
gradle-experimental plugin 0.4.0 0.6.0 0.7.0-alpha5
34. //project’s build.gradle:
buildscript {
…
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0'
classpath 'com.android.tools.build:gradle:2.0.0'
}
}
//to keep debugging working, set this in the build.gradle that uses the stable plugin:
android{
buildTypes.debug.jniDebuggable true
}
/! use the latest versions for both plugins, don’t mix older ones.
build.gradle
Mixing gradle stable and -experimental plugins
35. Mixing gradle stable and -experimental plugins
…and keep debugging working in AS:
36. #droidconIT
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
universalApk true
}
}
// map for the version code
project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3,
'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI),
0) * 1000000 + defaultConfig.versionCode
}
}
build.gradle
Multiple APKs (APK Splits – gradle-stable)
40. Multiple APKs and version codes handling
Google Play* supports multiple APKs for the same application.
What compatible APK will be chosen for a device entirely depends on the
android:versionCode
If you have multiple APKs for multiple ABIs, best is to simply prefix your current
version code with a digit representing the ABI:
2310 3310 6310 7310
You can have more options for multiple APKs, here is a convention that will work if
you’re using all of these:
x86ARMv7 ARM64 X86_64
41. #droidconIT
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
Other useful variables:
LOCAL_C_INCLUDES := ./headers/
LOCAL_EXPORT_C_INCLUDES := ./headers/
LOCAL_SHARED_LIBRARIES := module_shared
LOCAL_STATIC_LIBRARIES := module_static
Other predefined macros:
BUILD_SHARED_LIBRARY, BUILD_STATIC_LIBRARY,
PREBUILT_SHARED_LIBRARY, PREBUILT_STATIC_LIBRARY