This shows you the differences between two versions of the page.
|
osp:lectures:lecture-ndk [2016/11/06 22:28] vlad.traista [Practical] |
osp:lectures:lecture-ndk [2017/01/22 11:38] (current) laura.ruse [Lecture] |
||
|---|---|---|---|
| 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> | ||
| - | TODO - needs refactoring | ||
| === 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.c 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 70: | Line 73: | ||
| <code Java> | <code Java> | ||
| static { | static { | ||
| - | System.loadLibrary("native"); | + | System.loadLibrary("native-lib"); |
| } | } | ||
| Line 77: | 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 145: | 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 173: | 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) === | ||