您好,登錄后才能下訂單哦!
android 中為什么實用NDK,網上一搜一大堆,在這原因不在贅述。
在Android SDK首次發布時,Google就宣稱其虛擬機Dalvik是支持JNI編程方式的;也就是第三方的應用是可以調用自己公司的或者是其他C、C++動態庫。
搭建平臺:1.我這用的是MacBook,系統是OS X 10.11.5;
2.Android Studio 2.1.2
3.JDK1.8.0_77 x86_64
首先搭建NDK開發環境。啟動Android Studio,在Android studio中,屬性—>Appearance & Behaveor —> System Settings —> Android SDK選項(注意:windows在使用NDKr8版本之上的NDK編譯版本,是不需要cygwin來模擬linux,進行交叉編譯的)。如下圖所示:
打開右邊的SDK Tools下邊的選項欄有一個NDK的選項,打上對勾,點擊Apply按鈕,接著會出現下載NDK文件的對話框,點擊accept—>OK,會下載NDK文件,通常NDK會安裝到SDK的目錄下面。
下載安裝完成之后配置NDK環境變量:
1.Windows 上是在計算機—》屬性—》高級—》環境變量,在path上追加NDK的安裝目錄。
2.linux或者是MAC是在家目錄的.bash_profile中,添加環境變量,例如export NDK_HOME=/Users/XXX/Android/SDK/ndk-bundle export PATH=$PATH:$SDK_HOME。
OK.測試NDK是否安裝配置成功,打開終端,輸入ndk-build -version.回車
顯示
表示安裝成功。
1.創建一個Android項目來測試一個Android的使用方式,在這命名為JNIDemo;創建項目的過程不再贅述。
2.在Andorid視圖中建立jni文件夾,右鍵—>New—>Folder—>JNI Folder,確定。會創建一個jni目錄。這個目錄就是存放c源碼的文件。(jni目錄的創建,也可以在project視圖中在main文件中創建一個jni目錄。如果在Android視圖中創建JNI Folder,再切換到Project視圖,你會發現,main目錄下有一個jni目錄,兩個本質上是一致的)。
3.配置需要CUP編譯成的架構庫(.so文件)。
defaultConfig { applicationId "com.zzh.jni" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ moduleName "zzhJni”//c/c++編譯成的庫文件名稱 abiFilters "armeabi", "armeabi-v7a","arm64-v8a","x86", "x86_64"http://需要適配哪幾種類型的CPU架構。 } } |
4.在gradle.properties(Project Properties)中添加android.useDeprecatedNdk=true;
在local.properties中添加ndk.dir=/Users/XXX/Android/SDK/ndk-bundle(自己安裝NDK的路徑)
5.新建一個jni調用類NdkUtils寫一個native方法。在Java中,Java調用c/c++中的程序,需要使用到native關鍵字表示Java中調用C/C++中的方法。
package zzh; public class NdkUtils { public static native String getMapHeader(); }
6.點擊Build—>Make Project,編譯文件,編譯后
在終端,進入到debug目錄,運行javah -jni zzh.NdkUtils回車,生成c的頭文件,頭文件的命名為“包名_類名(包名之間的“.”使用“_”分割開的)”。將此文件復制到jni目錄中,打開可以看到一下內容
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class zzh_NdkUtils */ #ifndef _Included_zzh_NdkUtils #define _Included_zzh_NdkUtils #ifdef __cplusplus extern "C" { #endif /* * Class: zzh_NdkUtils * Method: getDeviceIdFromNdk * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader (JNIEnv *env, jobject obj); #ifdef __cplusplus } #endif #endif
· JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader(JNIEnv *env, jobject obj); 就是我們之前所用native在NdkUtils.java聲明的方法。這個只是C/C++的一個.h文件,方法的具體實現,還要一個.c。這個.c文件,自己創建就好。
方法實現如下
#include "zzh_NdkUtils.h" JNIEXPORT jstring JNICALL Java_zzh_NdkUtils_getMapHeader (JNIEnv *env, jobject obj){ return (*env) -> NewStringUTF(env, "string from c"); }
7.至此C語言,就寫好了,怎么讓c/c++生成庫文件呢,先點擊Build-clean Project(先clean是因為避免在編譯的時候產生沖突),再make Project,在6步驟的圖片中classes同級目錄下有ndk目錄,此目錄下有生成好的庫文件。
復制arm*、x86*到jniLibs目錄中,就像我們在做項目時,將第三方的.so文件放入到jniLibs目錄一樣。Android.mk復制到jni文件中。
8.最后一步,調用生成的庫文件。
在NdkUtils.java中,添加
static{
System.loadLibrary(“zzhJni"); //這一行,表示要加載C語言庫,zzhJni就是編譯成的c庫文件,也就是在第三步中build.gradle中配置的moduleName 的名字
}
這樣就可以在Java代碼中調用c/c++方法了。
示例:
在MainActivity.java中調用:
public class MainActivity extends Activity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.textView); findViewById(R.id.button).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { String str = "" + NdkUtils.getMapHeader(); mTextView.setText(str); } catch (Exception ex) { ex.printStackTrace(); } finally { } } }); } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.zzh.jni.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="調用C方法" android:id="@+id/button" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New Text" android:id="@+id/textView" android:layout_centerVertical="true" android:layout_centerHorizontal="true"/> </RelativeLayout>
運行截圖:
文筆有限,寫的不好,敬請原諒,如有錯誤,敬請指正
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。