Introduction to the Android NDK
-
Upload
bemyapp -
Category
Technology
-
view
590 -
download
1
description
Transcript of Introduction to the Android NDK
![Page 1: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/1.jpg)
Introduction to the Android NDK
Sebastian Mauer GDG Aachen
CodeFest Karlsruhe February 20th, 2014
![Page 2: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/2.jpg)
Who am I?Sebastian MauerGDG Aachen Co-Lead CS StudentSoftware Engineer I don’t work for Google…yet
![Page 3: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/3.jpg)
Part I: NDK? What is that?
![Page 4: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/4.jpg)
Android Platforms
MIPS x86ARM
![Page 5: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/5.jpg)
Two kinds of Apps
Apps in the DalvikVM(that’s the kind of apps you probably know)
Native Apps(created using the NDK)
![Page 6: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/6.jpg)
One VM to rule them all
• Dalvik is a Virtual Machine (VM)
• A VM is a common abstraction across different hardware platforms
• „Translates“ VM Bytecode to platform specific instructions
![Page 7: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/7.jpg)
It just works™
• The DalvikVM is already optimized for the x86 Platform
• Apps relying on the Android SDK / Dalvik Bytecodewill automatically benefit from Platform-specific Optimizations (like SSE & Co.)
![Page 8: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/8.jpg)
From Source to BytecodeJava
Sourcecode
Java Bytecode (.class)
Dalvik Bytecode (.dex)
JAR Archive
Dalvik VM
Java VM
![Page 9: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/9.jpg)
Android VM
Hardware
Linux Kernel
Dalvik VM App
App
App
App
App
App
![Page 10: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/10.jpg)
ONE DOES NOT SIMPLY
RUN CODE ON MULTIPLE PLATFORMS
![Page 11: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/11.jpg)
NOT SURE IF NDK CAN HELP ME RUN CODE FASTER
OR MAKE THINGS EVEN MORE COMPLICATED
![Page 12: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/12.jpg)
Part II: Going native. The NDK.
![Page 13: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/13.jpg)
What’s the NDK?• NDK stands for Native Development Kit
• Allows to compile C/C++ code to native (read: platform specific) executables/libraries.
• Build scripts/toolkit to incorporate native code in Android apps via the Java Native Interface (JNI)
• Has to be compiled for every platform you want to support
![Page 14: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/14.jpg)
But why?
• Performancee.g., complex algorithms, multimedia applications, games
• Differentiation app that takes advantage of direct CPU/HW accesse.g., using SSSE3 for optimization
• Fluid and lag-free animations
• Software code reuse
![Page 15: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/15.jpg)
Why not?
![Page 16: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/16.jpg)
![Page 17: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/17.jpg)
What could possibly go wrong?
• Performance improvements are not guaranteed
• In fact, you could make it worse (read: slower).
• Added complexity (Java/C++ Interop, Multiple platforms)
• Somewhat harder to debug
![Page 18: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/18.jpg)
![Page 19: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/19.jpg)
What’s an NDK app?It’s an Android application that uses native libraries. !Libraries are .so files, usually found inside libs/CPU_ABI/. !These libs can be generated from native sources inside jni folder, game engines, or required by other 3rd party libraries. !There is no 100% native application. Even an application purely written in C/C++, using native_app_glue.h, will be executed in the context of the Dalvik Virtual Machine.
![Page 20: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/20.jpg)
NDK Development in a NutshellC/C++Code Makefile ndk-build Java* calls GDB debug
Java Framework
Java Application
SDK APIs
JNI
Native Libs
Android* Applications
NDK APIs
Bionic C Library
APP_ABI := all or APP_ABI := x86
through jni
![Page 21: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/21.jpg)
NDK Anatomy
Native Platform
Dalvik VMDalvik Bytecode
NDK compiled binary
Java Native Interface
(JNI)
![Page 22: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/22.jpg)
Compatibility with Standard C/C++
• Bionic C Library: Lighter than standard GNU C LibraryNot POSIX compliantpthread support included, but limitedNo System-V IPCs Access to Android* system properties
• Bionic is not binary-compatible with the standard C library
• It means you generally need to (re)compile everything using the Android NDK toolchain
![Page 23: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/23.jpg)
Pick One
Runtime Exceptions RTTI STL
system No No No
gabi++ Yes Yes No
stlport Yes Yes Yes
gnustl Yes Yes Yes
• By default, libstdc++ is used. It lacks: Standard C++ Library support (except some headers) C++ exceptions supportRTTI support
• Fortunately, you have other libs available with the NDK:
![Page 24: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/24.jpg)
Compile for all the platforms.If you have the source code of your native libraries, you can compile it for several CPU architectures by setting APP_ABI to all in the Makefile “jni/Application.mk”:! APP_ABI=all
The NDK will generate optimized code for all target ABIs You can also pass APP_ABI variable directly to ndk-build, and specify each ABI: ndk-build APP_ABI=x86
ARM v7a libs are built
ARM v5 libs are built x86 libs are built
mips libs are built
Put APP_ABI=all inside Application.mkRun ndk-build…
![Page 25: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/25.jpg)
NDK
![Page 26: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/26.jpg)
NativeActivity•Only native code in the project •android_main() entry point running in its
own thread •Event loop to get input data and frame
drawing messages
/** * This is the main entry point of a native application that is using * android_native_app_glue. It runs in its own thread, with its own * event loop for receiving input events and doing other things. */ void android_main(struct android_app* state);
![Page 27: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/27.jpg)
Add native methods in JavaDeclare native methods in your Java classes using the ‘native’ keyword:
public native String stringFromJNI(); !Provide a native shared library built with the NDK that contains the methods used by your application:
libMyLib.so !Your application must load the shared library (before use… during class load for example):
static { System.loadLibrary("MyLib"); }
![Page 28: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/28.jpg)
Variant I: Use „javah“
javah creates JNI header stubs (.h) based on the Java source files from the compiled Java classes files !Example: > javah –d jni –classpath bin/classes \ com.example.hellojni.HelloJni !Generates com_example_hellojni_HelloJni.h file with the following method definition: JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv *, jobject);
![Page 29: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/29.jpg)
jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env, jobject thiz ) { return (*env)->NewStringUTF(env, "Hello from JNI !"); }
... { ... tv.setText( stringFromJNI() ); ... } public native String stringFromJNI(); ! static { System.loadLibrary("hello-jni"); }
Variant I: Use „javah“
![Page 30: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/30.jpg)
Variant II: JNI_OnLoad
• Proven method • No more surprises after methods registration • Less error prone when refactoring • Add/remove native functions easily • No symbol table issue when mixing C/C++ code • Best spot to cache Java class object references
![Page 31: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/31.jpg)
Variant II: JNI_OnLoadIn your library name your functions as you wish and declare the mapping with JVM methods: jstring stringFromJNI(JNIEnv* env, jobject thiz) { return env->NewStringUTF("Hello from JNI !"); } !static JNINativeMethod exposedMethods[] = { {"stringFromJNI","()Ljava/lang/String;",(void*)stringFromJNI}, } !()Ljava/lang/String; is the JNI signature of the Java* method, you can retrieve it using the javap utility: > javap -s -classpath bin\classes -p com.example.hellojni.HelloJni Compiled from "HelloJni.java“ … public native java.lang.String stringFromJNI(); Signature: ()Ljava/lang/String; …
![Page 32: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/32.jpg)
Variant II: JNI_OnLoadextern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env; if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR; ! jclass clazz = env->FindClass("com/example/hellojni/HelloJni"); if(clazz==NULL) return JNI_ERR; env->RegisterNatives(clazz, exposedMethods, sizeof(exposedMethods)/sizeof(JNINativeMethod)); env->DeleteLocalRef(clazz); return JNI_VERSION_1_6; }
![Page 33: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/33.jpg)
JNI PrimitivesJava Type Native Type Description
boolean jboolean unsigned 8 bits
byte jbyte signed 8 bits
char jchar unsigned 16 bits
short jshort signed 16 bits
int jint signed 32 bits
long jlong signed 64 bits
float jfloat 32 bits
double jdouble 64 bits
void void N/A
![Page 34: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/34.jpg)
Memory Handling of Java ObjectsMemory handling of Java* objects is done by the JVM: !
• You only deal with references to these objects • Each time you get a reference, you must not forget to
delete it after use • local references are automatically deleted when the
native call returns to Java • References are local by default • Global references are only created by NewGlobalRef()
![Page 35: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/35.jpg)
Creating a Java String
Memory is handled by the JVM, jstring is always a reference. You can call DeleteLocalRef() on it once you finished with it.
C: jstring string = (*env)->NewStringUTF(env, "new Java String"); !C++: jstring string = env->NewStringUTF("new Java String");
![Page 36: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/36.jpg)
Convert a jstring into a C/C++ String
const char *nativeString = (*env)->GetStringUTFChars(javaString, null); … (*env)->ReleaseStringUTFChars(env, javaString, nativeString);
![Page 37: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/37.jpg)
Call a Java MethodOn an object instance: jclass clazz = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, clazz, "methodName", "(…)…"); if (mid != NULL) (*env)->Call<Type>Method(env, obj, mid, parameters…); !Static call: jclass clazz = (*env)->FindClass(env, "java/lang/String"); jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "methodName", "(…)…"); if (mid != NULL) (*env)->CallStatic<Type>Method(env, clazz, mid, parameters…); !• (…)…: method signature • parameters: list of parameters expected by the Java* method • <Type>: Java method return type
![Page 38: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/38.jpg)
Handling Java Exceptions// call to java methods may throw Java exceptions jthrowable ex = (*env)->ExceptionOccurred(env); if (ex!=NULL) { (*env)->ExceptionClear(env); // deal with exception } !(*env)->DeleteLocalRef(env, ex);
![Page 39: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/39.jpg)
Throw a Java Exceptionjclass clazz = (*env->FindClass(env, "java/lang/Exception"); !if (clazz!=NULL) (*env)->ThrowNew(env, clazz, "Message");
The exception will be thrown only when the JNI call returns to Java*, it will not break the current native code execution.
![Page 40: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/40.jpg)
Demo
![Page 41: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/41.jpg)
Q&A
![Page 42: Introduction to the Android NDK](https://reader034.fdocuments.net/reader034/viewer/2022051012/5463b36baf795904328b6313/html5/thumbnails/42.jpg)
Thanks for your attention.