從何說起?
昨天算是真正的帶妹子入坑了,這不,又給我買奶茶了。
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)
暫時記錄這麼多,後面持續補充。
csdn地址:http://blog.csdn.net/u012534831
github地址:https://github.com/qht1003077897
如有幫助,請多多點贊支持