Android NDK development Common Errors
Error 1:
Make: *** No rule to make target '/cygdrive/d/1-workspace/showmap-android-opengles/jni/showmap_opengles_OpenGLESRenderer.c ', needed by '/cygdrive/d/1-workspace/showmap-android-opengles/obj/local/armeabi/objs/OpenGLESMap/showmap_opengles_OpenGLESRenderer.o '. stop.
This error occurs when showmap_opengles_OpenGLESRenderer.c is changed to showmap_opengles_OpenGLESRenderer.cpp. Of course, the android. mk file is modified accordingly.
Delete the obj folder. It is estimated that showmap_opengles_OpenGLESRenderer.c is not found because of cached information.
Error 2:
Problems caused by javah
BUG:
D/dalvikvm (1704): Trying to load lib/data/com. ulang/lib/libulangaudio. so 0x000052a38
D/dalvikvm (1704): Shared lib '/data/com. ulang/lib/libulangaudio. so' already loaded in same CL 0x000052a38
W/dalvikvm (1704): No implementation found for native Lcom/ulang/AudioLib;. sayHelloEx () Ljava/lang/String;
D/AndroidRuntime (1704): Shutting down VM
W/dalvikvm (1704): threadid = 1: thread exiting with uncaught exception (group = 0x409961f8)
E/AndroidRuntime (1704): fatal exception: main
E/AndroidRuntime (1704): java. lang. UnsatisfiedLinkError: sayHelloEx
E/AndroidRuntime (1704): at com. ulang. AudioLib. sayHelloEx (Native Method)
E/AndroidRuntime (1704): at com. ulang. One. onClick (One. java: 76)
E/AndroidRuntime (1704): at android. view. View. javasmclick (View. java: 3480)
E/AndroidRuntime (1704): at android. view. View $ export mclick. run (View. java: 13983)
E/AndroidRuntime (1704): at android. OS. Handler. handleCallback (Handler. java: 605)
E/AndroidRuntime (1704): at android. OS. Handler. dispatchMessage (Handler. java: 92)
E/AndroidRuntime (1704): at android. OS. Looper. loop (Looper. java: 137)
The second parameter javah is generated as jclass, so an error occurs,
You can change it to jobject.
Javah does not generate jclass for the second item in all cases, and sometimes it is also the generated jobject.
NE: special attention!
# Define _ cplusplus
# Ifdef _ cplusplus
Extern C {
# Endif
/*
* Class: com_ulang_AudioLib
* Method: sayHelloEx
* Signature: () Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ulang_AudioLib_sayHelloEx
(JNIEnv *, jclass );
# Ifdef _ cplusplus
}
# Endif
# Endif
II
When calling the JNI interface in the experiment, the following message is displayed on the logcat:
No implementation found in native ....
I searched the network and found that there may be several situations in this situation.
1. The function name is incorrect.
2. Confirm that you need to clean the project again and then rebuild all when you change the interface function.
After the above two points are confirmed, the no implementation error called by the JNI interface does not appear.
(2) run the. so library generated by c ++. If the following error is reported: (no function is found)
No implementation found for native Lcom/dgut/android/MainActivity;. stringFromJNI () Ljava/lang/String;
Java. lang. UnsatisfiedLinkError: stringFromJNI
At com. dgut. android. MainActivity. stringFromJNI (Native Method)
Solution:
Add extern c modifier before C ++ function for Java call, for example: (cpp file in NDK example is also so declared, refer to hello-gl2)
extern C {JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz );}JNIEXPORT jstring JNICALL Java_com_dgut_android_MainActivity_stringFromJNI( JNIEnv* env, jobject thiz ){ return env->NewStringUTF(Hello from JNI bear c++);}The reason is:
Variables and functions modified by extern C are compiled and connected in C language.
First, let's take a look at how C-like functions are compiled: As an object-oriented language, C ++ supports function overloading, while Procedural Language C does not. The name of the function in the symbol library after being compiled by C ++ is different from that in the C language. For example, assume that the prototype of a function is void foo (int x, int y). After the function is compiled by the C compiler, its name in the symbol library is _ foo, the C ++ compiler generates names such as _ foo_int_int (different compilers may generate different names, but all adopt the same mechanism, the new name is called "mangled name "). A name such as _ foo_int_int contains the function name, number of function parameters, and type information. C ++ relies on this mechanism to implement function overloading. For example, in C ++, The voidfoo (int x, int y) and void foo (int x, float y) functions generate different symbols, the latter is _ foo_int_float.
Similarly, variables in C ++ support both local variables and class member variables and global variables. The class member variables of the program you write may have the same name as the global variables. In essence, the compiler uses a unique name for the variables in the class when compiling, similar to the function processing. This name is different from the global variable name with the same name in the user program.
Therefore, if we do not use the extern C modifier, Jni may not be able to find this function by compiling and connecting in C language.
Error 3:
[Switch] JNI call error: No implementation found for native
When JNI is called, No implementation found for native is reported
One possibility is that if the code of C ++ is called, extern C must be added.
[Switch] the difference between jni Calling c and c ++.
1. Use of the JNIEnv * env Parameter
The first parameter of all JNI interfaces is JNIEnv * env. In C
(* Env)-> NewStringUTF (env, Hello from JNI !);
However, in C ++, the call method is
Env-> NewStringUTF (Hello from JNI !);
Why is there such a difference? Let's look at the definition of JNIEnv in jni. h:
# If defined (_ cplusplus)
Typedef _ JNIEnv;
# Else
Typedef const struct JNINativeInterface * JNIEnv;
# Endif
We can see that the definition of C and C ++ is different, mainly because C does not support classes, so a flexible method is adopted.
2. The interface cannot be found.
When calling the JNI interface in Java, an exception occurs. Check the log and find the following error:
WARN/dalvikvm (422): No implementation found for native Lcom/whty/wcity/HelixPlayer;. setDllPath (Ljava/lang/String;) V
After checking the code several times, Cpp does define this interface and carefully compares the Java package name and class name. There is indeed no error. Why is this problem. Later, I suddenly thought that the JNI interfaces were all defined in the form of C. Now I am using C ++. Do I need to add extern C before the function definition? A header file is defined to include this header file in the CPP file. The header file is added with the following code snippet:
# Ifdef _ cplusplus
Extern C {
# Endif
# Endif
...
# Ifdef _ cplusplus
}
Try again. The call is successful!