嘔心瀝血Android studio使用JNI實例


發現網上很多JNI的使用教程,也很詳細,不過有的地方有些缺漏,導致很多小問題難以解決的,今天就來總結一下。

 

准備工作:下載NDK。

簡單的說,要用到C/C++,就要用NDK。直接百度搜索然后去官網下載就行,位置可以隨便放。

 

1、新建一個類,聲明native方法。這個類是java與C/C++交互的中介,方法由java聲明,由C/C++實現。

不在Activity類里面寫是為了避免編譯時報錯:找不到android.support.v7.app.AppCompatActivity

public class myJNI {

  //加載so庫
static { System.loadLibrary("JniTest"); }   //native方法 public static native String sayHello(); }

 

2、打開android studio終端,使用javac編譯上述文件,生成class文件。

 

命令:

D:\AndroidStudioProject\testJNI\app\src\main\java\com\example\binbin\testjni>javac myJNI.java

 

3、確認自己類的包名!然后在上一級的位置使用javah生成.h頭文件

一定要在上一級哦,不然不會報錯:找不到xxx類

 

比如我的myJNI.class在

D:\AndroidStudioProject\testJNI\app\src\main\java\com\example\binbin\testjni

我的包名是:

package com.example.binbin.testjni;

所以我的javah命令應該這么寫:

D:\AndroidStudioProject\testJNI\app\src\main\java>javah -jni com.example.binbin.testjni.myJNI

 

然后就能看到生成了一個h文件。

 

4、新建一個jni文件夾,新建main.c,把.h里面的內容復制進去,並實現里面的函數。

 

生成的h文件

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

#ifndef _Included_com_example_binbin_testjni_myJNI
#define _Included_com_example_binbin_testjni_myJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_binbin_testjni_myJNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_binbin_testjni_myJNI_sayHello
        (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

 

拷貝修改后的main.c

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

#ifndef _Included_com_example_binbin_testjni_myJNI
#define _Included_com_example_binbin_testjni_myJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_binbin_testjni_myJNI
 * Method:    sayHello
 * Signature: ()Ljava/lang/String;
 */

//就實現了個函數 JNIEnv的用法可以自行百度,這里就不展開了 JNIEXPORT jstring JNICALL Java_com_example_binbin_testjni_myJNI_sayHello (JNIEnv *env, jclass jobj){
  //返回一句話
return (*env)->NewStringUTF(env,"JNI hahahahahahahaha"); } #ifdef __cplusplus } #endif #endif

 

還要在jni文件夾下添加一個空白的util.c文件,不然會報錯,我也不知道為什么。

 

 

5、配置NDK

打開Project的local.properties文件添加NDK路徑

  

  

打開app Module的build.gradle文件,在defaultConfig節點里添加以下代碼
注意這里的moduleName,是我們在之前自己編寫的類里面加載的so庫名
 ndk {
            moduleName "JniTest"
            ldLibs "log", "z", "m"
            abiFilters "armeabi", "armeabi-v7a", "x86"
        }

 

 

  

還要在gradle.properties里面加上這么一句話:
android.useDeprecatedNdk=true

 

6、生成SO庫

完成以上步驟之后,我們rebuild一下就可以生成so庫了

在項目的app\build\intermediates\ndk\debug\lib路徑下

 

7、配置so庫

在src\main下新建文件夾jniLIB,並將生成的SO文件拷貝到該文件夾下

 

8、使用JNI

因為native方法聲明成了靜態的方法,在Activity里面直接調用myJNI類就行

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


        text = (TextView)findViewById(R.id.text);
     //調用 text.setText(myJNI.sayHello()); } }

 

 

ok!

 

總結一下流程:

編寫靜態方法(用java聲明)-->編譯生成class文件--->編譯生成h文件---->編寫C文件(用C/C++實現)

---->配置NDK---->配置so庫---->在Activity調用(Java調用C/C++)。

 

android studio雖然很多小問題,但也算很方便了,mk文件編輯器幫你弄好了,直接可以生成so庫。

 
        

 

 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM