Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android studio 中使用Jni

Android studio 中使用Jni

編輯:關於Android編程

在使用Jni之前,我們需要對android studio進行一些配置:

有網的時候:在設置 - plugin - Android NDK Support 勾選--install plugin for disk 然後再打開設置---system setting--android SDK --sdk tool ---勾選上NDK 沒網的時候:直接下載下來並進行解壓
下載鏈接:點擊打開鏈接 一、環境配置: 1、解壓ndk到指定目錄(該目錄不能出現中文和空格) 修改系統的環境變量,在path裡加上D:\soft\ndk\android_ndk_r10e; 2、創建Project 1)在local.properties文件裡添加ndk路徑ndk.dir=D\:\\soft\\ndk\\android_ndk_r10e 2)在build裡添加
      ndk{
         moduleName "Hello"  //可根據自己取,表示.so文件的前綴
         ldLibs "log"  //打印日志
         abiFilters "armeabi", "armeabi-v7a", "x86"  //指定CPU
        }
注意://如果你編寫的.c文件include的時候報紅,在build.gradle裡添加
        sourceSets.main {
           jni.srcDirs 'src/main/source'
          }
最後build.gradle的代碼:
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.suixi.ndkproject"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk{
            moduleName "javaCallC"
            ldLibs "log"  //打印日志
            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.2.1'
    compile 'com.jakewharton:butterknife:6.0.0'
}
3、兼容老的NDK 在gradle.properties裡添加: android.useDeprecatedNdk=true   二、若要在C語言中進行LOG日志 在build.gradle
    ndk{
       moduleName "cCallJava"
       ldLibs "log"  //打印日志
       abiFilters "armeabi", "armeabi-v7a", "x86"
       }
在.c文件中添加如下代碼
   #include 
   #define LOG_TAG "linzhenxiang"
   #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
   #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
   #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
  三、編寫java調用c語言的方式   1、寫一個java類JNI(類名可自取),用於寫native代碼
public class JNI {
    public native String sayHello();//簡單的調用
    public native String sayAddHello(String s);//字符串拼接
    public native int add(int x,int y);//加法運算
    public native int[] increaseArray(int[] arr );//給數組的每個元素都增加10
    public native int checkPwd(String s);//檢查密碼是否正確,並返回值
}
2、動態的生成你所需要的C的頭文件的兩種方法 1)、在\NDKDEMO\app\src\main\java 執行命令:javah com.suixi.ndkproject.JNI(包名+類名) 2)、在studio底部中的terminal 裡執行javah javah com.suixi.ndkproject.JNI
  會自動生成如下的代碼:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_suixi_ndkproject_JNI */

#ifndef _Included_com_suixi_ndkproject_JNI
#define _Included_com_suixi_ndkproject_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_suixi_ndkproject_JNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello
  (JNIEnv *, jobject);

/*
 * Class:     com_suixi_ndkproject_JNI
 * Method:    sayAddHello
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_suixi_ndkproject_JNI
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_suixi_ndkproject_JNI
 * Method:    increaseArray
 * Signature: ([I)[I
 */
JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray
  (JNIEnv *, jobject, jintArray);

/*
 * Class:     com_suixi_ndkproject_JNI
 * Method:    checkPwd
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_checkPwd
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
3、在java中右鍵新建JniFodler,將上一步生成的.h文件移入改文件夾中
  4、rebuild Project 下,會在build-->intermediates生成ndk文件夾
\
  5、在JNI類下加載動態鏈接庫
    public class JNI {
    {
        System.loadLibrary("javaCallC");//動態加載。so文件,只要在用之前加載就成,不一定在這個類裡加載
    }
    public native String sayHello();//簡單的調用
    public native String sayAddHello(String s);//字符串拼接
    public native int add(int x,int y);//加法運算
    public native int[] increaseArray(int[] arr );//給數組的每個元素都增加10
    public native int checkPwd(String s);//檢查密碼是否正確,並返回值

   }

6、在jni文件夾下新建test.c文件,進行代碼編寫
#include "test.h"
#include "com_suixi_ndkproject_JNI.h"
#include 
#include 
#include 
#include 
#define LOG_TAG "linzhenxiang"//打印日志的別名,可自己去
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

//jstring to char*  jString 轉換成 char*指針
char *jstringTochar(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env, "utf-8");
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) (*env)->CallObjectMethod(env, jstr, mid, strencode);
    jsize alen = (*env)->GetArrayLength(env, barr);
    jbyte *ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    (*env)->ReleaseByteArrayElements(env, barr, ba, 0);
    return rtn;
}

JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayHello
        (JNIEnv *env, jobject jobject1) {
    // jstring     (*NewStringUTF)(JNIEnv*, const char*);
    char *s = "I AM FROM C";
    return (*env)->NewStringUTF(env, s);

};

/**
 * 返回帶有參數的字符串
 */
JNIEXPORT jstring JNICALL Java_com_suixi_ndkproject_JNI_sayAddHello
        (JNIEnv *env, jobject jobject1, jstring js) {

    char *from = jstringTochar(env, js);
    char *to = "I am from c";

    strcat(from, to);//字符串拼接,會把拼接後的結果放在第一個參數裡

    return (*env)->NewStringUTF(env, from);


};

/**
 * 加法運算
 */

JNIEXPORT jint JNICALL Java_com_suixi_ndkproject_JNI_add
        (JNIEnv *env, jobject jobject1, jint x, jint y) {
    return x + y;
};

/**
 * 給數組的每個元素添加10
 */
JNIEXPORT jintArray JNICALL Java_com_suixi_ndkproject_JNI_increaseArray
        (JNIEnv *env, jobject jobject1, jintArray array) {
    //jsize       (*GetArrayLength)(JNIEnv*, jarray);
    jsize size = (*env)->GetArrayLength(env,array);//獲取數組的長度
    //    jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
    jint* jint1 =  (*env)->GetIntArrayElements(env,array,JNI_FALSE);//獲取數組中的元素
    int i;
    for(i=0;i

四:在C中調用Java的方式1、寫一個java類JNI(類名可自取),用於寫native代碼
public class JNI {
    /**
     * 當執行這個方法的時候,讓C代碼調用
     * public void helloFromJava()
     */
    public native void callbackHelloFromJava();

    public void helloFromJava() {
        Log.e("TAG", "helloFromJava()");
    }
}
2、動態的生成你所需要的C的頭文件的兩種方法 1)、在\NDKDEMO\app\src\main\java 執行命令:javah com.suixi.ndkproject.JNI(包名+類名) 2)、在studio底部中的terminal 裡執行javah javah com.suixi.ndkproject.JNI

3、在java中右鍵新建JniFodler,將上一步生成的.h文件移入改文件夾中
4、rebuild Project 下,會在build-->intermediates生成ndk文件夾

5、在JNI類下加載動態鏈接庫
public class JNI {
    {
        System.loadLibrary("cCallJava");
    }
    /**
     * 當執行這個方法的時候,讓C代碼調用
     * public void helloFromJava()
     */
    public native void callbackHelloFromJava();

    public void helloFromJava() {
        Log.e("TAG", "helloFromJava()");
    }
}
6、編寫.c文件
#include "Test2.h"
#include 
#include 
#include 
JNIEXPORT void JNICALL Java_com_suixi_myapplication_JNI_callbackHelloFromJava(JNIEnv *env, jobject instance) {

    //jclass      (*FindClass)(JNIEnv*, const char*);
   jclass jclazz = (*env)->FindClass(env,"com/suixi/myapplication/JNI");//第二個參數表示的是JNI所在的包名+類名
    //第三個參數表示的是你要調用的java類中的方法,
    //第四個參數表示的是簽名:定位到JNI.class文件的位置,通過命令行:javap -s com/suixi/myapplication/JNI.class
    //                       生成簽名
    jmethodID  jmethodID1 = (*env)->GetMethodID(env,jclazz,"helloFromJava","()V");

    // jobject     (*AllocObject)(JNIEnv*, jclass);
    jobject jobject1 = (*env)->AllocObject(env,jclazz);

    //通過該方法調用即可
    (*env)->CallVoidMethod(env,jobject1,jmethodID1);

};

注意:GetMethodID的簽名的生成方法
定位到:build-->intermediates-->classes-->debug
按住 shift+鼠標右鍵 ----->點擊此處打開命令窗口
執行:javap -s com/suixi/myapplication/JNI.class
生成如下簽名:

\
7、在activity中調用
public class MainActivity extends Activity {

    private JNI jni;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.inject(this);
        jni = new JNI();
    }

    @OnClick({R.id.bt1})
    public void onClick(View v){
        switch (v.getId()){
            jni.callbackHelloFromJava();
        }
    }
}

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved