Android studio 使用NDK工具實現JNI編程

前言:

Android開發中經常會使用到第三方的.so庫。在使用.so庫的時候就要用到JNI編程。JNI是Java Native Interface的縮寫。它提供了若干的API實現了Java和其它語言的通訊(主要是C&C++)。開發中通常都用第三方的庫,很是多時候也可能咱們本身來編寫C或者C++來實現JNI編程,這篇博客主要是介紹Android studio 使用NDK工具來開發JNI編程。java

環境配置

JNI編程需要知足例如如下前提:android

  1. 你必須有安裝Android studio開發idea編輯器(本人使用的是android studio 1.3版本號)。

  2. 下載最新版本號的NDK工具,而後解壓到一個文件夾就能夠(配置NDK環境變量時使用到該路徑)。

    個人ndk版本號爲 android-ndk-r10e編程

  3. 配置ndk環境變量,計算機–>屬性–>高級系統設置–>環境變量–>系統變量–>新建 變量名:NDK_ROOT;變量值:F:\Android\SDK1\android2\android-ndk-r10e(此處是個人ndk路徑。換成你本身的ndk路徑就能夠)。

  4. 固然前提是你要配置了jdk環境變量,配置如同第三點:變量名:JAVA_HOME;變量值:F:\Android\SDK1\android2\Java\jdk1.7.0_67(此處是個人jdk路徑。換成你本身的jdk路徑就能夠)。

    除此以外,你還得新建一個CLASSPATH環境變量,變量名:CLASSPATH;變量值爲 .;%HOME_PATH%\lib; 一開始的 . 和;和最後的;都是需要的。bash

  5. 你還需要在gradle.progerties文件下加入例如如下代碼
android.useDeprecatedNdk=true

假設沒有gradle.progerties文件,請直接在當前project下新建該文件就能夠。markdown

JNI編程

1.新建JniUtils類。用來調用jni方法。代碼例如如下:app

package com.example.xjp.myjnidmoe;

public class JniUtils {
//載入靜態庫
    static {
        System.loadLibrary("Test");//此處載入的是對應的模塊庫,名稱必須和 ndk的moduleName名同樣。
    }
//定義本地方法
    public native String getValue();
}

2.Build 編譯當前project,最後會在build文件夾下生成例如如下文件
這裏寫圖片描寫敘述
該文件夾下生成了 JniUtils.class文件。編輯器

而後打開AS的Terminal終端,跳到debug文件夾下:這裏寫圖片描寫敘述
而後運行 javah -jni *(此處爲你的目標文件路徑。即JniUtils路徑)
這裏寫圖片描寫敘述
最後會在debug文件夾如下生成 com_example_xjp_myjnidmoe_JniUtils.h 頭文件。代碼例如如下:ide

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_xjp_myjnidmoe_JniUtils */

#ifndef _Included_com_example_xjp_myjnidmoe_JniUtils
#define _Included_com_example_xjp_myjnidmoe_JniUtils
#ifdef __cplusplus
extern "C" {
#endif
/* * Class: com_example_xjp_myjnidmoe_JniUtils * Method: getValue * Signature: ()Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_example_xjp_myjnidmoe_JniUtils_getValue
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

以上代碼是本身主動生成的,無需開發人員去改動。工具

3.在你的main文件夾下新建jni子文件夾。例如如下:這裏寫圖片描寫敘述
將剛纔生成的 .h頭文件拷貝到該jni文件夾下。而後新建一個 test.c文件,test.c文件代碼例如如下:post

//
// Created by 850302 on 2016/4/26.
//

#include "com_example_xjp_myjnidmoe_JniUtils.h"

JNIEXPORT jstring JNICALL Java_com_example_xjp_myjnidmoe_JniUtils_getValue
        (JNIEnv *env, jobject obj) {
    return (*env)->NewStringUTF(env, "This is my first JNI demo!");
}

由於jni編程對方法的名稱有必定規則要求。開頭需要Java_ 後面依次是jni方法的java類路徑。以「_」切割。

開發人員爲了避免寫錯,可以直接將剛纔的.h頭文件中的方法 copy下來直接實現就能夠。

4.配置Gradle文件
首先你得配置當前project的 build.gradle文件,事實上配置很是easy,直接在原來的build.gradle文件中加入 ndk的配置就能夠。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.example.xjp.myjnidmoe"
        minSdkVersion 21
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        //這裏是配置ndk
        ndk{
            //定義庫的模塊名稱。該名稱用於System.loadLibrary("Test")
            moduleName "Test" 
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

是否是很是easy。不過定義了 ndk 的moduleName的名稱而已。

其次是爲當前project配置指定的ndk,配置方法例如如下:右鍵當前project名。選擇Open Module Settings。彈出例如如下窗體。這裏寫圖片描寫敘述
如圖。1:sdk路徑;2:jdk路徑。3:ndk路徑;點擊ok以後。

會在local.properties文件下配置指定的sdk和ndk路徑:

#Tue Apr 26 18:36:18 CST 2016
ndk.dir=F\:\\Android\\SDK1\\android2\\android-ndk-r10e
sdk.dir=F\:\\Android\\SDK1\\android2\\sdk

如此,所有的準備工做都已經完畢。現在可以在你的代碼中使用Test庫了,調用代碼例如如下:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.text);

        //start=====
        JniUtils jniUtils = new JniUtils();
        String content = jniUtils.getValue();
        //end=====
        textView.setText(content);

    }

結果例如如下:這裏寫圖片描寫敘述

可能會有人問。代碼生成的libTest.so庫在哪裏呢?事實上生成的libTest.so庫已經打包到apk中去了,那麼假如我要把這個so庫給別人使用怎麼辦?很是easy,在你編譯的過程事實上已經生成了libTest.so,在哪裏呢?文件夾例如如下:bulid/intermediates/ndk文件夾下。該文件夾是編譯成功以後生成的。

這裏寫圖片描寫敘述
看到沒?生成了不一樣平臺下的libTest.so庫。

總結

該博客主要是記錄Android studio 下使用NDK工具實現JNI編程和生成so庫的整個過程。以便開發人員瞭解JNI編程的一個完整的過程。

相關文章
相關標籤/搜索