Android NDK开发(三)——常见错误集锦以及LOG使用,androidndk

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41826511 

Android NDK开发经常因某些因素会出现一些意想不到的错误,很多时候调试这些错误的时候,显得比调试Java代码要复杂,一方面是导致错误的原因很多很杂,另一方面NDK开发涉及到C/C++代码的编写,很多程序员对此不熟悉。那么这篇博客就总结一下,在NDK开发中经常出现的一些问题,并且尝试提供一些正确的解决方案,方便在开发时能够快速定位到错误,更改错误,当然了,错误是多种多样的,很难把所有的错误都总结出来,在这里仅作为一个笔记吧,以后在NDK开发中发现一个错误或者解决一个错误后,我就在这里记录一下,日积月累,就不错了!

常见错误及解决方法

1,Android.mk文件不存在

错误描述: Android NDK: Your APP_BUILD_SCRIPT points to an unknown file: ./jni/Android.mk  
                   /cygdrive/e/ndk/android-ndk-r10d/build/core/add-application.mk:199: *** Android NDK: Aborting...    。 停止。

解决方法:报这个错误就需要查看一下工程目录下的jni目录下,是否有Android.mk文件,或者Android.mk文件名是否输入错误了。

2,Android.mk文件配置出错

错误描述:/cygdrive/e/ndk/android-ndk-r10d/build/core/build-shared-library.mk:23: *** Android NDK: Missing LOCAL_MODULE before including                                                                    BUILD_SHARED_LIBRARY in jni/Android.mk    。 停止。

解决方法:检查Android.mk文件配置信息。Missing LOCAL_MODULE表明LOCAL_MODULE配置出错,查看并修正。

3,C语言代码有错误

错误描述:[armeabi] Compile thumb  : Hello <= Hello.c
                    jni/Hello.c: In function 'Java_com_example_ndk_MainActivity_java_1From_1JNI':
                    jni/Hello.c:17:9: warning: division by zero [-Wdiv-by-zero]
                    int i=5/0;
                              ^
                    [armeabi] SharedLibrary  : libHello.so
                    [armeabi] Install        : libHello.so => libs/armeabi/libHello.so

解决方法:C语言报错通常错误信息很多,我们可以根据cygwin上的LOG定位到错误。

4,Java代码中没有找到C代码库


错误描述: AndroidRuntime(1171): java.lang.UnsatisfiedLinkError: Couldn't load Hello1 from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.ndk-1.apk"],nativeLibraryDirectories=[/data/app-lib/com.example.ndk-1, /system/lib]]]: findLibrary returned null

解决方法:说明Java代码在加载C代码库的时候弄粗了C代码库的名称,请在java层中改正。

5,C代码函数签名错误

错误描述:java.lang.UnsatisfiedLinkError: Native method not found: com.example.ndk.MainActivity.java_From_JNI:()Ljava/lang/String;

解决方法:Native method not found。这个应该不难吧,一看就知道是C语言中的函数签名出错了。

6,ndk版本问题

错误描述:Android NDK: WARNING: APP_PLATFORM android-19 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml
                    [armeabi] Compile thumb  : Hello <= Hello.c
                    [armeabi] SharedLibrary  : libHello.so
                    [armeabi] Install        : libHello.so => libs/armeabi/libHello.so

解决方法:这只是一个警告而已,不处理的话程序也照样运行。导致这个警告的原因是当前ndk的版本>工程中minSdkVersion,想要去掉这个警告就将minSdkVersion支持的最小版本号改成ndk版本号一致,当然了这是愚蠢的做法,但是我们可以使用ndk的低版本编译,也不太好。下面是个好的解决方法:

1,在工程目录jni下建立一个新的文件,文件名是 Application.mk

2,在Application.mk文件里加上这样的一句:

APP_PLATFORM := android-8

3,保存工程,编译一下,就看见这个警告没有了。

7,使用javah命令生成函数签名时,找不到class文件

错误描述:错误: 无法访问android.app.Activity
                              找不到android.app.Activity的类文件

解决方法:这个错误的具体原因应该没有找到对应的native方法所在的Java字节码文件,但是我这里确实路径是正确,还是报错了,很奇怪,不知道是不是Eclipse上的一个BUG。遇到这个问题时,可以这样解决,既然切换到\bin\classes目录下不行的话,那就切换到工程目录\src目录,再javah一下,这次居然生成了.h的头文件,不知道为什么这样,反正我测试的时候可行。

tip:获得本地方法头文件 
jdk6.0:在Android工程的bin\classes目录下执行:javah 包名+类名
jdk7.0:在Android工程的src目录下执行:javah 包名+类名

8,中文乱码问题

错误描述:ndk开发中经常会在C语言代码中往Java代码返回一个中文字符串,偶尔在Java中调用的时候,程序结果会出现中文乱码情况,或者更有甚者导致程序直接崩溃掉,查看Log日志也是说明出现乱码的情况。

解决方法:

中文乱码的原因是英文C语言文件保存的格式不是UTF-8的格式,或者整个工程都不是UTF-8的格式,因为C语言jni传递字符串时采用的UTF-8编码,这一点可以在(*env)->NewStringUTF(env, "hello jni!")看出,NewStringUTF(env,char*)这个方法说明返回的是UTF-8编码形式的字符串。所以我们在建立工程的时候,或者新建一个C语言代码文件的时候,需要指定工程编码为UTF-8或者C语言代码文件的保存格式是UTF-8。

9,编码GBK的不可映射的字符

错误描述:编码GBK的不可映射字符。

解决方法:引起这个错误的原因是使用javah时没有指定java的编码集,这种情况下编译器自动根据windows默认的编码(GBK)编译,而Java支持UTF-8的编码集。解决这个问题的方法是在javah命令执行时为编译器指定一个编码集,使用javah命令的参数-encoding 编码集,如图

LOG日志的使用

上面列举了一些ndk开发中经常会遇见的问题以及解决方法,但是唯独没有列出的,也是最常见的错误,就是C语言代码中出现错误,这个不太好解决,而且出现的问题是各种各样,具体情况具体对待。已知在使用Java开发Android程序时,Google为了方便程序员调试,在SDK中提供了LOG输出功能,程序员用来输出程序中的日志使用。那么庆幸的是,Google在NDK中也提供了类似的LOG机制,帮助native层代码错误的定位。下面就尝试一下使用这个LOG机制。

在ndk解压目录下platforms\android-8\arch-arm\usr\include\android有个log.h的头文件,这个log.h的头文件用来管理C语言代码中的LOG输出,代码如下:

#ifndef _ANDROID_LOG_H
#define _ANDROID_LOG_H#include <stdarg.h>#ifdef __cplusplus
extern "C" {
#endif/** Android log priority values, in ascending priority order.*/
typedef enum android_LogPriority {ANDROID_LOG_UNKNOWN = 0,ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */ANDROID_LOG_VERBOSE,ANDROID_LOG_DEBUG,ANDROID_LOG_INFO,ANDROID_LOG_WARN,ANDROID_LOG_ERROR,ANDROID_LOG_FATAL,ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
} android_LogPriority;/** Send a simple string to the log.*/
int __android_log_write(int prio, const char *tag, const char *text);/** Send a formatted string to the log, used like printf(fmt,...)*/
int __android_log_print(int prio, const char *tag,  const char *fmt, ...)
#if defined(__GNUC__)__attribute__ ((format(printf, 3, 4)))
#endif;/** A variant of __android_log_print() that takes a va_list to list* additional parameters.*/
int __android_log_vprint(int prio, const char *tag,const char *fmt, va_list ap);/** Log an assertion failure and SIGTRAP the process to have a chance* to inspect it, if a debugger is attached. This uses the FATAL priority.*/
void __android_log_assert(const char *cond, const char *tag,const char *fmt, ...)
#if defined(__GNUC__)__attribute__ ((noreturn))__attribute__ ((format(printf, 3, 4)))
#endif;#ifdef __cplusplus
}
#endif#endif /* _ANDROID_LOG_H */

上面的代码看不懂也没关系,我们只需要知道怎么用就行了。

1,在C语言代码中引用log.h的头文件,并且预定义LOG_TAG标记Tag名称,预定义输出规则:

2,用上面预定义的名称定义LOG输出的内容

#include<stdio.h>
#include<jni.h>
#include"com_example_ndk_MainActivity.h"
#include <android/log.h>
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)JNIEXPORT jstring JNICALL Java_com_example_ndk_MainActivity_javaFromJNI(JNIEnv* env, jobject obj) {return (*env)->NewStringUTF(env, "hello jni!");
}/** Class:     com_example_ndk_MainActivity* Method:    java_From_JNI* Signature: ()Ljava/lang/String;*/
JNIEXPORT jstring JNICALL Java_com_example_ndk_MainActivity_java_1From_1JNI(JNIEnv* env, jobject obj) {LOGI("function called");LOGI("array init");char c1[3] = { 'a', 'b', 'c' };char c2[2] = { 'd', 'e' };LOGI("array init finish");LOGI("copy array");strcat(c1, c2); //把c2的内容放在c1的后面,要求c1长度>c2长度LOGI("copy array finish");return (*env)->NewStringUTF(env, "hello_jni__");
}

上述的代码中

#include <android/log.h>
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

是必须添加的,告诉编译器这里需要输出LOG,LOG的TAG标记是“System.out.c”,并且预定义LOGD(...)代表Debug输出,LOGI(...)代表Info输出。然后在C语言主题代码中就可以使用LOGD和LOGI了,传递字符串就可以了,需要注意的是传递的字符串要用英文字符,不支持中文。

3,在Android.mk文件中配置LOG输出

    LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE    := HelloLOCAL_SRC_FILES := Hello.cLOCAL_LDLIBS += -lloginclude $(BUILD_SHARED_LIBRARY)

注意:就一句 LOCAL_LDLIBS += -llog 就行了,但是必须得加在 include $(BUILD_SHARED_LIBRARY) 之前。

4,重新编译代码,运行看看效果

好了,我们在Logcat里面过滤出来System.out.c的TAG,可以看到在输出copy array之后程序停止了,说明LOGI("copy array");下面的strcat(c1, c2);出现了错误,这里需要修改代码中的错误,程序才能正确执行,是不是很方便啊?试试吧!

转自:http://www.bkjia.com/Androidjc/934212.html

Android NDK开发(三)——常见错误集锦以及LOG使用,androidndk相关推荐

  1. Android NDK开发Crash错误定位

    在Android开发中,程序Crash分三种情况:未捕获的异常.ANR(Application Not Responding)和闪退(NDK引发错误).其中未捕获的异常根据logcat打印的堆栈信息很 ...

  2. 安卓逆向_15( 三 ) --- Android NDK 开发【 jni 静态注册、JNI_OnLoad 动态注册】

    Android Studio开发JNI示例:https://blog.csdn.net/wzhseu/article/details/79683045 JNI_动态注册_静态注册.zip : http ...

  3. Android NDK开发从0到1

    本文的开发环境为 Windows,其他平台操作类似 其实说到 NDK 就不得不提 JNI ( Java Native Interface ) ,JNI 是专门用来与本地代码进行交互而提供的一个接口.通 ...

  4. OpenCV android sdk配置OpenCV android NDK开发实例

    OpenCV android sdk配置OpenCV android NDK开发实例 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/det ...

  5. Android NDK开发: 通过C/C++调用第三方so库

    文章目录 一.编写so库代码 二.安装Android NDK 三.编译so库 3.1 编辑Android.mk 3.2 编辑Application.mk 3.3 编译 四.集成到Android工程中 ...

  6. 使用CMake来进行Android NDK开发

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 前言 Android NDK开发可能在平时的项目开发中不常用到,但是这并不代表其不重要, 相反NDK开发是Android开发人员的进 ...

  7. Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

    Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发 (码字不易,转载请声明出处:http://blog.csdn.NET/andrex ...

  8. 【Android NDK 开发】Android.mk 配置动态库 ( Android Studio 配置动态库 | 动态库加载版本限制 | 本章仅做参考推荐使用 CMake 配置动态库 )

    文章目录 I . Android Studio 中使用 Android.mk 配置动态库 总结 II . 第三方动态库来源 III . 配置 Android.mk 构建脚本路径 IV . 预编译 第三 ...

  9. 【Android NDK 开发】JNI 方法解析 ( JNIEnv *env 参数 )

    文章目录 一. JNI 方法解析 二. JNIEnv *env 参数解析 三. C 语言 环境中 JNIEnv *env 参数解析 四. C ++ 环境中 JNIEnv *env 参数解析 总结 : ...

最新文章

  1. python hashlib模块_python-hashlib模块
  2. JAVA序列化和反序列化
  3. ubuntu路由器联网_路由器及其协议简介| 联网
  4. 神经网络“炼丹炉”内部构造?牛津大学博士小姐姐用论文解读
  5. 大学计算机ppt制作步骤,PPT制作教程步骤方法_PPT制作技巧教程快捷键_PPT制作基础教程...
  6. JDK动态代理和CGLIB动态代理介绍
  7. 神经网络准确率计算公式,神经网络计算复杂度
  8. 360安全桌面没有计算机了,360安全卫士桌面上的图标不见了怎么办
  9. Unity Recorder屏幕录制问题
  10. 计算机开机出现代码卡顿,电脑开机后很卡怎么办
  11. 163邮箱苹果设置不成功_怎么样才能让自己服务器发出的邮件不被 Gmail、Hotmail、163、QQ 等邮箱放入垃圾箱...
  12. 免费截图工具PicPick 2.1.2绿色版
  13. [转]使用jenkins实现持续集成
  14. 【加装固态硬盘】联想小新Air15-IKBR 2018款加装固态硬盘教程
  15. fik在计算机领域英语缩写,计算机常用英语词汇表
  16. c语言 while 阶乘之和,c语言阶乘之和问题示例详解
  17. 理论:引导过程与服务控制 (解决root密码忘记问题、不能正常开机)
  18. 团队任务3:每日立会(2018-10-23)
  19. excel文件.xlsx操作 openpyxl 笔记
  20. 不容错过的20亿像素珠穆朗玛峰图

热门文章

  1. Webots 机器人仿真平台(二) 与ROS通讯
  2. 电解电容与固态电容全面对比分析
  3. 2021旅游调查:六成海外受访者愿为旅行弃用社交媒体一个月
  4. da转化输出不同波形8086和DAC0832的Proteus仿真
  5. 网上兼职打字员日结是真的吗?网友是如何步步入坑的?
  6. JRebel最新破解激活版(IDEA自动部署插件)
  7. Swin UNETR: Swin Transformers for Semantic Segmentation of Brain Tumors in MRI Images
  8. 一种应用于工业4.0新制造的室内定位解决方案
  9. 泰勒展开 — Taylor Expansion
  10. VisualStudio之模板的使用与删除