Android NDK 開發
說到 NDK 開發,其實是為了有些時候為了項目需求需要調用底層的一些 C/C++ 的一些東西;另外就是為了效率更加高些。Google主力推動 Android Studio 這個是個不錯的工具,至少現在來看在 Eclipse 上能做到的 這邊都有,這邊有的Eclipse上不一定有。但是為了複習,兩個IDE都記錄一下。
準備工作
去官網下載NDK,這個需要翻牆,下面發放福利了。
http://yunpan.cn/cdFTKe3Ty4D9e 訪問密碼 6776(Android-ndk-r10e0) http://yunpan.cn/cdFTQAmSAI9sY 訪問密碼 f594(我下載的翻牆工具,勉強過得去)
下載好了ndk,雙擊解壓到目前的目錄,貌似時間有點忽悠人,耐心等待一下。接下來我們可以開始NDK開發了。之前我們可以去ndk目錄下找samples,找官網給的例子。學習ing中……先從Eclipse開始吧。
一、Eclipse DNK開發
1、建立一個項目HelloNDK
在Activity 中寫一個native方法
public class MainActivity extends Activity { static{ System.loadLibrary(hello); } /** * native * @return */ public static native String getStringFromC(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView text = (TextView) findViewById(R.id.textView); text.setText(getStringFromC()); }}
寫好了native方法後。來到java目錄,執行javah命令,產生c/c++所需要的標頭檔xxx.h
-classpath 是項目bin目錄下class檔案
-d 輸出目錄(jni,是我剛才在工程目錄下建好的jni檔案夾)<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;">**xxx/xxx/xxx.h檔案**extern C {/* * Class: com_example_jnindk_MainActivity * Method: getStringFromC * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_jnindk_MainActivity_getStringFromC (JNIEnv *, jclass);#ifdef __cplusplus}
之後去官網的例子jni檔案夾把Android.mk,application.mk複製到現在的工程jni檔案夾。
Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := helloLOCAL_SRC_FILES := hello.cinclude $(BUILD_SHARED_LIBRARY)
注意LOCAL_MODULE本地的moduleName。LOCAL_SRC_FILES本地寫的c檔案。
2、我們在jni檔案夾中寫一個hello.c檔案
#include#include#include com_example_jnindk_MainActivity.hJNIEXPORT jstring JNICALL Java_com_example_jnindk_MainActivity_getStringFromC (JNIEnv * env, jclass jclass){ return (*env)->NewStringUTF(env, Hello from the world !);};
返回一個字串。仔細看類名,第一個是Java,接下是包名+類名+方法名。這裡包名跟我cmd中寫的類名不一樣,失誤,上面是我隨便寫的,注意一下就可以。
3、產生so檔案
成功後會在工程目錄產生一個obj檔案夾,這裡可以找到so檔案。
做過百度地圖的朋友們有沒有看到so,感到很親切。接下我們就去Maintivity中調用了。
static{ System.loadLibrary(hello); }
測試通過。
二、下面把NDK開發切換到Android studio下。
前面的步驟差不多,只是不需要我們敲命令去產生so檔案,我們在build.gradle中去配置就可以了。
注意ndk的位置,defaultConfig下面。
ndk的位置
剛在Eclipse中我們手動命令產生so檔案,as只需要配置重新build的時候這個so檔案產生都哪兒去了呢。請看。
看lib,so檔案移植到這麼多的APP_ABI裡面。這是如何做到的,我們發現application.mk中的配置。和build.gradle中ndk的配置。
APP_ABI := APP_ABI := armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64APP_PLATFORM := android-
三:錯誤總結
1、`Error:Execution failed for task ‘:app:compileDebugNdk’.
com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process ‘command ‘D:Usershtj-123AppDataLocalAndroidandroid-ndk-r10b dk-build.cmd” finished with non-zero exit value 2`
這個是我工程目錄有空格導致的。
2、Process: com.eddie.ndk, PID: 23210
java.lang.UnsatisfiedLinkError: Native method not found: com.eddie.ndk.MainActivity.getStringFromC:()Ljava/lang/String;
1) Android.mk裡面:
最後產生的時候
LOCAL_MODULE := testcmmb_jni 千萬不能寫成 libtestcmmb_jni!!!!雖然編譯出來的檔案名稱貌似相同
2) C++ 的代碼裡面:
extern “C”{
。。。
}
這是因為產生的二進位檔案中,C和C++的符號表不相同造成的。Jni是按照C的建置規則去找函數的, 所以要加上extern C使編譯器把函數按照C的規則編譯 這樣才能被JAVA調用