1. 程式人生 > >Android中JNI使用詳解(3)---Android Studio中SO檔案生成

Android中JNI使用詳解(3)---Android Studio中SO檔案生成

AndroidJNI使用詳解(2)---Android StudioSO檔案生成


上一篇寫到過在Android Studio中配置NDK環境地址:Android Studio中NDK環境配置

這篇文章講解在Android Studio中如何使用NDK生成so檔案


1、首先建立一個Android Studio專案


建立 jni 目錄:在專案中右鍵 new->folder->jni folder 選擇 main 資料夾點選 finish ,這時候在專案中
app->main 生成了 jni 目錄,當然也可以手動建立。


2、建立native方法


在專案中建立 com.jni.test 包,在包中建立 NativeUtil.class 檔案 , 新增 native 方法 ;


package com.jni.test;

/**
 * Created by Shaofeng.lan on 2016/7/12.
 */
public class NativeUtil {
    public static native String getJniString();
}

3、生成.h檔案

3.1Terminal(位置在Android Studio下面)輸入命令cd app/src/main/java進入app java路徑。

D:\AndroidStudio\NdkDemo>cd app/src/main/java

3.2輸入命令執行javah +【包名+檔名】如:javah com.jni.test.NativeUtil

D:\AndroidStudio\NdkDemo\app\src\main\java>javah com.jni.test.NativeUtil

3.3然後在java目錄下可以看見生成的對應.h【com_jni_test_NativeUtil.h檔案。


com_jni_test_NativeUtil.h程式碼:

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

#ifndef _Included_com_jni_test_NativeUtil
#define _Included_com_jni_test_NativeUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_test_NativeUtil
 * Method:    getJniString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jni_test_NativeUtil_getJniString
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

4、編寫.c檔案

將生成的.h檔案拷貝到jni資料夾中,並重命名為test.c並實現native方法

test.c程式碼:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jni_test_NativeUtil */

#ifndef _Included_com_jni_test_NativeUtil
#define _Included_com_jni_test_NativeUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_test_NativeUtil
 * Method:    getJniString
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_jni_test_NativeUtil_getJniString
  (JNIEnv * env, jclass jobj){
   return (*env)->NewStringUTF(env,"Hello JNI!");
  }

#ifdef __cplusplus
}
#endif
#endif

5、配置jni環境


appbuild.gradle檔案中,在defaultConfig節點新增一下程式碼
ndk {
    moduleName "JniDemo"
    ldLibs "log", "z", "m"
    abiFilters "armeabi", "armeabi-v7a", "x86"
}

整體程式碼如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.example.shaofenglan.ndkdemo"
        minSdkVersion 9
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "JniDemo"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
}

projectgradle.properties目錄下新增:

android.useDeprecatedNdk=true

檢視projectlocal.properties目錄是否有配置ndk環境:

ndk.dir=【NDK路徑】


6、生成so檔案

執行Build->Rebuild Project就可以編譯出SO 檔案,如圖:

app -> build -> intermediates -> ndk -> debug -> lib 中可以看到生成的 so檔案,如圖:


7、呼叫so檔案


載入靜態庫:

static {
    System.loadLibrary("JniDemo");
}

然後呼叫native方法,程式碼如下:

package com.example.shaofenglan.ndkdemo;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

import com.jni.test.NativeUtil;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("TAG", NativeUtil.getJniString());
    }

    static {
        System.loadLibrary("JniDemo");
    }
}

控制檯列印: