Android Studio NDK及so檔案開發

來源:互聯網
上載者:User

標籤:

前言什麼是NDK?

NDK全稱是Native Development Kit,NDK提供了一系列的工具,協助開發人員快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。NDK整合了交叉編譯器(交叉編譯器需要UNIX或LINUX系統內容),並提供了相應的mk檔案隔離CPU、平台、ABI等差異,開發人員只需要簡單修改mk檔案(指出“哪些檔案需要編譯”、“編譯特性要求”等),就可以建立出so。

為什麼使用NDK?

1、代碼的保護。由於apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。 
2、可以方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++代碼編寫的。 
3、提高程式的執行效率。將要求高效能的應用邏輯使用C開發,從而提高應用程式的執行效率。 
4、便於移植。用C/C++寫得庫可以方便在其他的嵌入式平台上再次使用。

什麼是JNI?

JNI的全稱是Java Native Interface,它提供了若干的API實現了Java和其他語言的通訊(主要是C和C++)。

為什麼使用JNI?

JNI的目的是使java方法能夠調用c實現的一些函數。

安卓中的so檔案是什嗎?

android中用到的so檔案是一個c++的函數庫。在android的JNI中,要先將相應的C語言打包成so庫,然後匯入到lib檔案夾中供java調用。

Android Studio NDK及so檔案開發NDK安裝及配置NDK安裝

Android Studio 從1.3 Beta1開始,支援了NDK。之前則不支援,所以我們建議使用新版的編輯器。

右鍵當前工程 => Open Moudle Setting => Android SDK location

如果未安裝,點擊安裝下載;

那麼接下來配置環境變數;

配置環境變數

安裝好的NDk一般位於你的sdk檔案夾下的ndk-bundle。

比如我這裡是:D:\SDK\ndk-bundle(如),可以看到裡面有ndk-build檔案,下文進行編譯的時候我們會用到。


然後將該路徑配置到你系統變數的path裡面去,如下:

1、在系統內容變數裡面建立NDK_ROOT


2、將NDK_ROOT追加到Path環境變數下--> ;%NDK_ROOT%

添加完畢後開啟cmd,輸入ndk-build,出現如下內容則表示成功(網上說是成功的,雖然顯示的貌似是一些錯誤資訊,但是後文啟動並執行時候是沒問題的可以編譯成功)。

so庫開發建立“本地”方法

如下,在MainActiviy.java中建立了一個方法

public native String getStrFromJNI();

可以看到這個方法的聲明中有native關鍵字,這個關鍵字表示這個方法是本地方法,也就是說這個方法getStrFromJNI()是通過本地代碼(C/C++)實現的,在java代碼中僅僅是聲明。

編譯該類得到對應的.h檔案

切換到Terminal,進入到該工程的java目錄下(如所示),然後輸入

javah -jni  -encoding utf-8 包名.類名(如所示)。

編譯成功後,重新整理下工程可以看到編譯出的.h檔案,該檔案只是為了輔助我們寫出相應的.c檔案,使用完了即可刪除。

該檔案的代碼如下所示:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class cn_handsomedragon_testndk_MainActivity */#ifndef _Included_cn_handsomedragon_testndk_MainActivity#define _Included_cn_handsomedragon_testndk_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     cn_handsomedragon_testndk_MainActivity * Method:    getStrFromJNI * Signature: ()Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_cn_handsomedragon_testndk_MainActivity_getStrFromJNI  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif

其實重要的部分就是這一句代碼:

JNIEXPORT jstring JNICALL Java_cn_handsomedragon_testndk_MainActivity_getStrFromJNI  (JNIEnv *, jobject);

仔細觀察可以看到他是遵循“Java_包名類名本地方法名”來組織的(瞭解到這些後我們以後就可以不產生.h檔案然後直接去寫.c檔案了)。

編寫.c檔案

這時我們切換到Project,然後在app目錄下建立jni檔案夾,並在裡面建立一個demo.c的c檔案(如所示)。

在demo.c檔案中編寫最基本的測試代碼:

#include <string.h>#include <jni.h>jstringJava_cn_handsomedragon_testndk_MainActivity_getStrFromJNI(JNIEnv *env,jobject thiz) {    return  (*env)->NewStringUTF(env, "I`m Str !");}

這是就可以看出我們用的是.h中的那行代碼,稍微修改為如上格式就是我們所需要的.c檔案了。

編寫Android.mk檔案

在jni目錄下建立Android.mk(必須是這個名稱Android.mk)檔案,如所示:

編輯Android.mk代碼:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE        := demo         //要產生的so庫的名稱,但實際為libdemo.soLOCAL_SRC_FILES     := demo.c       //要使用的檔案,剛才編寫的demo.c檔案include $(BUILD_SHARED_LIBRARY)

產生so檔案

在控制台中,進入到工程的app目錄下,然後輸入ndk-build(如下所示),不出問題即可編譯成功。

編譯完成後重新整理工程,可以看到在app目錄下產生的libs和obj檔案夾,其中libs是有用的,obj檔案夾無用可以刪除。libs中的可以看到產生的libdemo.so檔案。

兩個必要設定

1、在local.properties中設定NDK路徑,我的NDK樣本如下:

2、在app的build.gradle的android節點下設定:

這兩處必要的地方該修改完畢後就可以開心的調用我們產生的so檔案了。

使用so檔案

在MainActivity.java中,載入so檔案並調用,代碼如下:

這個庫demo(完整的名字是libdemo.so)會在第一次使用MainActivity這個類的時候載入。(static代碼塊聲明的代碼會先於onCreate方法執行)

觀察控制台的輸出,可以看到列印出來的字串:

此時表示so庫使用成功,之前的jni檔案夾以及原來產生的.h檔案就可以完全刪除了。當然這個so庫你要做好文檔的記錄,否則到時候估計你也忘了都有哪本地個方法可以調用了。

Android Studio NDK及so檔案開發

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.