編輯:關於Android編程
什麼是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
/* Header for class cn_handsomedragon_testndk_MainActivity */
#ifndef _Included_cn_handsomedragon_testndk_MainActivity
#define _Included_cn_handsomedragon_testndk_MainActivity
#ifdef __cplusplus
extern "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
#include
jstring
Java_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.so
LOCAL_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 中導入項目後 包出現錯誤的解決方法 選中項目,右擊打開Proper
我們學的Android 數據持久化的技術包括文件存儲、SharedPreferences 存儲、以及數據庫存儲。不知道你有沒有發現,使用這些持久化技術所保存的數據都只能在
Android廣播BroadcastReceiver Android 系統裡定義了各種各樣的廣播,如電池的使用狀態,電話的接收和短信的接收,開機啟動都會產生一個
自從Fragment出現,曾經有段時間,感覺大家談什麼都能跟Fragment談上關系,做什麼都要問下Fragment能實現不~~~哈哈,是不是有點過~~~ 本篇博客力求為