### jni開發中的常見錯誤
#### 錯誤一 :java.lang.UnsatisfiedLinkError: Native method not found:(本地方法沒有找到原因)
- java.lang.UnsatisfiedLinkError: Native method not found:
- 1. 本地函數名寫錯,如果本地方法名中有下劃線“_”,則聲明時,.c文件中在最后一個下劃線后面加1,如以下代碼所示
如果不加1會出現以下錯誤
```
07-20 23:00:15.542: E/AndroidRuntime(1307): Caused by: java.lang.UnsatisfiedLinkError: Native method not found: com.wsc.jnihelloworld.MainActivity.hello_FromC:()Ljava/lang/String;
```

如果后面加1,如下圖所示
MainActivity.class中修改如下

hello.c中修改如下

再重新編譯生成.so文件,運行到模擬器上,正常運行
**虐心2**
如果遇到這種情況,方法名命名及其腦殘如下圖所示:

這時,人工修改本地函數名,很麻煩,這時可以使用javah -jni命令,生成頭文件
如果是jdk1.7版本則來到項目的src目錄下運行javah命令,如果是jdk1.6版本,則到項目的bin目錄下的class目錄下運行javah命令

盡管報了GBK錯誤,但是那是編碼格式的問題,不影響
本地方法聲明在哪一個類中,就把這個類的全類名拿來,復制粘貼到DOS中 javah 后面,在項目文件鼠標移動到該處,按住F5刷新一下,就會出現頭文件,打開可以看到

打開頭文件可以看到javah命令生成的頭文件

這樣就可以直接拿到本地函數名,不用人工修改本地函數名
- 2.忘記加載.so文件,沒有調用System.loadlibrary()
- System.loadlibrary()一般并不是調用它的時候才加載這個函數,可以在MainActivity中寫一個靜態代碼塊,MainActivity實例已創建,就加載.so文件
####錯誤二 : findLibrary returned null ####
- findLibrary returned null
- 1.加載動態鏈接庫時,動態鏈接庫名字寫錯
System.loadLibrary("libhello");//動態鏈接庫名字錯了
報錯如下
07-21 04:59:47.232: E/AndroidRuntime(1475): java.lang.UnsatisfiedLinkError: Couldn't load libhello from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.wsc.jnihelloworld-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.wsc.jnihelloworld-2, /system/lib]]]: findLibrary returned null
- 2.平臺類型錯誤,把只支持arm平臺的.so文件部署到了x86CPU的設備上
報錯如下
07-21 09:08:13.872: E/AndroidRuntime(1917): Caused by: java.lang.UnsatisfiedLinkError: Couldn't load hello from loader dalvik.system.PathClassLoader[dexPath=/data/app/com.wsc.jnihelloworld-1.apk,libraryPath=/data/app-lib/com.wsc.jnihelloworld-1]: findLibrary returned null
Application.mk 中有這樣一段話
By default, the NDK build system will generate machine code for the 'armeabi' ABI. This corresponds to an ARMv5TE based CPU with software floating point operations. You can use APP_ABI to select a different ABI.
默認情況下,NDK 生成系統將生成 'armeabi' ABI 的機器代碼。這對應于 ARMv5TE 基于 CPU 浮點運算的軟件。您可以使用 APP_ABI 來選擇不同的 ABI。
沒有指定APP_ABI,則它只去編譯支持armeabi這種CPU的機器代碼,想支持其他平臺,就要添加APP_ABI指定想要支持的平臺,支持多個平臺時,用空格隔開,比如:
APP_ABI := armeabi x86
**注意:genymotion模擬器應該都是支持x86CPU平臺,所以APP安裝到這些模擬器,應該注意指定APP_ABI**
重新ndk-build生成x86平臺下的.so文件如圖,然后運行到x86模擬器

### cpu平臺 ###
* arm :指令集,精簡指令集,簡單的事情,效率特別高,
* 優點:移動平臺,執行簡單的指令操作,效率高,資源消耗低,功耗低。
* 缺點:復雜邏輯的時候,就有缺陷。
* 發展:arm平臺的服務器
* x86:復雜指令集,SSE,SSE3
* 優點:執行復雜業務邏輯的時候,性能非常強大,這種性能遠超arm平臺
* 缺點:耗電,功耗高。
* 發展:x86 平臺手機cpu,x86:聯想的k900,拉攏一些山寨廠商使用x86 cpu
* mips:cpu 類型
* 龍芯:用mips
* sigma:機頂盒
### javah ###
- jdk 1.7項目 src目錄下運行 javah
- jdk 1.6項目 bin目錄下classes文件夾
- javah native方法聲明的java類的全類名
從上圖可以看到在ndk-build時,出現一個warning,說APP_PLATFORM ,Android-19比最小版本14大,解決這個warning可以在Application.mk中添加
APP_PLATFORM := android-14

可以看到,不再報這個warning
####錯誤三: 使用javah生成頭文件報找不到類文件 ####
很有可能是由你的JDK環境變量配置出錯,記住CLASSPATH這個系統變量,前面應該加上“.;”,如圖所示

- 前言
- JNI基礎知識
- C語言知識點總結
- ①基本語法
- ②數據類型
- 枚舉類型
- 自定義類型(類型定義)
- ③格式化輸入輸出
- printf函數
- scanf函數
- 編程規范
- ④變量和常量
- 局部變量和外部變量
- ⑤類型轉換
- ⑥運算符
- ⑦結構語句
- 1、分支結構(選擇語句)
- 2、循環結構
- 退出循環
- break語句
- continue語句
- goto語句
- ⑧函數
- 函數的定義和調用
- 參數
- 函數的返回值
- 遞歸函數
- 零起點學通C語言摘要
- 內部函數和外部函數
- 變量存儲類別
- ⑨數組
- 指針
- 結構體
- 聯合體(共用體)
- 預處理器
- 預處理器的工作原理
- 預處理指令
- 宏定義
- 簡單的宏
- 帶參數的宏
- 預定義宏
- 文件包含
- 條件編譯
- 內存中的數據
- C語言讀文件和寫文件
- JNI知識點總結
- 前情回顧
- JNI規范
- jni開發
- jni開發中常見的錯誤
- JNI實戰演練
- C++(CPP)在Android開發中的應用
- 掘金網友總結的音視頻開發知識
- 音視頻學習一、C 語言入門
- 1.程序結構
- 2. 基本語法
- 3. 數據類型
- 4. 變量
- 5. 常量
- 6. 存儲類型關鍵字
- 7. 運算符
- 8. 判斷
- 9. 循環
- 10. 函數
- 11. 作用域規則
- 12. 數組
- 13. 枚舉
- 14. 指針
- 15. 函數指針與回調函數
- 16. 字符串
- 17. 結構體
- 18. 共用體
- 19. typedef
- 20. 輸入 & 輸出
- 21.文件讀寫
- 22. 預處理器
- 23.頭文件
- 24. 強制類型轉換
- 25. 錯誤處理
- 26. 遞歸
- 27. 可變參數
- 28. 內存管理
- 29. 命令行參數
- 總結
- 音視頻學習二 、C++ 語言入門
- 1. 基本語法
- 2. C++ 關鍵字
- 3. 數據類型
- 4. 變量類型
- 5. 變量作用域
- 6. 常量
- 7. 修飾符類型
- 8. 存儲類
- 9. 運算符
- 10. 循環
- 11. 判斷
- 12. 函數
- 13. 數學運算
- 14. 數組
- 15. 字符串
- 16. 指針
- 17. 引用
- 18. 日期 & 時間
- 19. 輸入輸出
- 20. 數據結構
- 21. 類 & 對象
- 22. 繼承
- 23. 重載運算符和重載函數
- 24. 多態
- 25. 數據封裝
- 26. 接口(抽象類)
- 27. 文件和流
- 28. 異常處理
- 29. 動態內存
- 30. 命名空間
- 31. 預處理器
- 32. 多線程
- 總結
- 音視頻學習 (三) JNI 從入門到掌握
- 音視頻學習 (四) 交叉編譯動態庫、靜態庫的入門學習
- 音視頻學習 (五) Shell 腳本入門
- 音視頻學習 (六) 一鍵編譯 32/64 位 FFmpeg 4.2.2
- 音視頻學習 (七) 掌握音頻基礎知識并使用 AudioTrack、OpenSL ES 渲染 PCM 數據
- 音視頻學習 (八) 掌握視頻基礎知識并使用 OpenGL ES 2.0 渲染 YUV 數據
- 音視頻學習 (九) 從 0 ~ 1 開發一款 Android 端播放器(支持多協議網絡拉流/本地文件)
- 音視頻學習 (十) 基于 Nginx 搭建(rtmp、http)直播服務器
- 音視頻學習 (十一) Android 端實現 rtmp 推流
- 音視頻學習 (十二) 基于 FFmpeg + OpenSLES 實現音頻萬能播放器
- 音視頻學習 (十三) Android 中通過 FFmpeg 命令對音視頻編輯處理(已開源)