Differences

This shows you the differences between two versions of the page.

Link to this comparison view

osp:lectures:lecture-ndk [2016/10/05 12:03]
laura.gheorghe
osp:lectures:lecture-ndk [2017/01/22 11:38] (current)
laura.ruse [Lecture]
Line 1: Line 1:
-===== 05 - Android NDK =====+===== 06 - Android NDK =====
  
   * Description: ​   * Description: ​
Line 8: Line 8:
  
  
-  *{{:​osp:​lectures:​lecture-ndk.pdf | Lecture ​Slides - Part 1}}+  *{{:​osp:​lectures:​lecture-ndk.pdf | Slides ​- Part 1}} 
 +  *{{:​osp:​lectures:​6.ndk_notes.pdf | Notes - Part 1}}
  
 {{url>​http://​ocw.cs.pub.ro/​courses/​_media/​osp/​lectures/​lecture-ndk.pdf}} {{url>​http://​ocw.cs.pub.ro/​courses/​_media/​osp/​lectures/​lecture-ndk.pdf}}
  
-  *{{:​osp:​lectures:​lecture-ndk-2.pdf | Lecture ​Slides - Part 2}}+  *{{:​osp:​lectures:​lecture-ndk-2.pdf | Slides ​- Part 2}} 
 +  *{{:​osp:​lectures:​6.ndk2_notes.pdf | Notes - Part 2}}
  
 {{url>​http://​ocw.cs.pub.ro/​courses/​_media/​osp/​lectures/​lecture-ndk-2.pdf}} {{url>​http://​ocw.cs.pub.ro/​courses/​_media/​osp/​lectures/​lecture-ndk-2.pdf}}
Line 26: Line 28:
  
 <note warning>​If you do not have the Android NDK installed, you can downloand it and extract it from [[https://​developer.android.com/​ndk/​downloads/​index.html|this link]]. Afterwards in Android Studio you must set the NDK path if it is not set already. The path can be set by right clicking on the project and selecting the **Open Module Settings** menu item and setting the Android NDK location with a path similar to **/​home/​student/​android-ndk-10re**. <note warning>​If you do not have the Android NDK installed, you can downloand it and extract it from [[https://​developer.android.com/​ndk/​downloads/​index.html|this link]]. Afterwards in Android Studio you must set the NDK path if it is not set already. The path can be set by right clicking on the project and selecting the **Open Module Settings** menu item and setting the Android NDK location with a path similar to **/​home/​student/​android-ndk-10re**.
 +</​note>​
 +
 +<note warning>
 +In order to successfully run an Android application with native support, you need to have [[http://​www.oracle.com/​technetwork/​java/​javase/​downloads/​jdk7-downloads-1880260.html|Oracle Java 7 SDK]] installed and configure Android Studio to use that SDK.
 </​note>​ </​note>​
  
 === Files === === Files ===
  
-{{:​osp:​lectures:​nativeapplication.zip|}} +{{:​osp:​lectures:​introapplication.zip|}} 
-{{:​osp:​lectures:​lab5_tasks.zip|}}+{{:​osp:​lectures:​tasks.zip|}} 
 + 
 +<note warning>​ 
 +Abandon hope all ye who enter here for Android NDK is a mighty obstacle :D 
 +</​note>​
  
 === Task 1 - Create a Native Project (1p) === === Task 1 - Create a Native Project (1p) ===
  
-<note warning>​Because NDK is not fully support on Android Studio yet, you will have to import the project from this archive: {{:​osp:​lectures:​nativeapplication.zip|}}+<note warning>​Because NDK is not fully support on Android Studio yet, you will have to import the project from this archive: {{:​osp:​lectures:​introapplication.zip|}}
 You should use this whenever a new project is required. You can find more information about NDK integration in Android Studio at [[http://​tools.android.com/​tech-docs/​new-build-system/​gradle-experimental|this link]]. You should use this whenever a new project is required. You can find more information about NDK integration in Android Studio at [[http://​tools.android.com/​tech-docs/​new-build-system/​gradle-experimental|this link]].
 </​note>​ </​note>​
  
-Create a new project. +Edit native.cpp and add the following function: 
- +<code C++> 
-Edit native.and add the following function: +extern "​C"​ 
-<code C> +jstring ​Java_com_example_user_nativeapplication_MainActivity_getString(JNIEnv *env, jobject ​instance)
-jstring ​Java_com_example_student_nativeapplication_MainActivity_getString(JNIEnv *env, jobject ​thiz)+
 { {
- return ​(*env)->​NewStringUTF(env, "Hello world from JNI!"​);​+ return env->​NewStringUTF("​Hello world from JNI!"​);​
 } }
 </​code>​ </​code>​
  
-The equivalent C++ code is: +The equivalent C code is: 
-<code C++> +<code C> 
-extern "​C"​ { +jstring ​Java_com_example_user_nativeapplication_MainActivity_getString(JNIEnv *env, jobject ​instance)
- jstring Java_com_example_student_nativeapplication_MainActivity_getString(JNIEnv *env, jobject thiz); +
-+
- +
-jstring ​Java_com_example_student_nativeapplication_MainActivity_getString(JNIEnv *env, jobject ​thiz)+
 { {
- return env->​NewStringUTF("​Hello world from JNI!"​);​+ return ​(*env)->​NewStringUTF(env, "Hello world from JNI!"​);​
 } }
 </​code>​ </​code>​
Line 68: Line 73:
 <code Java> <code Java>
 static { static {
- System.loadLibrary("​native"​);​+ System.loadLibrary("​native-lib");
 } }
  
Line 75: Line 80:
  
 Then, make sure your activity has a TextView (with an id to reference it), and at onCreate, set the TextView to the String returned by getString(). Then, make sure your activity has a TextView (with an id to reference it), and at onCreate, set the TextView to the String returned by getString().
- 
-There is a more practical way of generating function prototypes: using javah or by automatically adding the functions using Android Studio. Declare all your native functions in the Java files first and then call javah to generate the headers. 
- 
-For example: 
-<​code>​ 
-javah -classpath <​sdk>/​platforms/​android-23/​android.jar:​android_workspace/​native/​bin/​classes/​ com.example.student.nativeapplication.MainActivity 
-</​code>​ 
-will generate com_example_student_nativeapplication_MainActivity.h 
-which contains 
-<code C> 
-/* DO NOT EDIT THIS FILE - it is machine generated */ 
-#include <​jni.h>​ 
-/* Header for class com_example_native1_MainActivity */ 
- 
-#ifndef _Included_com_example_student_nativeapplication_MainActivity 
-#define _Included_com_example_student_nativeapplication_MainActivity 
-#ifdef __cplusplus 
-extern "​C"​ { 
-#endif 
-/* 
- * Class: ​    ​com_example_student_nativeapplication_MainActivity 
- * Method: ​   getString 
- * Signature: ()Ljava/​lang/​String;​ 
- */ 
-JNIEXPORT jstring JNICALL Java_com_example_student_nativeapplication_MainActivity_getString 
-  (JNIEnv *, jobject); 
- 
-#ifdef __cplusplus 
-} 
-#endif 
-#endif 
-</​code>​ 
- 
  
 === Task 2 - Logging from Native Code (1p) === === Task 2 - Logging from Native Code (1p) ===
  
-To use logging from native code you will have to include **<​android/​log.h>​**. Add this include to **native.c**. You will have to also link this module against liblog. This already done in the imported project (ldLibs += "​log"​ in gradle.build).+To use logging from native code you will have to include **<​android/​log.h>​**. Add this include to **native-lib.cpp**. You will have to also link this module against liblog. This already done in the imported project (ldLibs += "​log"​ in gradle.build).
  
 Then, to print something, you need to use this macro: Then, to print something, you need to use this macro:
Line 143: Line 115:
 Finally, to get the class, call Finally, to get the class, call
 <code C> <code C>
-jclass cls = env->​FindClass("​osp/lab5/tasks/​MainActivity"​);​+jclass cls = env->​FindClass("​com/example/user/test/​MainActivity"​);​
 </​code>​ </​code>​
 which has a single parameter, the class name and package, with the path divided by "/"​. which has a single parameter, the class name and package, with the path divided by "/"​.
Line 171: Line 143:
 </​code>​ </​code>​
  
-Now, call setText(String,​ int), giving it as parameters the int that task3 receives and the jstring obtained from getInput. ​There is an easy way to obtain the signature of a function by using javap. Call it like this: +Now, call setText(String,​ int), giving it as parameters the int that task3 receives and the jstring obtained from getInput. Remember to call ReleaseStringUTFChars after you are done with the string.
-<code C> +
-javap -classpath $WORKSPACE/​Lab5_Tasks/​app/​build/​intermediates/​classes/​flavor1/​debug/​osp/​lab5/​tasks -p -s osp.lab5.tasks.MainActivity +
-</​code>​ +
-javap is used to disassemble java files, and the -s parameter is used to generate the signatures for public functions and fields, -p tells it to also generate signatures for private members of the class. +
-Remember to call ReleaseStringUTFChars after you are done with the string.+
  
 === Task 6 - Call a static method (1p) === === Task 6 - Call a static method (1p) ===
Line 228: Line 195:
 env->​ExceptionClear();​ env->​ExceptionClear();​
 </​code>​ </​code>​
- 
-=== Task 11 - Accessing an array (1p) === 
- 
-To access a Java array in the JNI you need a reference to it. You can pass the reference from Java or create a new array inside the JNI. Arrays have the type: j<​type>​Array,​ for example jintArray. 
- 
-To create a Java array from JNI: 
-<code C> 
-jintArray javaArray = env->​NewIntArray(jsize length); 
-</​code>​ 
-or 
-<code C> 
-jobjectArray javaArray = env->​NewObjectArray(jsize length, 
-jclass elementClass,​ jobject initialElement);​ 
-</​code>​ 
-where length is the number of elements in the array, elementClass is the class of the Objects and initialElement is the element each item in the array will be initialized as. 
- 
-To access a primitive type array use: 
-<code C> 
-env->​Get<​Type>​ArrayRegion(j<​type>​Array array, 
-jsize start, jsize len, j<​type>​ *buf); 
-</​code>​ 
-This will copy len elements, starting at element start from array into buf (starting from position 0 in buf). 
- 
-To copy back from a native array use: 
-<code C> 
-env->​Set<​Type>​ArrayRegion(j<​type>​Array array, 
-jsize start, jsize len, j<​type>​ *buf); 
-</​code>​ 
-This will copy len elements, starting at element start from buf into array (starting from position 0 in buf). 
- 
-For object arrays, use 
-<code C> 
-jobject obj = env->​GetObjectArrayElement(jobjectArray array, jsize index); 
-env->​SetObjectArrayElement(jobjectArray array, jsize index, jobject obj); 
-</​code>​ 
-instead. You cannot access more than one object at once (and it is impractical since there is a small amount of object references you can have at any one time). 
- 
-Implement the two native functions: getIntArray and getStringArray. Allocate the arrays and initialize the elements to 1, 2, 3, 4, 5 and "​one",​ "​two",​ "​three",​ "​four",​ "​five"​ respectively (from native code). They will get printed to the log. Use NewStringUTF to create the Strings. Return the created arrays. 
-Use DeleteLocalRef to remove the String references (JNI guarantees only 16 references to Java objects at any one time). 
- 
-=== Task 12 - Keeping a reference to the array (1p) === 
- 
-In the getIntArray method, after creating the array, use 
-<code C> 
-globalObj = env->​NewGlobalRef(jobject obj) 
-</​code>​ 
-to create a global reference. Make sure globalObj is declared globally. This means that globalObj will remain valid until it is deleted. 
- 
-<code C> 
-DeleteGlobalRef(globalObj);​ 
-</​code>​ 
-deletes a global reference. 
- 
-There are also Weak Global references, which allow objects to be garbage collected. You have to check if the reference is still 
-valid before using it with **IsSameObject**. 
- 
-Implement the updateArray method. Use the global reference to get access to the array. Increment each element by one. 
-Use GetArrayLength to get the length of the array. 
- 
-=== Task 13 - Direct pointer to array (1p) === 
- 
-Get<​Type>​ArrayRegion and Set<​Type>​ArrayRegion copy the array each time they are used. This will add overhead. Use 
-<code C> 
-j<​type>​ *directArray = env->​Get<​Type>​ArrayElements(j<​type>​Array array, jboolean *isCopy) 
-</​code>​ 
-to get a direct reference (if possible). ​ 
- 
-To release the array and free space 
-<code C> 
-env->​Release<​Type>​ArrayElements(j<​type>​Array array, j<​type>​ *directArray,​ jint mode) 
-</​code>​ 
-where can be: 
-  * 0 - Copy back the content and free directArray 
-  * JNI_COMMIT - Copy the content but don't free directArray 
-  * JNI_ABORT - Free directArray 
-Copying is only done if directArray is a copy. 
- 
-Modify the updateArray method to use direct copies of the array if possible. 
  
osp/lectures/lecture-ndk.1475658193.txt.gz · Last modified: 2016/10/05 12:03 by laura.gheorghe
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0