Android NDK使用常见错误

Andorid NDK使用简要的流程【来源于Android NDK文档中的 OVERVIEW.txt】

Here’s a very rough overview of how you can develop native code with the Android NDK:

1/ Run build/host-setup.sh to configure the NDK
2/ Place your native sources under $PROJECT/jni/…
3/ Write $PROJECT/jni/Android.mk to describe your sources to the NDK build system
4/ Write apps/<myapp>/Application.mk to describe your application and the native sources it needs to the NDK build system
5/ Build your native code by running “make APP=<myapp> ” in the top-level NDK directory.

The last step will copy, in case of success, the stripped shared libraries your application needs to your application’s root project directory. You will then need to generate your final .apk through the usual means.

按照上述步骤,我们说明在每一步中可能存在的错误【第一步,我们就不在这里详细说了,网上有很多不错的文章】。

常见错误说明:

1、make:*** No rule specified and no make file found. Stop.

1
错误的原因估计是(cat : Linux命令,显示文件的内容):工程名与Aplication.mk中的APP_MOUDLES不一致。

2

2、make: *** No rule to make target “XXXXXX”, needed by “ndk-app-XXXXX”. Stop.

3

这个错误的主要原因是:编译C文件为最后的so库文件需要2个文件:Application.mk、Android.mk,如下图所示:

4

MK文件如何设置,看了上面的图一目了然【详细的说明还是要去看文档】,以下几点需要注意:

  • 文件的相对路径是否正确(Application.mk中的APP_PROJECT_PATH设置相对路径),如下图所示:5
    这些在Android NDKzhong 都有“严格”规范的,在android-ndk的文档中都有详细说明。
  • 工程文件名、Aplication.mk中的APP_MOUDLES、Android.m中的LOCAL_SRC_FILES是否完全一致。Android.m中的LOCAL_SRC_FILES是输出库文件的名称【NDK会默认的加上前缀lib(如果LOCAL_SRC_FILES中已经是以lib开头就不添加),以及后缀.so】,但是尝试后发现这个地方必须与Aplication.mk中的APP_MOUDLES一致,否则就会导致上述错误。

3、make: ***[XXXX]Errror 1

6

这个错误只要大家仔细看下就明白是C 的编译错误,C 代码无法编译。

如何编写C文件【native file】中的函数说明?从Java Source File推导出C/C++ Native File,可以参考以下4步:

1) 编译java文件【Java sources:包含我们需要的native函数】,如下图所示:

7

2) 使用命令javac JNITest.jva && javah JNITest,命令运行后增加了2个文件:

8

JNITest.jva编译后的文件JNITest.class、JNITest.h,这个文件就是我们需要的头文件,如下图所示:

9

3) 修改函数名,如何修改?我们先分析Android-NDK中的例子程序:

10

从上面的例子发现,函数名分为4部分:13

按照上面的规则修改就可以了。

4) 将上面的函数声明拷贝出来,在jni文件中创建一个*.c文件,按照上述函数结构实现函数,如下图所示:

11

这样我们就从Java Source File一步一步的得到C/C++ Native File

4、程序运行时崩溃,这个时候我们需要注意以下几个问题:

库文件的加载

12

编译后的so文件是libJNITest.so,而实际加载的库文件名是: JNITest【这实际上是Unix的“规范”,在Android NDK的文档OVERVIEW.txt中有详细说明】;还有Linux系统区分大小写的,所以如果上面的代码中,将加载的库文件名写成jnitest,也会导致运行崩溃。