AndroidStudio如何配置NDK/JNI開發環境

參考文章:

http://www.th7.cn/Program/Android/201509/550864.shtml

http://www.open-open.com/lib/view/open1451917048573.html

http://blog.csdn.net/sodino/article/details/41946607

http://www.codes51.com/article/detail_197383.html

 

        AndroidStudio沒有像Eclipse那樣的一鍵add native support,相對來說比較麻煩,下面就介紹在AndroidStudio中如何實現類似於Eclipse的add native support功能(也就是進行NDK開發的步驟)。

 

1、新建一個Android工程,這一步就不多說了;

2、在AndroidStudio中配置NDK路徑,方法是:

(1)先下載NDK並安裝(這句基本是廢話);

(2)點菜單欄的File->ProjectStructure…->在打開的窗口中左側選中SDKLocation->在右側Android NDK Location中填入NDK目錄所在路徑,如下圖所示:

  


3、編譯生成.class文件,方法是:

點菜單欄的Build->Make Project,如下圖所示;

        這時,在工程的app/build/intermediates下就會生成classes文件夾,打開classes目錄下的debug目錄就會看到以你的包名命名的各級文件夾,最裏邊文件夾下有你的Java類對應的.class文件;

4、確定你要引用本地方法的類:

        其實你也可以先生成jni目錄,再去創建這個類,但是先Google顯然建議先創建要引用C代碼的Java類,因爲AndroidStudio可以根據你在java類中定義的native方法的名稱來自動生成.h頭文件。

        比如你想在MainActivity中引用本地方法,那麼你先用

static {

        System.loadLibrary("myNativeLib");

}

來聲明本地代碼庫,然後定義幾個natvie方法,比如

public native String getStringFromNative();

做完這些工作就可以進行下一步了。

5、使用javah命令行生成jni目錄及對應的頭文件:

        我用的是AndroidStudio 2.1.1,在主界面最下邊就能找到Terminal,點一下就能打開系統的命令行工具,並且已經爲你自動cd到當前工程所在目錄,如下圖所示:


如上圖所示,打開命令行編輯工具後,cd到工程的src/main/java目錄,輸入

     javah -d ../jni 你的包名.引用本地方法的類的名稱

javah意思是生成一個.h頭文件,-d ../jni的意思是生成一個名字叫做jni的文件夾(directory),位置是在當前目錄(src/main/java)的上一級目錄(即src/main目錄);比如我的工程下,這條命令是

     javah -d ../jni com.example.lixinyu.myapplication2.MainActivity

我直接用了MainActivity類做爲調用JNI的Java類,你也可以寫一個自己的類,之後就等吧,構建完成後就會在工程的src/main目錄下生成一個jni目錄,下邊還包含.h頭文件,如下圖所示:

        如果你事先在java代碼中定義了native方法,那麼這裏還會自動生成方法對應的.h頭文件。當然,要運行javah命令的前提是你的電腦已經安裝過java,並且已經配置了java環境變量。

        這裏再多說幾句,很多網友說要使用javah -d jni -classpath命令來構建jni目錄並生成.h頭文件,但是我親測是不行的,會報bash: ../../build/intermediates/classes/debug:is a directory錯誤,大概是版本不同吧,感謝碼蟻之家的網友提供的不一樣的答案。

        至此,我們就基本完成了相當於Eclipse中的add native support功能了,接下來還要配置gradle和一大堆其它的配置文件;

 

6、配置build.gradle文件

這裏的build.gradle是指app模塊下的build.gradle,不是整個工程的build.gradle文件。在模塊的build.gradle的defaultConfig下加入以下idk配置:

ndk {

      moduleName"myNativeLib"

      ldLibs "log""z""m"

      abiFilters "armeabi""armeabi-v7a""x86"

}

其中moduleName是隨便寫的,與將來在Java類中使用System.loadLobrary(“本地庫名稱”);以及生成的.so文件名稱對應;

ldLibs是要用到的jni庫,一般由google提供,比如上邊引入的log庫可以讓我們在C代碼中使用LogCat日誌;

abiFilters指的是我們要生成哪些平臺的so文件,這裏生成arm平臺和x86平臺;

配置後的build.gradle文件如下圖所示:

        至此build.gradle文件就配置完了,其實這一步有點像我們eclipse中配置.mk文件;

7、配置local.properties文件

        打開工程目錄下的local.properties,感覺這一步是自動配置的,或者說在你一開始在AndroidStudio中指定NDK目錄時已經自動生成了。我的AndroidStudio在打開local.properties已經有了

ndk.dir=/Develop/Android/android-ndk-r10e

這一行,所以就不用配了;

8、配置gradle.properties

        打開工程目錄下的gradle.properties文件(注意不是build.gradle,而是gradle.properties),在文件的最後一行加入

android.useDeprecatedNdk=true

這句的作用是允許我們使用已經過時的NDK版本,不知道AndroidStudio要求使用哪個版本的NDK纔不會報錯,總之只要配置了這一句就可以使用比較舊的NDK版本了,我用的r10;

        至此我們在AndroidStudio中就完成了NDK環境的配置,接下來就可以寫Native代碼了;

9、寫一個.c文件測試一下是否運行正常

(1)在我們之前生成src/main/jni目錄下新建一個.c文件,方法是在jni文件夾上點鼠標右鍵,選擇New->C/C++ Source File,然後在彈出的對話框中填入.c或.cpp文件的文件名就可以了,比如說mail.c,名字可以隨便起;

(2)在main.c中隨便寫一段JNI代碼,比如如下所示的一段代碼:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

#include <android/log.h>

 

#ifndef LOG_TAG

#define LOG_TAG"ANDROID_LAB"

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

#endif

 

/* Header for class lab_sodino_jnitest_MainActivity */

 

#ifndef _Included_com_example_lixinyu_myapplication2_MainActivity

#define _Included_com_example_lixinyu_myapplication2_MainActivity

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:lab_sodino_jnitest_MainActivity

 * Method: getStringFromNative

 * Signature: ()Ljava/lang/String;

 */

JNIEXPORT jstringJNICALL Java_com_example_lixinyu_myapplication2_MainActivity_getStringFromNative

  (JNIEnv *env, jobject jObj){

      LOGE("log string from ndk.");

      return (*env)->NewStringUTF(env,"HelloFrom JNI!");

  }

 

#ifdef __cplusplus

}

#endif

#endif

JNI基礎就不多說了;

(3)在Java中調用:

比如我在MainActivity中加入以下代碼:

package com.example.lixinyu.myapplication2;

 

import android.os.Bundle;

import android.support.v4.app.FragmentActivity;

import android.widget.TextView;

 

public class MainActivityextends FragmentActivity {

   

    private TextViewmTextView;

   

    static {

        System.loadLibrary("myNativeLib");

    }

   

    publicnative String getStringFromNative();

 

    @Override

    protected voidonCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        mTextView= (TextView) findViewById(R.id.main_textview);

        mTextView.setText(getStringFromNative()+"");

    }

}

       至此NDK/JNI代碼就算是完成了,可以再次點菜單欄的Build->Make Project編譯一下工程,看看在工程目錄下app/build/intermediates/ndk/debug/lib目錄下是否成功生成了相應的.so文件,如果以上配置都正確的話這裏是會生成對應平臺的.so文件的,debug目錄下還自動生成了Android.mk文件,這個確實還不錯,相當於我們用build.gradle文件的配置替代了Android.mk文件的配置,運行一下,正常的話是可以運行的,至此就算是在AndroidStudio中配置了NDK/JNI開發環境。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章