MasteringtheNDKwith Android Studio 2.0+ and the gradle-experimental plugin
Xavier Hallade
Application Engineer @ Intel
#droidconIT
Mastering the NDK - Agenda
The Android NDK
Brief history of Android Studio support of the NDK
What we can do n...
TheAndroidNDK
Let’s briefly reexamine what it is and how it works
#droidconIT
The Android NDK
Checking .so files
https://play.google.com/store/apps/details?id=co
m.xh.nativelibsmonitor.app
#droidconIT
Java Native Interface (JNI)
Java side
 System.loadLibrary()
 native keyword
C/C++ side - .so files
 #includ...
#droidconIT
use and return Java primitives and objects
jint xxx(JNIEnv* env, jclass cls, …)
use a specific function name:
...
Uses Android.mk and Application.mk Makefiles.
The NDK will generate optimized code for all target ABIs
You can also pass A...
#droidconIT
Classic* execution flow
1. .so files loaded in memory by System.loadLibrary()
1. C/C++ functions  Java native...
AndroidStudioandtheNDK
Where are we now?
#droidconIT
Android Studio and the NDK – a brief history
• December 2013: gradle 0.7.3 – “sort of” support for the NDK
• D...
ASNDKCodeediting
Demo
13
ASNDKDebugging
Demo
HowtogetThis?
#droidconIT
Solutions to use the NDK with gradle/AS
• gradle(-stable) plugin, deprecated Android NDK support
• gradle(-sta...
#droidconIT
gradle(-stable) plugin, deprecated Android NDK support
- bad APP_PLATFORM handling
- it’s deprecated!
#droidconIT
gradle(-stable) plugin, manual call to NDK build
+ stable
+ most configurable solution (using Android.mk/Appli...
#droidconIT
gradle(-experimental) plugin, built-in NDK support
+ full code editing/debugging within Android Studio
+ good ...
#droidconIT
Mixing gradle-stable and gradle-experimental plugins
+ full code editing/debugging support within Android Stud...
#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....
Migratingtogradle-experimental
#droidconIT
Gradle experimental plugin
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0'
}
com....
#droidconIT
Example of build.gradle update to gradle-experimental
apply plugin: 'com.android.application'
android {
compil...
#droidconIT
NDK configurability
android.ndk {
moduleName
platformVersion
toolchain
toolchainVersion
cFlags
cppFlags
ldLibs...
#droidconIT
Android Studio configuration
Gradleconfigurationexamples
#droidconIT
android.ndk {
moduleName = "TeapotNativeActivity"
platformVersion = 17
cppFlags.add("-I${file("src/main/jni/na...
#droidconIT
android.sources {
main{
jni {
source {
srcDir 'src/main/XXX'//folder
srcDir 'src/main/YYY'//other folder
exclu...
repositories { libs(PrebuiltLibraries) { myexternallib {
headers.srcDir "src/main/jni/prebuilts/include"
binaries.withType...
apply plugin: 'com.android.model.application'
model {
def versionCodeBase = 11;
def versionCodePrefixes = ['armeabi': 1, '...
//project’s build.gradle:
buildscript {
…
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0'
cla...
Mixing gradle stable and -experimental plugins
…and keep debugging working in AS:
#droidconIT
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a'
universalApk true
}
}
/...
Q&A@ph0b – ph0b.com – +XavierHallade
#droidconIT
Resources
http://ph0b.com/new-android-studio-ndk-support/
https://github.com/googlesamples/android-ndk
Watch f...
Additionalslides
Multiple APKs and version codes handling
Google Play* supports multiple APKs for the same application.
What compatible APK...
#droidconIT
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hel...
#droidconIT 43
Application.mk
APP_PLATFORM := android-15 # <= minSDKVersion
APP_CFLAGS := -O3
APP_STL := c++_shared
APP_AB...
import org.apache.tools.ant.taskdefs.condition.Os
android.sources {
main {
jni {
source {
srcDirs = ['src/main/none']
}
}
...
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Prochain SlideShare
Chargement dans…5
×

Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin

20 806 vues

Publié le

Android Studio is finally fully supporting the NDK so you can easily integrate C/C++ inside Android applications.

While this support is still experimental, it’s promising and worth already doing the final jump from other IDEs and build systems.

After a short introduction on what is the NDK, learn how to use it from Android Studio while avoiding several classic pitfalls.

Publié dans : Technologie
2 commentaires
27 j’aime
Statistiques
Remarques
Aucun téléchargement
Vues
Nombre de vues
20 806
Sur SlideShare
0
Issues des intégrations
0
Intégrations
885
Actions
Partages
0
Téléchargements
234
Commentaires
2
J’aime
27
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin

  1. 1. MasteringtheNDKwith Android Studio 2.0+ and the gradle-experimental plugin Xavier Hallade Application Engineer @ Intel
  2. 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
  3. 3. TheAndroidNDK Let’s briefly reexamine what it is and how it works
  4. 4. #droidconIT The Android NDK
  5. 5. Checking .so files https://play.google.com/store/apps/details?id=co m.xh.nativelibsmonitor.app
  6. 6. #droidconIT Java Native Interface (JNI) Java side  System.loadLibrary()  native keyword C/C++ side - .so files  #include <jni.h> – Java primitive types, objects, methods – JNIEnv*, JavaVM*
  7. 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. 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. 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.
  10. 10. AndroidStudioandtheNDK Where are we now?
  11. 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 !!
  12. 12. ASNDKCodeediting Demo
  13. 13. 13
  14. 14. ASNDKDebugging Demo
  15. 15. HowtogetThis?
  16. 16. #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
  17. 17. #droidconIT gradle(-stable) plugin, deprecated Android NDK support - bad APP_PLATFORM handling - it’s deprecated!
  18. 18. #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
  19. 19. #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.
  20. 20. #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
  21. 21. #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
  22. 22. Migratingtogradle-experimental
  23. 23. #droidconIT Gradle experimental plugin dependencies { classpath 'com.android.tools.build:gradle-experimental:0.6.0' } com.android.model. application / library / native model{} .with{} distributionUrl=https://services.gradle.org/distributions/gradle-2.10-all.zip .add() / .addAll() / .removeAll()
  24. 24. #droidconIT Example of build.gradle update to gradle-experimental apply plugin: 'com.android.application' android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { applicationId "com.ph0b.example" minSdkVersion 15 targetSdkVersion 23 versionCode 4 versionName "1.0.1" ndk { moduleName "mymodule" ldLibs "log" stl "gnustl_static" cFlags "-std=c++11 -fexceptions" } } signingConfigs { release { storeFile file(STORE_FILE) storePassword STORE_PASSWORD keyAlias KEY_ALIAS keyPassword KEY_PASSWORD } } buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.txt' signingConfig signingConfigs.release } debug { jniDebuggable true } } } apply plugin: 'com.android.model.application' model { android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig.with { applicationId "com.ph0b.example" minSdkVersion.apiLevel 15 targetSdkVersion.apiLevel 23 versionCode 4 versionName "1.0.1" } } android.ndk { moduleName = "mymodule" ldLibs.addAll(['log']) cppFlags.add("-std=c++11“) cppFlags.add("-fexceptions“) stl = 'gnustl_static' } android.signingConfigs { create("release") { keyAlias KEY_ALIAS keyPassword STORE_PASSWORD storeFile file(STORE_FILE) storePassword KEY_PASSWORD } } android.buildTypes { release { signingConfig = $("android.signingConfigs.release“) minifyEnabled true proguardFiles.add(file('proguard-rules.txt')) } } }
  25. 25. #droidconIT NDK configurability android.ndk { moduleName platformVersion toolchain toolchainVersion cFlags cppFlags ldLibs ldFlags abiFilters stl renderscriptNdkMode debuggable } android.abis { // 0.7.0+ create("ABI") { //ABI can be any of x86, x86_64, armeabi-v7a, arm64-v8a… cppFlags ldLibs ldFlags } }
  26. 26. #droidconIT Android Studio configuration
  27. 27. Gradleconfigurationexamples
  28. 28. #droidconIT android.ndk { moduleName = "TeapotNativeActivity" platformVersion = 17 cppFlags.add("-I${file("src/main/jni/native_app_glue")}".toString()) cppFlags.add("-I${file("src/main/jni/cpufeatures")}".toString()) cppFlags.add("-I${file("src/main/jni/ndk_helper")}".toString()) ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log"]) stl = "stlport_static" } build.gradle Native dependencies (with sources)
  29. 29. #droidconIT android.sources { main{ jni { source { srcDir 'src/main/XXX'//folder srcDir 'src/main/YYY'//other folder exclude "**/not_this_one.c" //single file } } } } build.gradle Adding/Removing native sources to be compiled
  30. 30. repositories { libs(PrebuiltLibraries) { myexternallib { headers.srcDir "src/main/jni/prebuilts/include" binaries.withType(SharedLibraryBinary) { sharedLibraryFile = file("src/main/jni/prebuilts/${targetPlatform.getName()}/libmyexternallib.so") } }}} android.ndk { moduleName = "TeapotNativeActivity" platformVersion = 17 ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log"]) stl = "stlport_static" } android.sources { main { jni { dependencies { library "myexternallib" linkage "dynamic" //dynamic is default / can be static too }}}} build.gradle Native dependencies (prebuilts)
  31. 31. apply plugin: 'com.android.model.application' model { def versionCodeBase = 11; def versionCodePrefixes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]; //... android.productFlavors { create ("armv7") { ndk.abiFilters.add("armeabi-v7a") versionCode = versionCodePrefixes.get("armeabi-v7a", 0) * 1000000 + versionCodeBase } create ("x86") { ndk.abiFilters.add("x86") versionCode = versionCodePrefixes.get("x86", 0) * 1000000 + versionCodeBase } } } build.gradle Multiple APKs (gradle-experimental)
  32. 32. //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
  33. 33. Mixing gradle stable and -experimental plugins …and keep debugging working in AS:
  34. 34. #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)
  35. 35. Q&A@ph0b – ph0b.com – +XavierHallade
  36. 36. #droidconIT Resources http://ph0b.com/new-android-studio-ndk-support/ https://github.com/googlesamples/android-ndk Watch for this issue to be resolved for fixing editing on Windows versions of AS: http://b.android.com/195483
  37. 37. Additionalslides
  38. 38. 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
  39. 39. #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
  40. 40. #droidconIT 43 Application.mk APP_PLATFORM := android-15 # <= minSDKVersion APP_CFLAGS := -O3 APP_STL := c++_shared APP_ABI := all # or all32, all64… APP_OPTIM := release # default NDK_TOOCLHAIN_VERSION := 4.8 # default
  41. 41. import org.apache.tools.ant.taskdefs.condition.Os android.sources { main { jni { source { srcDirs = ['src/main/none'] } } jniLibs { source { srcDirs = ['src/main/libs'] } } } } task ndkBuild(type: Exec) { def ndkBuildExt = Os.isFamily(Os.FAMILY_WINDOWS) ? ".cmd" : "" commandLine "ndk-build${ndkBuildExt}", '-C', file('src/main').absolutePath } tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } build.gradle Using Android.mk/Application.mk from Gradle

×