準備工作:
- JDK安裝
- Eclipse 安裝(包括ADT插件)
- Andorid SDK 下載安裝
- Android NDK 下載安裝
注:NDK版本在r7以上之后就集成了Cygwin伍俘,而且還是十分精簡版勉躺,已經不需要單獨安裝Cygwin
第一個Demo
- 新建一個Android工程,然后在工程上右鍵點擊Android Tools->Add Native Support… 妨退,然后給我們的.so文件取個名字,例如我的是:FirstNDK,這時候工程就會多一個jni的文件夾碧注,jni下有Android.mk和FirstNDK.cpp文件。Android.mk是NDK工程的Makefile轩端,F(xiàn)irstNDK.cpp就是NDK的源文件。
(關于 Android.mk 的說明可以參考資料:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/13/2137577.html)
JNI接口的命名規(guī)范是:Java_ + 調用該方法的包名(包名的點用代替) + + 調用該接口的類名 + _ + 方法名基茵,對于實例方法壳影,有兩個參數(shù)是必要的,一個JNI的環(huán)境指針JNIEnv *宴咧,另一個是調用該方法的Java實例jobject
接下來編輯FirstNDK.cpp文件,寫一個FirstNDK的demo掺栅,代碼如下:
#include <jni.h>
extern "C"{
jstring
Java_com_example_firstndk_MainActivity_getStringFromJNI(JNIEnv* env, jobject thiz)
{
//返回一個字符串給Java層
return env->NewStringUTF("Hello from JNI.");
// return (*env)->NewStringUTF(env, "Hello from JNI.")
}
}
- 然后在MainActivity調用我們剛剛編寫的FirstNDK,代碼如下:
public class MainActivity extends Activity {
Button btn;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
tv = (TextView) findViewById(R.id.text);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
tv.setText(getStringFromJNI() );
}
});
}
public native String getStringFromJNI();
static {
System.loadLibrary("FirstNdk");
}
}
完成了桃笙,然后運行沙绝。運行時會先編譯NDK,然后在編譯JAVA代碼闪檬。
問題與解決
問題1:編譯也許會遇到Unable to launch cygpath. Is Cygwin on the path?
解決方法:
1.工程右鍵,點Properties->C/C++ Build的Building Settings中去掉Use default build command强饮,然后輸入${NDKROOT}/ndk-build.cmd
2.在C/C++ Build中點擊Environment,點Add...添加環(huán)境變量NDKROOT,值為NDK的根目錄
3.再編譯行您,問題就解決啦!
問題2:運行時崩潰娃循,遇到java.lang.UnsatisfiedLinkError
解決方法: 在C++文件中函數(shù)定義用extern "C"修飾
原因是:使用extern "C"修飾,編譯器會按C語言的方式編譯和連接。在C語言中泉沾,函數(shù)編譯之后函數(shù)名與C++函數(shù)編譯之后不同妇押,例如foo(int x, int y),C可能會編譯成_foo的名字,而C++因為支持重載敲霍,所以會編譯成像_foo_int_int這種帶參數(shù)的函數(shù)名。如果是按照C語言的編譯方式肩杈,調用foo函數(shù)是找不到_foo的函數(shù)名就會報出函數(shù)名找不到的錯誤。所以要添加extern "C"修飾扩然。
問題3:Method 'NewStringUTF' could not be resolved 問題
因不想使用extern "C"修飾, 所以將FirstNDK.cpp改為FirstNDK.c夫偶,
同時將c++寫法 env->NewStringUTF("HelloWorld from JNI.") 改為 c寫法 (*env)->NewStringUTF(env, "Hello from JNI.")
遇到Method 'NewStringUTF' could not be resolved 問題
解決方法:右鍵工程 property->C/C++ General->Code Analysis—>配置當前工程(或者workspace)->使 method cannot be resolved 不選中(即此項不進行報錯 )