NDK撩妹三部曲(三)—美女,我看你婀娜多姿,宛若天仙,這本“ndk排錯指南”就送你了

從何說起?

  昨天算是真正的帶妹子入坑了,這不,又給我買奶茶了。
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

如有幫助,請多多點贊支持

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章