更新時間:2015年12月28日15時22分 來源:傳智播客Android培訓(xùn)學(xué)院 瀏覽次數(shù):
一步一步做Android Studio下JNI開發(fā)
Android Studio是Google基于IntelliJ IDEA專門為Android開發(fā)而定制的集成開發(fā)環(huán)境。在2013年5月的Google大會上首次發(fā)布。Goolge宣布2015年底就中止Eclipse官方支持,所以是時候擁抱Android Studio了。
先來看下相關(guān)知識背景
1.什么是JNI?
Java native interface是一種協(xié)議,并提供一套編程框架,讓java和本地語言(C/C++)之間能夠相互調(diào)用。
2.為什么需要JNI呢?
Java是一種平臺無關(guān)的語言,通過不同操作系統(tǒng)下具有相同功能的JVM實現(xiàn)一次編譯,可以到處運行。也正是因為JVM,使得Java程序運行的效率相對于C/C++等本地語言較低,而且不能像C/C++一樣直接操作底層硬件。因為C/C++本地語言編譯程序是直接被操作系統(tǒng)運行,而不需要類似Java的虛擬機。
所以如果Android app需要操作底層硬件,或要求應(yīng)用的運行效率,安全性,就可以使用JNI來實現(xiàn)java和本地C/C++語言之間的相互調(diào)用。
3.那什么是NDK呢?
Native Development Kit 本地開發(fā)工具集。簡單的說就是一整套工具,用來構(gòu)建、編譯本地c/c++源程序,生成.so動態(tài)庫,加入本地庫中,讓Android應(yīng)用程序中Java程序通過jni調(diào)用。
JNI和NDK關(guān)系見圖1
4.怎樣進行JNI開發(fā)呢?
之前大家使用Eclipse+CDT+NDK進行JNI開發(fā),轉(zhuǎn)到Android Studio后怎樣來進行JNI開發(fā)呢?
需要指出的是Android Studio當前對NDK的支持還處于測試階段,還未產(chǎn)生穩(wěn)定的支持。隨著Android Studio版本的升級,開發(fā)方式還在變化。本文使用的環(huán)境是Android Studio1.4穩(wěn)定版,gradle 2.4。
下面就通過一個簡單的例子介紹怎樣用Android Studio進行JNI開發(fā)。
先上效果見圖2
例子很簡單,android應(yīng)用程序TestJni中java借助JNI調(diào)用本地C函數(shù),獲得一個字符串,并用Toast提示在界面上。
step1:首先新建一個Module模塊,TestJni,新建一個包com.itheima.jni
,和一個專門存放本地方法的類JNI。然后用native關(guān)鍵字聲明本地方法helloFromC
package com.itheima.jni; /** * Created by tim on 2015/12/15. */ public class JNI {
//本地方法獲得字符串,本地方法由c/c++實現(xiàn) public static native String helloFromC(); }
step2:在MainActivity類中調(diào)用JNI類中的本地方法,獲得字符串,并用Toast打印輸出
package com.itheima.testjni; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import
android.widget.Toast; import com.itheima.jni.JNI; public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); JNI jni = new JNI(); Toast.makeText(this, jni.helloFromC(), Toast.LENGTH_SHORT).show(); } }step3:在testjni模塊中新建存放c源文件的jni文件夾
step4:在jni文件夾下新建c/c++源文件,這里新建了hello-jni.h和hello-jni.c#include "com_itheima_jni_JNI.h" //包含生成的頭文件并將com_itheima_jni_JNI.h頭文件中,本地方法對應(yīng)函數(shù)聲明拷貝到hello-jni.c文件中,方便下一步來實現(xiàn)這個函數(shù) step6:實現(xiàn)本地方法相應(yīng)的Java_com_itheima_jni_JNI_helloFromC函數(shù)功能,返回一個Java中的String字符串對象
JNIEXPORT jstring JNICALL Java_com_itheima_jni_JNI_helloFromC
(JNIEnv * env, jclass obj){
char buf[] = "Hello world from C!";
//env調(diào)用struct JNINativeInterface中的函數(shù)指針
//實現(xiàn)轉(zhuǎn)換c里面的char *字符串為java中的String對象
return (*env)->NewStringUTF(env, buf); }
在defaultConfig{}中添加ndk{}
defaultConfig { applicationId "com.itheima.testjni" minSdkVersion 10 targetSdkVersion 23 versionCode 1 versionName "1.0" ndk{ //指定生成模塊名字,也就是最終的動態(tài)庫名hello-jni,相應(yīng)庫文件名libhello-jni.so moduleName "hello-jni" //指定生成哪些處理器架構(gòu)的動態(tài)庫文件,如果要運行在x86架構(gòu)處理器一定需要指定 abiFilters "armeabi" , "x86" } }
step9:在JNI類中加載動態(tài)庫
package com.itheima.jni; /** * Created by tim on 2015/12/15. */ public class JNI { static{ //指定庫名,加載動態(tài)庫,需要和build.gradle中指定的庫名一致 System.loadLibrary("hello-jni"); } //本地方法獲得字符串,本地方法由c/c++實現(xiàn) public static native String helloFromC(); }
step10:編譯這個模塊
等待結(jié)果......結(jié)果,納尼?編譯報錯了!
Error:(14, 1) A problem occurred evaluating project ':testjni'.
> Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.
com/tech-docs/new-build-system/gradle-experimental. Set "android.useDeprecatedNdk=true" in gradle.
properties to continue using the current NDK integration.
淡定!
仔細一讀,原來是NDK集成在當前Gradle插件中棄用,建議用新的實驗性插件,或者在工程中g(shù)radle.proerties中設(shè)置android.useDeprecatedNdk=true
ok照辦。