android studio之JNI技术

一、环境准备
1.JDK
2.NDK
3.android studio
二、准备测试的项目
1.新建app项目
2.编写一个本地方法类,如下参考

/**
 * Created by jhone on 2015/11/23.
 */
public class JNIUtils {

    private static JNIUtils jniUtils;
    public synchronized static JNIUtils getInstants(){
        if (jniUtils==null){
            jniUtils=new JNIUtils();
        }
        return jniUtils;
    }
    //从C中获取信息的方法
    public native String getFormC();
    //传递信息到C中的方法
    public native void sendToC(int a);

}

3.在界面中显示效果,这里只测试了一个方法

public class JNIActivity extends AppCompatActivity {

    //加载libhello-jni.so库
    static {
        System.loadLibrary("hello-jni");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jni);
    }
    //界面buttion的点击事件
    public void click(View view){
        //调用JNIUtils中的本地方法声明,而该方法在.so库中具体实现
        String message=JNIUtils.getInstants().getFormC();
        Toast.makeText(this,message,Toast.LENGTH_LONG).show();
    }
}

上面的代码实现了java部分的代码,那么里面所涉及的本地方法在哪实现,怎么实现呢?那么NDK就派上用场了
声明的native本地方法在C中实现,NDK把我们写的C代码编译成.so库,也就是像我们在上面activity中加载的libjini-hello.so~

那么问题清楚了,只要我们将相应的.so文件放到我们项目的对应目录下,那么程序跑起来就OK了

三、准备.so库,实现本地方法
1.打开cmd终端,使用javac命令编译我们刚刚写的JNIUtils.java成JNIUtils.class文件(目的就是拿到.calss文件,所以其他方式也行)
2.使用javah命令将JNIUtils.class转换成.h文件,这里注意了,由于我们JNIUtils.java是有包名的
所以 javah JNIUtils这样是不行的
应该根据包名逐层新建文件夹,将JNIUtils.class放到里面,在使用javah 包名.JNIUtils.class,生成”com_example_jhone_j4java_base_JNIUtils.h”
3.在项目的src/main目录下新建jni文件夹,将上面生成的.h文件放在里面:
jni目录结构
Android.mk是JNI相关的描述文件,不可少
Application.mk是配置NDK平台版本的,保持默认就行
这两个文件可以从NDK目录的simple目录中的demo中获取
然后新建一个C文件hello-jni.c,hello-jni.h是自动生成的,你懂得
然后修改Android.mk描述文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni //.so文件名,自动加上lib
LOCAL_SRC_FILES := hello-jni.c  //要编译的文件,多个文件用空格隔开

include $(BUILD_SHARED_LIBRARY)

到这里jni所需要的文件都准备OK了,下面就是实现本地方法了
4.打开com.example_…_JNIUtils.h

#endif
/*
 * Class:     com_example_jhone_j4java_base_JNIUtils
 * Method:    getFormC
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jhone_j4java_base_JNIUtils_getFormC
  (JNIEnv *, jobject);

/*
 * Class:     com_example_jhone_j4java_base_JNIUtils
 * Method:    sendToC
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_example_jhone_j4java_base_JNIUtils_sendToC
  (JNIEnv *, jobject, jint);

#ifdef __cplusplus
}
#endif
#endif

观察可知是两个方法签名,没错就是本地方法映射到C中的方法签名,在hello-jni.c中实现这两个方法,就实现了java中那两个本地方法
5.打开hello-jni.c,开始编写C代码:

//
// Created by jhone on 2015/11/23.
//

#include<stdio.h>
#include<jni.h>
#include "com_example_jhone_j4java_base_JNIUtils.h"//同目录下这样导包
//使用上面映射过来的方法签名
JNIEXPORT jstring JNICALL Java_com_example_jhone_j4java_base_JNIUtils_getFormC(JNIEnv* env,jobject obj){
    return (*env)->NewStringUTF(env,"Hello JNI");//jni.h中的声明的方法函数
}

/*
 * Class:     com_example_jhone_j4java_base_JNIUtils
 * Method:    sendToC
 * Signature: (I)V
 */
JNIEXPORT void JNICALL Java_com_example_jhone_j4java_base_JNIUtils_sendToC(JNIEnv* env,jobject obj, jint a){

}

6.使用NDK项目编译jni这个目录,生成.so库
1>打开NDK目录结构如下:
这里写图片描述
可以看到ndk-build和ndk-build.cmd这个命令,不要疑惑
ndk-build是给linux用的,ndk-build.cmd是给window用的,大神们都说要安装sgwin,在sgwin中使用命令来编译.so,都说ndk-build.cmd会有什么什么问题,可能吧,但是我用这个挺爽,而且NDK都更新到10了,应该扶持window也不错了,等等,隔壁有动静~~
没错,就是用这个ndk-build.cmd命令来生成.so文件
2>将这个命令添加到环境变量,别问我怎么添加,我会告诉你和JDK是一样的
3>使用cmd命令进入到我们项目中的jni目录中,然后键入ndk-build,稍等片刻,看看项目目录有什么变化,对了,已经成功了
这里写图片描述
如图,生成了libs和obj两个目录,其中libs目录中就是我们要的.so文件,而obj并没有什么卵用,有大神就笑了,特么之前给我们看的图中也有这两个目录啊,呃呃,这下你可是给我造成了10000+伤害


对,jni就是这么简单,大神一键run,run完之后眼泪都快掉下来了,天呐,闪退了~~
其实还有个知识点没告诉你,在eclipse中,.so是放在libs目录中,而在android studio中,你要把这个libs目录改成jniLibs,注意,是这个libs而不是那个libs,别改错了,你懂的,然后就OK了,不信?不信你run一下就信了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一鱼浅游

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值