Jni系列1起航例子

为什么选择JNI,我想大家都应该有理解。要么就是前人写好了库,自己懒了不想重写,要么就是你们项目这个技术比较核心,不想轻松被人给反编译,也有可能你需要与底层打交道,这时候由于某种理由我们可能就需要选择JNI开发。

Jni实际上就是用于JAVA与C进行通信的,NDK是用来编译C语言文件成so给Android进行调用的。所以大家需要区分清楚JNI与NDK不同的功能。C语言中的函数通过jni数据类型接收JAVA的传入参数,但是一般jni数据类型我们不能直接在C中使用,这时候就需要将jni类型,转化为C语言能够使用的数据类型了。

本文以Android Studio为例来说明一个非常简单的JNI demo。个人觉得JNI在Android开发中还是比较重要的,况且最近项目因为实时性就用到了此块。打算好好讲解一下JNI开发。凡事以基础为起点,本文首先是运行起来一个JNI demo。另外我使用的是Android mk文件,Android Studio2.2已经可以使用CMakeList文件了,变得更加方便与智能,不过我觉得你习惯使用哪个,觉得哪个更顺手自己决定就好。

1,创建一个Android Studio项目,新建一个类JniUtils

package org.eclipse.paho.android.jnidemo.jniutil;

/**
 * Created by IBM on 2016/11/10.
 */

public class JniUtils {
    static {
        System.loadLibrary("jnilib");
    }
    public native int sum(int a,int b);
    public native String getString(String s1,String s2);

}

System.loadLibrary(“jnilib”);这个就是加载ndk编译生成的so库,此处生出的库名字是libjnilib.so,注意名字要去掉lib和lib.so

2,使用javah命令生成JniUtils的.h文件,名字是org_eclipse_paho_android_jnidemo_jniutil_JniUtils.h
本文生成的.h文件具体内容是:

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

#ifndef _Included_org_eclipse_paho_android_jnidemo_jniutil_JniUtils
#define _Included_org_eclipse_paho_android_jnidemo_jniutil_JniUtils
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_eclipse_paho_android_jnidemo_jniutil_JniUtils
 * Method:    sum
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_org_eclipse_paho_android_jnidemo_jniutil_JniUtils_sum
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     org_eclipse_paho_android_jnidemo_jniutil_JniUtils
 * Method:    getString
 * Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_org_eclipse_paho_android_jnidemo_jniutil_JniUtils_getString
  (JNIEnv *, jobject, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

3,新建jniUtils.c文件,就是开始写C代码实现

//
// Created by IBM on 2016/11/10.
//
#include "org_eclipse_paho_android_jnidemo_jniutil_JniUtils.h"
#include<stdlib.h>
// 引入log头文件
#include <android/log.h>
// log标签
#define TAG "JniUtils"
// 定义info信息
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
// 定义debug信息
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
// 定义error信息
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)

JNIEXPORT jint JNICALL Java_org_eclipse_paho_android_jnidemo_jniutil_JniUtils_sum
  (JNIEnv * env, jobject thiz, jint a, jint b){
    int re = a + b;
    return (jint)re;
  }

JNIEXPORT jstring JNICALL Java_org_eclipse_paho_android_jnidemo_jniutil_JniUtils_getString
  (JNIEnv * env, jobject thiz, jstring str1, jstring str2){
       char *str;
       //char result[256];
       str = (*env)->GetStringUTFChars(env,str1,NULL);

       //strcpy(result,str);
       (*env)->ReleaseStringUTFChars(env,str1,str);
       char *re = "jni to java";
       jstring ret = (*env)->NewStringUTF(env,re);
       return ret;
  }

具体的代码如果你是刚接触jni可以先不要搞懂,先照着例子做,我一般都是先看现象,再去看如何实现,这样能一开始放心能出结果。
3,编写mk文件
在Android Studio的jni目录下新建Android.mk文件和Application.mk文件
Android.mk:
LOCAL_PATH := (callmydir)include (CLEAR_VARS)
LOCAL_LDLIBS := -L (SYSROOT)/usr/libllogLOCALMODULE:=jnilibLOCALSRCFILES:=jniUtils.cinclude (BUILD_SHARED_LIBRARY)
Application.mk文件
APP_ABI := armeabi

4,然后你就可以使用ndk进行编译了。
现在回到MainActivity文件里,加入几行代码:

JniUtils jniUtils = new JniUtils();
        int re = jniUtils.sum(2,3);
        Log.i(TAG, "onCreate: Sum result is "+re);
        String r  = jniUtils.getString("hehe","haha");
        Log.i(TAG, "onCreate: getString result is"+r);

运行虚拟机即可看到控制台打印输出结果:
11-10 09:54:54.509 2546-2546/? I/MainActivity: onCreate: Sum result is 5
11-10 09:54:54.509 2546-2546/? I/MainActivity: onCreate: getString result isjni to java
说明我们的JNI例子是跑通的。

下一篇明天再写基本JNI数据类型与C语言的数据类型之间的转换关系。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值