Android Studio JNI開發入門教程

概述

在Andorid Studio不支持JNI開發之前大家一般都是使用Eclipse開發JNI,各種配置讓人覺得很蛋疼。從Andorid Studio支持JNI開發后,讓我們開發JNI變的如此簡單。下面我就介紹一下Android Studio開發JNI的全過程,如有不對的地方大家批評指正。

你將學習到什么

  • 什么是NDK和JNI
  • 為什么要用JNI做開發
  • 如何使用Android Studio開發JNI項目

你需要準備什么

  • c/c++開發語言基礎
  • java開發語言基礎
  • 了解Android Studio開發環境

NDK 和 JNI介紹

JNI (Java Native Interface)是一套編程接口,用來實現java代碼和其他語言(c、C++或匯編)進行交互。這里需要注意的是JNI是JAVA語言自己的特性,也就是說JNI和Android沒有關系。在Windows下面用JAVA做開發也經常會用到JNI,例如:讀寫系統注冊表等。

NDK(Native Development Kit)是Google提供的一套工具集,可以讓你其他語言(C、C++或匯編)開發 Android的 JNI。NDK可以編譯多平臺的so,開發人員只需要簡單修改 mk 文件說明需要的平臺,不需要改動任何代碼,NDK就可以幫你編譯出所需的so。

用JNI做應用開發難度要比JAVA難很多,門檻也要高很多,如果你對C/C++把握的不好應用還會出現難以發現的Bug!所以
通常在對性能要求比較高才會使用。游戲引擎就是一個對性能要求極高的例子。另外就是如果你想把核心的一些算法或處理邏輯保護起來,選用JNI也是一個不錯的方案。

下載NDK

官網下載
網盤下載

NDK配置

將ndk解壓到~/Library/Android/ndk下;
2016-03-24_15-10-10.png

創建Hello World工程

設置NDK路徑

選擇File>Project Structure>SDK Location(快捷鍵:Cmd+;),指定NDK的路徑。
2016-03-24_16-11-28.png
2016-03-24_16-10-35.png
你也可以通過直接修改local.properties,在里面指定NDK的所在目錄:

ndk.dir=/Users/open-open/Library/Android/ndk

2016-03-27_21-17-34.png

添加本地方法

在MainActivity中加入兩個JNI方法

public static native String helloJni();
public static native int addCalc(int a, int b);

加載SO文件

static {
    System.loadLibrary("hello_jni"); // 注意沒有前綴lib和后綴.so
}

</code></pre>

利用javah命令生成JAVA所對應的JNI頭文件,1、打開終端,2、將目錄定位到java目錄下,3、通過javah產生頭文件。
2016-03-28_07-46-07.png
通過上圖可以看到javah已經幫我們產生了一個名為com_test_jcit_helloworld_MainActivity.h頭文件,里面已經幫我們產生好了2個函數原型定義,

JNIEXPORT jstring JNICALL Java_com_test_jcit_helloworld_MainActivity_helloJni(JNIEnv , jclass);
JNIEXPORT jint JNICALL Java_com_test_jcit_helloworld_MainActivity_addCalc(JNIEnv , jclass, jint, jint);

</code></pre>

javah產生的文件名和函數名不能直視,我們只需要在需要的地方填入相應的代碼。

創建JNI目錄

2016-03-27_20-03-35.png
New Android Component中直接點擊Finish按鈕完成JNI目錄創建
2016-03-27_20-34-45.png
結果如下:
2016-03-27_20-40-24.png
將前面產生的com_test_jcit_helloworld_MainActivity.h頭文件移動到這個目錄下.
2016-03-28_22-11-05.png
move窗口中點擊ok按鈕,確定移動。
2016-03-28_22-14-02.png
com_test_jcit_helloworld_MainActivity.h拷貝一個將擴展名改為.c,在.c中完成業務邏輯處理相關代碼:

#include <com_test_jcit_helloworld_MainActivity.h>
JNIEXPORT jstring JNICALL Java_com_test_jcit_helloworld_MainActivity_helloJni
  (JNIEnv env, jclass jobj) {
    return (env)->NewStringUTF(env,"Hello JNI!");
}

JNIEXPORT jint JNICALL Java_com_test_jcit_helloworld_MainActivity_addCalc   (JNIEnv *env, jclass jobj, jint ja, jint jb) {   return ja + jb; } </code></pre>

2016-03-28_22-57-59.png

添加一個名為hello_jni的jni模塊

修改Module中Build.gradle文件,在defaultConfig段落中加入ndk編譯配置。  

defaultConfig {
    applicationId "com.test.jcit.helloworld"
    minSdkVersion 15
    targetSdkVersion 19
    versionCode 1
    versionName "1.0"
    ndk {
        moduleName "hello_jni"
    }
}

調用兩個native方法

在MainActivity中OnCreate中調用helloJni和addCalc。

protected TextView mHelloWorldTV;
protected TextView mCalcResultTV;

@Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_main);     mHelloWorldTV = (TextView) findViewById(R.id.HelloWorldTV);     mHelloWorldTV.setText(helloJni());     mCalcResultTV = (TextView) findViewById(R.id.CalcResultTV);     Integer addResult = new Integer(addCalc(12, 13));     mCalcResultTV.setText(addResult.toString()); }</code></pre>

編譯錯誤排查

編譯過程出現了Error:(13, 1) A problem occurred evaluating project ':app'.

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.

提示已經告訴我們需要在gradle.properties設置android.useDeprecatedNdk=true,設置好后點擊同步按鈕。
2016-03-28_23-24-02.png

大功告成

2016-03-28_23-36-28.png

存在疑問

 本文由用戶 五嘎子 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!