1. 程式人生 > >Android下jni開發之ndk的使用(下載、配置、編譯遇到的問題)

Android下jni開發之ndk的使用(下載、配置、編譯遇到的問題)

Android下jni開發之ndk的使用

一、簡介

     JNI和NDK很多Android開發初學者沒有搞明白這個問題,JNI是Java呼叫Native機制,是Java語言自己的特性全稱為Java Native Interface,類似的還有微軟.Net Framework上的p/invoke,可以讓C#或Visual Basic.Net可以呼叫C/C++的API,所以說JNI和Android沒有關係,在PC上開發Java的應用,如果執行在Windows平臺使用JNI是是經常的,比如說讀寫Windows的登錄檔。而NDK是Google公司推出的幫助Android開發者通過C/C++本地語言編寫應用的開發包,包含了C/C++的標頭檔案、庫檔案、說明文件和示例程式碼,我們可以理解為Windows Platform SDK一樣,是純C/C++編寫的,但是Android並不支援純C/C++編寫的應用,同時NDK提供的庫和函式功能很有限,僅僅處理些演算法效率敏感的問題

簡單點說,用C語言生成一個庫檔案,在java中呼叫這個庫檔案的函式。JNI的過程比較複雜,生成.so需要大量操作,而NDK就是簡化了這個過程。


    Java通過JNI機制和C/C++溝通的具體步驟

    1、編寫包含native本地方法的java類
    2、通過javah工具生成C/C++語言的標頭檔案
    3、使用C/C++語言實現標頭檔案
    4、使用交叉編譯工具對C/C++原生代碼進行編譯,最後通過連結生成*.so可執行的C/C++庫
    5、實際執行Java程式碼去和本地的C/C++程式碼互相溝通



、NDK開發環境的搭建

   

     1.下載安裝Android NDK

     2.NDK環境配置 http://jingyan.baidu.com/article/ff42efa91906b8c19e220234.html


通過連結生成*.so可執行的C/C++庫

       開啟cmd,進入jni目錄,執行ndk-build命令,如果ndk-build執行不了,回到上一條環境配置

四、執行ndk-build命令 遇到的問題

        1.android.mk: *** missing separator (did you mean TAB instead of 8 spaces?)或者*** missing separator的解決辦法

           http://blog.csdn.net/z13144099248m/article/details/41800747

          這個錯誤是由於在編寫這個檔案的時候,行前面用的是空格,而不是tab,所以造成了操作符丟失的錯誤。
          解決辦法是:把縮排的空格delete掉,然後按tab鍵用tab代替4個空格。

        2、android.mk: ***commands commence before first target.的原因

            http://blog.csdn.net/dahaibeibe/article/details/8162955

            上一行換行符號 \ 後面有空格
            本行前面的空白有非法字元

       3.android.mk: *** missing separator  missing separator的解決辦法

          http://blog.csdn.net/sunnyfans/article/details/8807427


   總而言之,這三問題都是操作符有問題,建議刪除行前行後的空格用Tab/回車代替,所有的空格都有可能有問題,所以如果是貼上過來的android.mk需要注意下格式等要求,其他的問題以後遇到i補充i


      4.執行成功後,在android 6.0 會報java.lang.UnsatisfiedLinkError: No implementation found for intcom.gauss.speex.encode.Speex.open(int)      (tried Java_com_gauss_speex_encode_Speex_open and Java_com_gauss_speex_encode_Speex_open__I)這個錯誤

             http://blog.csdn.net/donglynn/article/details/25377067

           問題顯然是沒有找到相應的本地函式。解決辦法也很簡單,就是Java程式碼,.h檔案和.cpp檔案中的宣告,肯定有一個不對應的。

           我是由於包名com.gauss.speex.encode.和貼上過來的程式碼不一致,自己生成.h檔案和copy過來的.cpp檔案中方法名不一致導致的找不到相應的         本地函式,坑爹的是這麼明顯的錯編譯竟然不報錯
      

五、android實現jni的步驟

    (對這個我開始一直很混亂,百度了資料看了還是混亂,第二次android下jni下使用speex終於清晰點了,以下是當時參考連結,混亂時再跟著走一          遍就ok)

         speex演算法在android上的移植  http://blog.csdn.net/zkw12358/article/details/25339003

         speex編解碼在android上實現   http://blog.csdn.net/xyz_lmn/article/details/8013490

        android SDK使用cygwin編譯.so檔案  http://blog.csdn.net/zkw12358/article/details/24560499

        Android移植live555之二:android平臺下jni的使用  http://blog.163.com/[email protected]/blog/static/69429295201398115116782/