標籤:
NDK簡介
NDK能幹什麼:NDK使得在android中,java可以調用C 函數庫。
1.Android平台從誕生起,就已經支援C、C++開發。眾所周知,Android的SDK基於Java實現,這意味著基於Android SDK進行開發的第三方應用都必須使用Java語言。但這並不等同於“第三方應用只能使用Java”。
2.在Android SDK首次發布時,Google就宣稱其虛擬機器Dalvik支援JNI編程方式,也就是第三方應用完全可以通過JNI調用自己的C動態庫,即在Android平台上,“Java+C”的編程方式是一直都可以實現的。
3.NDK提供了一系列的工具,協助開發人員快速開發C(或C++)的動態庫,並能自動將so和java應用一起打包成apk。這些工具對開發人員的協助是巨大的。
4.NDK整合了交叉編譯器,並提供了相應的mk檔案隔離CPU、平台、ABI等差異,開發人員只需要簡單修改mk檔案(指出“哪些檔案需要編譯”、“編譯特性要求”等),就可以建立出so。
5.NDK可以自動地將so和Java應用一起打包,極大地減輕了開發人員的打包工作。
6.NDK提供了一份穩定、功能有限的API標頭檔聲明
7.Google明確聲明該API是穩定的,在後續所有版本中都穩定支援當前發布的API。從該版本的NDK中看出,這些API支援的功能非常有限,包含有:C標準庫(libc)、標準數學庫(libm)、壓縮庫(libz)、Log庫(liblog)。
Today
1.NDK並不能顯著提升應用效率。我們都覺得C語言比起java來說效率要高出很多,一方面,隨著jdk的不斷更新,java的效率也隨之提高;另一方面,即便使用C語言編碼提高了應用效率,但是在java與C相互調用時平白又增大了開銷。
2.今天折騰了大半天,才編譯出自己想要的so檔案。但是android studio整合式開發環境中還沒嘗試。
3.關於Cygwin下載問題,官方放在的step.exe國內今天根本沒發弄下來,下載了一個老版本的exe,但是又不給更新。
http://www.redhat.com/services/custom/cygwin/ 在紅帽試過,雖然exe能弄下來,但是Cygwin需要的下載的檔案根本沒法下載(網速太慢,比蝸牛還慢,況且有好幾個G的)
http://mirrors.163.com/ 網易開源鏡像站
http://www.cygwin.cn/site/info/show.php?IID=1003 Cygwin中文網
4.由於Java中的本地方法名稱及包路徑都是寫死在C語言中的,因此本地相關代碼不能混淆
5.項目中的JNI目錄時編寫c/c++的代碼區,執行ndk-build命令後會在libs下產生so檔案,在運行項目時,也是調用so檔案中的相關資源。
為什麼要使用NDK
java是半解釋型語言,很容易被反組譯碼後拿到原始碼檔案,在開發一些重要協議時,我們為了安全起見,使用C語言來編寫這些重要的部分,來增大系統的安全性。還有,在一些接近硬體環境下,相信大家都清楚C與java的優劣。
1.代碼的保護。由於apk的java層代碼很容易被反編譯,而C/C++庫反匯難度較大。
2.可以方便地使用現存的開源庫。大部分現存的開源庫都是用C/C++代碼編寫的。
3.提高程式的執行效率。將要求高效能的應用邏輯使用C開發,從而提高應用程式的執行效率。
4.便於移植。用C/C++寫得庫可以方便在其他的嵌入式平台上再次使用。
5.Eclipse中ndk配置
NDK開發所需要的環境
1.Android應用開發所需要的開發Integration Environment(環境變數自己百度)
2.NDK所需要的開發包(C:\java\android-ndk-r7b)
3.linux環境需要下載cygwin(C:\java\cygwin\bin)
4.配置各自的環境變數(JDK,SDK,NDK,cygwin)
JNI編碼
1.建立一個android工程
2.在工程目錄下添加名為 jni 的檔案夾(必須)如:
3.在jni檔案夾下建立你的.c和.h檔案檔案(JNI_Demo.c和JNI_Demo.h)
4.在jni檔案夾下建立名字為Android.mk檔案(檔案名稱符合命名規則都行)
5.在上述.mk檔案中加入如下代碼:
LOCAL_PATH := $(call my-dir)//當前路徑(如果你瞭解shell語言,應該可以很輕鬆的理解)include $(CLEAR_VARS)LOCAL_MODULE := JNI_Demo //要產生的.so庫名LOCAL_SRC_FILES := JNI_Demo.c //jni檔案夾下的c檔案名稱include $(BUILD_SHARED_LIBRARY)
6.在JNI_Demo.c檔案中加入如下代碼:
#include <stdio.h>#include "JNI_Demo.h"const char keyValue[] = { 119,119,119,46,104,111,109,105,108,121,46,99,110};JNIEXPORT jbyteArray JNICALL Java_com_homily_SecurityUtil_getKeyValue (JNIEnv *env, jclass obj){ jbyteArray kvArray = (*env)->NewByteArray(env, sizeof(keyValue)); jbyte *bytes = (*env)->GetByteArrayElements(env,kvArray,0); int i; for (i = 0; i < sizeof(keyValue);i++) { bytes[i] = (jbyte)keyValue[i]; } (*env)->SetByteArrayRegion(env,kvArray, 0, sizeof(keyValue),bytes); (*env)->ReleaseByteArrayElements(env,kvArray,bytes,0); return kvArray;}
7.在JNI_Demo.h檔案中加入如下代碼:
#include <jni.h>#ifndef _Included_com_homily_SecurityUtil#define _Included_com_homily_SecurityUtil#ifdef __cplusplusextern "C" {#endifJNIEXPORT jbyteArray JNICALL Java_com_homily_SecurityUtil_getKeyValue (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
8.然後就是寫C對應的Java代碼
Java_com_homily_SecurityUtil_getKeyValue
這個是Java類對應的路徑,必須以Java開頭,com.homily.SeturityUtil.java類下的getKeyValue方法。JNI橋接代碼如下:
1 package com.homily; 2 3 public class SecurityUtil { 4 private static byte[] keyValue; 5 6 static { 7 System.loadLibrary("JNI_Demo"); 8 keyValue = getKeyValue(); 9 } 10 11 public static String getValue() {12 return new String(keyValue);13 }14 15 public static native byte[] getKeyValue();16 17 }
9.android調用代碼如下
1 package com.homily; 2 import android.app.Activity; 3 import android.os.Bundle; 4 import android.util.Log; 5 6 public class MainActivity extends Activity { 7 8 private static final String TAG = "MainActivity"; 9 10 @Override11 protected void onCreate(Bundle savedInstanceState) {12 super.onCreate(savedInstanceState);13 14 setContentView(R.layout.activity_main);15 String enstr = SecurityUtil.getValue();16 Log.d(TAG, "web address[" + enstr +"]");17 }18 19 }NDK編譯結果
1.產生so檔案
開啟cmd,使用cd等相關命令進入該工程目錄下 ,運行下面的命令,完成後點擊右鍵重新整理下項目,在libs下面就會產生so檔案,如下:
E:\android_workspace\JNI_Demo>NDK-buildAndroid NDK: WARNING: APP_PLATFORM android-19 is larger than android:minS[armeabi] Compile thumb : JNI_Demo <= JNI_Demo.c[armeabi] SharedLibrary : libJNI_Demo.so[armeabi] Install : libJNI_Demo.so => libs/armeabi/libJNI_Demo.so
so檔案如:
2.最後運行下項目,輸出日誌如下:
參考資料:
http://mobile.51cto.com/aprogram-434525.htm
http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html
[Android NDK/JNI-1A]-開發環境搭建