編輯:關於Android編程
錯誤一:
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.
該錯誤是將showmap_opengles_OpenGLESRenderer.c改成showmap_opengles_OpenGLESRenderer.cpp後出現,當然android.mk文件中也作了相應修改
刪除 obj 文件夾,估計是有緩存信息導致去找showmap_opengles_OpenGLESRenderer.c而沒找到。
錯誤二:
一 javah引發的問題
BUG:
D/dalvikvm( 1704): Trying to load lib /data/data/com.ulang/lib/libulangaudio.so 0x41052a38
D/dalvikvm( 1704): Shared lib '/data/data/com.ulang/lib/libulangaudio.so' already loaded in same CL 0x41052a38
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.performClick(View.java:3480)
E/AndroidRuntime( 1704): at android.view.View$PerformClick.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)
發現第二個參數 javah生成為 jclass, 因此出錯 ,
要將其換成 jobject則可以.
Javah並不是所有情況都將第二項生成 jclass, 有時也是生成的jobject.
NE:要特別注意!
#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
二
在確認以上兩點後,JNI接口調用的no implementation error沒有出現了。
(2)運行c++生成的.so庫,若報以下錯誤:(既找不到函數)
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)
解決方法:
為供Java調用的c++函數前加入extern C 修飾,如:(NDK example裡面的cpp文件也是這麼聲明的,參考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++); }原因是:
被extern C修飾的變量和函數是按照C語言方式編譯和連接的。
首先看看C++中對類似C的函數是怎樣編譯的:作為一種面向對象的語言,C++支持函數重載,而過程式語言C則不支持。函數被C++編譯後在符號庫中的名字與C語言的不同。例如,假設某個函數的原型為:void foo( int x, int y );該函數被C編譯器編譯後在符號庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了相同的機制,生成的新名字稱為“mangled name”)。_foo_int_int這樣的名字包含了函數名、函數參數數量及類型信息,C++就是靠這種機制來實現函數重載的。例如,在C++中,函數voidfoo( int x, int y )與void foo( int x, float y )編譯生成的符號是不相同的,後者為_foo_int_float。
同樣地,C++中的變量除支持局部變量外,還支持類成員變量和全局變量。用戶所編寫程序的類成員變量可能與全局變量同名,我們以.來區分。而本質上,編譯器在進行編譯時,與函數的處理相似,也為類中的變量取了一個獨一無二的名字,這個名字與用戶程序中同名的全局變量名字不同。
因此,若我們沒有使用extern C修飾函數,按照C語言方式編譯和連接,Jni調用將可能找不到該函數。
錯誤三:
JNI 調用時,一直報 No implementation found for native
有一個可能是,如果調用的是C++的代碼,必須加extern C
【轉】 jni 調用c和c++的區別.
1、JNIEnv *env參數的使用
所有JNI接口的第一個參數是JNIEnv *env, 在C中,使用方法是
(*env)->NewStringUTF(env, Hello from JNI!);
但在C++中,其調用方法是
env->NewStringUTF(Hello from JNI!);
為什麼有這種區別呢,看看jni.h中關於JNIEnv的定義就可以知道了:
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
#else
typedef const struct JNINativeInterface* JNIEnv;
#endif
可以看到,對於C和C++,定義有所不同,主要原因是C不支持類,所以采用了一種變通的方法。
2、接口找不到
在Java中調用JNI接口時,出現異常,察看日志,發現有如下錯誤:
WARN/dalvikvm(422): No implementation found for native Lcom/whty/wcity/HelixPlayer;.setDllPath (Ljava/lang/String;)V
檢查了幾遍代碼,Cpp中確實定義了這個接口,而且仔細對照了Java的包名、類名,確實沒有錯誤,那為什麼會出現這種問題呢。後來突然想到,JNI接口 都是以C的方式定義的,現在使用C++實現,函數定義前是否需要加上extern C呢?為此定義了一個頭文件,在CPP文件中include該頭文件,頭文件加上如下代碼片斷:
#ifdef __cplusplus
extern C {
#endif
#endif
...
#ifdef __cplusplus
}
再次嘗試,調用成功!
在Android 5.0之前,雖然也有手機是雙卡手機,但是雙卡方案都是ODM廠商自己做的,或者是有芯片廠商提供的源碼完成。因此,如果要在4.4甚至更早之前的手機上獲取雙卡
這篇博客我們來一發自定義控件的實戰,恰好前些天有一個小需求,效果圖如下:??根據效果圖,我們可以確定,用自定義View完全可以搞定,在自定義控件系列博客第一篇中,我們總結
在使用Jni之前,我們需要對android studio進行一些配置:有網的時候:在設置 - plugin - Android NDK Support 勾選--insta
AsyncTask的隱蔽陷阱先來看一個實例這個例子很簡單,展示了AsyncTask的一種極端用法,挺怪的。復制代碼 代碼如下:public class AsyncTask