Android JNI开发流程(android开发艺术探索随笔)

今天来了兴趣想更搞下JNI,于是乎拿起任玉刚的Android开发艺术看了会,看起来挺简单的,但是做的时候各种问题。经过自己的努力,也算是弄好了。那么就来和大家分享下。
这篇博客的所用的是Ubuntu14.04+android studio(1.0版本)+JDK1.8.x,因为这台电脑很久没用,所以是低版本。

接下来便按照任教主的方法来一步一步走下去,当让,其中会有很多坑。。。

  • 在java中声明native方法
package com.gl.jnidemo;

/** * Created by guolei on 15-10-31. */
public class JniTest {
    static {
        System.loadLibrary("jni-test");
    }

    public static void main(String args[]){
        JniTest jniTest = new JniTest();
        System.out.println(jniTest.get());
        jniTest.set(" hello world jni");
    }

    public native String get();
    public native void set(String str);
}

  • 编译java源文件得到class文件并且,得到.h头文件。
    在编译之前,先来看下我自己的目录结构。
    Android JNI开发流程(android开发艺术探索随笔)_第1张图片

看到了目录结构,我们就开始了。首先我在这里不建议大家用as自带的终端来控制,因为我在用的时候出了点问题。
编译成class文件,首先进入到java文件夹下面。
在终端输入

javac com/gl/jnidemo/JniText.java 

回车,我们进去包下面看看。

cd com/gl/jnidemo

ls


看到,多出来了.class文件。

接下来就编译.h文件了。我们会退到java目录下

javac com.gl.jnidemo.JniText 

或许上面这一句可以成功编译出.h头文件,但是很遗憾我没成,

别着急,试试下面的这一条

javac -classpath . -jni com.gl.jnidemo.JniText

如果上面的一条还是不行的话,那么 请去终端输入吧。

经过上面的步骤,已经成功生成.h头文件了。
我们看看生成的.h文件的代码

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

#ifndef _Included_com_gl_jnidemo_JniTest
#define _Included_com_gl_jnidemo_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/* * Class: com_gl_jnidemo_JniTest * Method: get * Signature: ()Ljava/lang/String; */
JNIEXPORT jstring JNICALL Java_com_gl_jnidemo_JniTest_get
  (JNIEnv *, jobject);

/* * Class: com_gl_jnidemo_JniTest * Method: set * Signature: (Ljava/lang/String;)V */
JNIEXPORT void JNICALL Java_com_gl_jnidemo_JniTest_set
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

做一下简要说明

  • 函数名的格式 Java_包名_类名 方法名 ,抽筋,打不出来,自己对照的看看吧
  • JNIEnv* 指向jni环境的指针,可以通过他来访问jni提供的接口方法
  • jobject 表示java对象中的this,
  • JNIEXPORT和JNICALL 他们是jni所定义的宏,可以在jni.h这个文件中找到
  • 实现JNI方法
    首先我们右键包,新建一个floder,选择jni,就会在java同级目录下,生成jni文件夹,我们先把生成的.h头文件复制过去。
    接着,我们在jni文件夹下面,建一个test.cpp文件(这里我只做c++)的。
    我们看下test.cpp
#include "com_gl_jnidemo_JniTest.h"
#include <stdio.h>

JNIEXPORT jstring JNICALL Java_com_gl_jnidemo_JniTest_get(JNIEnv *env, jobject thiz) {
    printf("invoke get in c++\n");
    return env->NewStringUTF("Hello from JNI !");
}

JNIEXPORT void JNICALL Java_com_gl_jnidemo_JniTest_set(JNIEnv *env, jobject thiz, jstring string) {
    printf("invoke set from C++\n");
    char* str = (char*)env->GetStringUTFChars(string,NULL);
    printf("%s\n", str);
    env->ReleaseStringUTFChars(string, str);
}

上面的函数名就是.h文件中的函数.
最后,我们生成.so文件,这里也是一个大坑。mac电脑上上午还能生成,下午来了就告我少个jni_md.h头文件。结果逼我跑到另一台电脑上搞。

gcc -shared -I JDK路径/include -fPIC test.cpp -o libjni-test.so

按照上面的格式在终端输入,比如我这里

gcc -shared -I /usr/lib/jvm/default-java/include -fPIC test.cpp -o libjni-test.so

JDK路径在as配置中看就好,回车,就生成的.so文件

  • 测试
    在终端输入
java -Djava.library.path=../jni com.gl.jnidemo.JniTest

-Djava.library.path=so文件路径,请对照我最先给出的图。

最后,来张效果图,被电脑坑的不要不要的,弄出来自己也是很高兴。
Android JNI开发流程(android开发艺术探索随笔)_第2张图片

好,今天就到这里了,祝大家学习愉快。

你可能感兴趣的:(android,命令,jni)