今天终于将第一个 Android NDK 程序编译、运行成功
今天终于将第一个 NDK 程序编译、运行成功。
起先看资料和书籍时,都要求安装 CygWin。我也安装了,并将 Sample: hello-jni 编译成功。编译的 LOG 如下:
LeoZheng@LeoZheng-PC /cygdrive/d/Android-Linux/android-ndk-r10c/samples/hello-jni
$ ../../ndk-build
[arm64-v8a] Gdbserver : [aarch64-linux-android-4.9] libs/arm64-v8a/gdbserver
[arm64-v8a] Gdbsetup : libs/arm64-v8a/gdb.setup
[x86_64] Gdbserver : [x86_64-4.9] libs/x86_64/gdbserver
[x86_64] Gdbsetup : libs/x86_64/gdb.setup
[mips64] Gdbserver : [mips64el-linux-android-4.9] libs/mips64/gdbserver
[mips64] Gdbsetup : libs/mips64/gdb.setup
[armeabi-v7a] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi-v7a/gdbserver
[armeabi-v7a] Gdbsetup : libs/armeabi-v7a/gdb.setup
[armeabi] Gdbserver : [arm-linux-androideabi-4.6] libs/armeabi/gdbserver
[armeabi] Gdbsetup : libs/armeabi/gdb.setup
[x86] Gdbserver : [x86-4.6] libs/x86/gdbserver
[x86] Gdbsetup : libs/x86/gdb.setup
[mips] Gdbserver : [mipsel-linux-android-4.6] libs/mips/gdbserver
[mips] Gdbsetup : libs/mips/gdb.setup
[arm64-v8a x86_64 mips64 armeabi-v7a armeabi x86 mips] Cygwin : Generating dependency file converter script
[arm64-v8a] Compile : hello-jni <= hello-jni.c
[arm64-v8a] SharedLibrary : libhello-jni.so
[arm64-v8a] Install : libhello-jni.so => libs/arm64-v8a/libhello-jni.so
[x86_64] Compile : hello-jni <= hello-jni.c
[x86_64] SharedLibrary : libhello-jni.so
[x86_64] Install : libhello-jni.so => libs/x86_64/libhello-jni.so
[mips64] Compile : hello-jni <= hello-jni.c
[mips64] SharedLibrary : libhello-jni.so
[mips64] Install : libhello-jni.so => libs/mips64/libhello-jni.so
[armeabi-v7a] Compile thumb : hello-jni <= hello-jni.c
[armeabi-v7a] SharedLibrary : libhello-jni.so
[armeabi-v7a] Install : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
[armeabi] Compile thumb : hello-jni <= hello-jni.c
[armeabi] SharedLibrary : libhello-jni.so
[armeabi] Install : libhello-jni.so => libs/armeabi/libhello-jni.so
[x86] Compile : hello-jni <= hello-jni.c
[x86] SharedLibrary : libhello-jni.so
[x86] Install : libhello-jni.so => libs/x86/libhello-jni.so
[mips] Compile : hello-jni <= hello-jni.c
[mips] SharedLibrary : libhello-jni.so
[mips] Install : libhello-jni.so => libs/mips/libhello-jni.so
到实际编写自己的 NDK 程序时,才发现了如下一段话:
谷歌改良了ndk的开发流程,对于Windows环境下NDK的开发,如果使用的NDK是r7之前的版本,必须要安装Cygwin才能使用NDK。
而在NDKr7开始,Google的Windows版的NDK提供了一个ndk-build.cmd的脚本,这样,就可以直接利用这个脚本编译,而不需要使用Cygwin了。只需要为Eclipse Android工程添加一个Builders,而为Eclipse配置的builder,其实就是在执行Cygwin,然后传递ndk-build作为参数,这样就能让Eclipse自动编译NDK了。
具体的Eclipse配置 builder 的方法,就不说了,网上有现成的。如: http://www.cnblogs.com/yejiurui/p/3476565.html
D:\Android-Linux\workspace\NDKEumClick>
D:\Android-Linux\workspace\NDKEumClick\bin\classes>javah com.hs.leozheng.ndkeumclick.jniClick
生成的 .h 文件位于目录: workspace\NDKEumClick\bin\classes
com_hs_leozheng_ndkeumclick_jniClick.h
新建文件 com_hs_leozheng_ndkeumclick_jniClick.c,并输入代码。
Android.mk 的内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jniClick
LOCAL_SRC_FILES := com_hs_leozheng_ndkeumclick_jniClick.c
include $(BUILD_SHARED_LIBRARY)
完成后在 Android 中可以看到如下 Log:
Android NDK: WARNING: APP_PLATFORM android-21 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml
Android NDK: WARNING: Unsupported source file extensions in jni/Android.mk for module jniClick
Android NDK: com_hs_leozheng_ndkeumclick_jniClick.h
[armeabi] Install : libjniClick.so => libs/armeabi/libjniClick.so
调用 .so 的 Android 工程代码如下:
public class MainActivity extends ActionBarActivity {
static {
System.loadLibrary("jniClick");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String str = jniClick.AddStr("test", "test");
Log.i("NDK", "jni addStr function: " + str);
int ret = jniClick.AddInt(10, 6);
Log.i("NDK", "jni addInt function: " + Integer.toString(ret));
}
......
}
FATAL EXCEPTION: main
java.lang.UnsatisfiedLinkError: AddStr
at com.hs.leozheng.ndkeumclick.jniClick.AddStr(Native Method)
at com.hs.leozheng.ndkeumclick.MainActivity.onCreate(MainActivity.java:19)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
错误产生的原因:
在 Android.mk 错误的将 LOCAL_SRC_FILES 设置为头文件: com_hs_leozheng_ndkeumclick_jniClick.h
正确的应该是:
LOCAL_SRC_FILES := com_hs_leozheng_ndkeumclick_jniClick.c