从何说起?
昨天算是真正的带妹子入坑了,这不,又给我买奶茶了。 But,路漫漫其修远兮,没过两天,妹子就又来找我了。“Q哥,我最近碰到一些问题,麻烦你帮我看一下呗”? 妹子是个聪明人,又补充道“餐厅新开了一家麻辣烫,下班请你吃”。呵,我大丈夫岂能为了份麻辣烫而折腰?“有冰封没?”,我问道。俗话说,人不要脸,天下无敌,为了不辜负妹子的厚望,我决定拿出久封的必杀秘籍,“NDK排错指南”。
正文
问题1:QT 无法在android环境下导出事件循环,导致信号槽无法使用,QTSocket无法使用
解决方案:so 库的运行线程取决于上层调用方的线程,但是 so 库内部也可以创建工作线程,因此需要上层对so库返回的内容处理(尤其是工作线程的回调)
问题2:UDP/TCP 等接受数据时 char* 转 std::string 不指定长度会偶现被\0截断
解决方案:1、使用QT封装类QByteArray 2、指定数据长度
问题3:ndk默认char为无符号,和windows不一致,导致在计算校验和时在不同平台表现不一致
解决方案:设置gcc选项,指定ndk默认char为有符号,和windows一致
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char")
问题4:linux下setsocket 有个入参是 (void*),结果传入 bool值,在windows OK,但是因为是 C 函数,导致在linux下入参错误,UDP 无法广播
解决方案:不传bool,传入int值
问题5:Cmake 启用 C++ 17 支持 编译警告
解决方案:添加预定义宏:
add_definitions(-D _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING)
add_definitions(-D _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS)
问题6:编译so库时提示:C1128: 节数超过对象文件格式限制: 请使用 /bigobj 进行编译
解决方案:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /bigobj")
问题7:编译so库时报错:error: undefined reference to 'inflate'
解决方案:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lz")
问题8:编译so库时报错:error: undefined reference to 'bsd_signal'
解决方案:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ANDROID_API__=16")
问题9:编译的so库要支持5.0以上
解决方案:修改变量 D__ANDROID_API__ > 20
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ANDROID_API__=21")
问题10:编译的so库体积太大
解决方案:so 库体积优化
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections -s -Ofast")
问题11:java.lang.UnsatisfiedLinkError: dlopen failed: library “libtest.so” not found
解决方案:这个问题有好几种原因:
- 运行的设备和库的abi不匹配
- android 代码中load时写错库的名字
- 有多个 abi 文件夹,但是库的数量不一致
- gradle 中的 abiFilters 和实际文件夹不匹配
- System.loadLibrary 时带上了so库的"lib"前缀
- 编译 so库的时候看看 cmake 有没有将所有的头文件和 cpp 文件add_executable 进去
- 尝试使用其他版本(建议使用更高的版本)的ndk去编译so库
- 自己编译的so库还有其他的依赖库没有拷贝
其他的具体问题具体分析了。
问题12:IOS 锁屏或者进入后台后 so库的 socket 被系统干掉,导致无法发送数据
解决方案:在 app 进入后台时杀死 socket,进入前台重新创建 socket 对象,SO_LINGER 选项可以保证端口立即被释放,不然端口不能被立即释放,可能会停留在 time_wait。
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
int ret = setsockopt(usock,SOL_SOCKET, SO_LINGER,(const char *) &linger,sizeof(linger));
问题13:int 、bool等默认值在android和windows下不一致
解决方案:int、bool等基础类型进行初始化,不然编译器会给它搞个非法值
问题14:默认情况下ndk不支持C++异常捕获
解决方案:设置开启异常支持
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
问题14:Android api24以下getifaddr 和 freeifaddrs 函数缺失
解决方案:
1、 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ANDROID_API__=24")
2、手动添加这两个函数(可从网上下载)
问题15:提前掌握tcdump adb抓包
解决方案:
#手机需要root。
#清除文件
adb shell rm /sdcard/capture.pcap
#推送tcpdump到手机
adb push D:/tcpdump /data/local/tcpdump
cd /data/local
#开始监听
./tcpdump -i any -p -s 0 -w /sdcard/capture.pcap
#拉取抓包文件使用wireshark打开
adb pull /sdcard/capture.pcap
注意:不能在shell下执行这个命令
如果提示:adb: error: failed to copy 'tcpdump' to '/data/local/tcpdump': remote Permission denied
首先进入此目录,su ,root用户,chmod赋予权限,然后再从shell出来,执行push
问题16:Android api24以下getifaddr 和 freeifaddrs 函数缺失
解决方案:
1、 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__ANDROID_API__=24")
2、手动添加这两个函数(可从网上下载)
附上下载地址:
ifaddrs 下载地址:https://download.csdn.net/download/u012534831/12495592
问题17:JNI 报错 More than one file was found with OS independent path 'META-INF/ASL2.0'
解决方案:这是因为引用的jar包里面的 asl2.0 协议冲突,需要删掉一个。 找见两个冲突的jar包,解压jar包,找见jar文件中META-INF下的ASL2.0文件,.删除掉ASL2.0文件,在打包剩下的文件,最后把.zip的后缀换成.jar,拖到项目运行。
问题18:JNI 报错 More than one file was found with OS independent path 'META-INF/ASL2.0'
解决方案:这是因为引用的jar包里面的 asl2.0 协议冲突,需要删掉一个。 找见两个冲突的jar包,解压jar包,找见jar文件中META-INF下的ASL2.0文件,.删除掉ASL2.0文件,在打包剩下的文件,最后把.zip的后缀换成.jar,拖到项目运行。
问题19:qtcreator for android: 报错:D:\Java\android-ndk-r20/toolchains/x86-4.9/prebuilt/windows-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin\ld: error: cannot find -lc++
解决方案:来到红框目录下,将libc++.so.16复制一份重命名为libc++.so。
问题20:Android studio 中 sdk-tools 中没有 cmake 选项
解决方案:取消http代理(选择:no proxy)
暂时记录这么多,后面持续补充。
如有帮助,请多多点赞支持