安卓JNI分析

安卓JNI分析

安卓JNI分析

jni定义
使用jni的原因
jni实现步骤
具体实现
jni数据类型

jni定义

jni(JavaNative Interface),java本地开发接口,一般上层Android应用程序通过Java虚拟机调用底层接口,衔接底层c/c++库与Java应用程序间的接口正是jni。

使用jni的原因

效率上c++优与java
代码移植,复用c++/c的模块
java容易被反编译

jni实现步骤

java类中书写对应的native方法
使用javah创建符合jni规范的C语言头文件
编写c++/c代码
书写makefile文件
使用ndk编译成so文件
在java层载入so文件并使用里面的方法

具体实现

书写native方法
     public native void CallNativcFromJava(byte[] arrray);

     public native void CallNativcFromJava2(byte[] arrray);
     // 测试Native访问C
     public native void CallNativcFromJava3();
     public native void CallNativcFromJava4();

这里写图片描述

生成对应jni方法

接口名字必须符合JNI规范
JNIEXPORT 函数返回值类型 JNICALL
Java_报名类名函数名(JNIEenv* env,jobject obj,参数列表)
{}

    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava(JNIEnv *env, jobject instance,                                                         jbyteArray arrray_)
        {
    }
    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava2(JNIEnv *env, jobject instance,                                                         jbyteArray arrray_)
    {
    }
    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava3(JNIEnv *env, jobject instance)
    {
    }
    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava4(JNIEnv *env, jobject instance)
    {
    }
书写对应代码
    #include <jni.h>
    #include <android/log.h>
    #include <stdio.h>
    #define TAG "System.out" // 这个是自定义的LOG的标识


    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型
    #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型
    #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型


    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava(JNIEnv *env, jobject instance,
                                                            jbyteArray arrray_)
    {
     char array[1024];
// 获取传递下来数组的长度
int len = (*env)->GetArrayLength(env,arrray_);
(*env)->GetByteArrayRegion(env,arrray_,0,len,array);

        int i;
     for(i = 0;i < len;i++)
      {
    array[i] += i;
    LOGI(" %d",array[i]);
}

(*env)->SetByteArrayRegion(env,arrray_,0,len,array);


    }

    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava2(JNIEnv *env, jobject instance,
                                                             jbyteArray arrray_)
    {
              //   获取传递下来数组的长度
    int len =             (*env)->GetArrayLength(env,arrray_);
// 对数组进行直接操作
char* pArray = (*env)->GetByteArrayElements(env,arrray_,0);

      int i;
        for(i = 0;i < len;i++)
{
    pArray[i] += i;
    LOGI(" %d",pArray[i]);
}

// 释放内存 防止内存泄漏
(*env)->ReleaseByteArrayElements(env,arrray_,pArray,0);

}

    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava3(JNIEnv *env, jobject instance)
    {
 // 获取域所属的类
jclass calzz = (*env)->GetObjectClass(env,instance);
// 定义域ID
jfieldID numberID = (*env)->GetFieldID(env,calzz,"number","I");
//  把域ID转成本地的基本数据类型
int num = (*env)->GetIntField(env,instance,numberID);
LOGI("************num = %d",num);
num += 1000;
//  获取方法ID
jmethodID showNumID = (*env)->GetMethodID(env,calzz,"showNumber","(I)V");
// 调用方法
(*env)->CallVoidMethod(env,instance,showNumID,num);
}

    JNIEXPORT void JNICALL
    Java_com_example_newyx_jnidemo2_MainActivity_CallNativcFromJava4(JNIEnv *env, jobject instance)
    {
// 获取ID 的class
jclass clazz = (*env)->GetObjectClass(env,instance);

// 获取域ID
jfieldID numID = (*env)->GetFieldID(env,clazz,"number","I");
jfieldID strID = (*env)->GetFieldID(env,clazz,"testStr","Ljava/lang/String;");
jfieldID chID = (*env)->GetFieldID(env,clazz,"ch","C");
jfieldID arrayID = (*env)->GetFieldID(env,clazz,"mArray","[B");

// 获取整形值
int num = (*env)->GetIntField(env,instance,numID);
LOGI("num = %d",num);
// 获取字符串
jstring str = (*env)->GetObjectField(env,instance,strID);
// 把jstring转换为char *
char *p = (*env)->GetStringUTFChars(env,str,0);
LOGI("string = %s",p);
// 获取字符 (注意是2个字节)
unsigned short ch = (*env)->GetCharField(env,instance,chID);
LOGI("ch = %d" , ch);
// 获取数组
jbyteArray mArray = (*env)->GetObjectField(env,instance,arrayID);
// 获取数组长度
int len = (*env)->GetArrayLength(env,mArray);
//  把jbayteArray转换为char数组
char* pArray = (*env)->GetByteArrayElements(env,mArray,0);

int i;
for(i = 0;i < len;i++)
{
    LOGI(" %d",pArray[i]);
    pArray[i] += 2;
}

// 获取方法ID
jmethodID showInfoID = (*env)->GetMethodID(env,clazz,"showInfo","(ILjava/lang/String;[B)Ljava/lang/String;");
// 调用方法
(*env)->CallObjectMethod(env,instance,showInfoID,num,str,mArray);

// 释放资源
(*env)->ReleaseStringUTFChars(env,str,p);
(*env)->ReleaseByteArrayElements(env,mArray,pArray,0);

}

这里写图片描述

mk书写(此处为gradle脚本)

    defaultconfig
            {
ndk
    {
moudleName “myjni.so”
ldLibs “LOG”
    }
    }

java层调用

static
{
    System.loadLibrary("myjni");
}

使用方法

    package com.example.newyx.jnidemo2;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity
{
private int number = 1000;
private String testStr = "fjsd";
private char ch = 'a';
private byte[] mArray= {1,2,3,4,5};
// 导入库
static
{
    System.loadLibrary("myjni");
}

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void testArray(View v)
{
    byte[] array = {3, 4, 5, 6, 7};
    CallNativcFromJava(array);
    for (byte i : array)
    {
        System.out.println(" " + i);
    }
}
public void testArray2(View v)
{
    byte[] array = {3, 4, 5, 6, 7};

    CallNativcFromJava(array);

    for (byte i : array)
    {
        System.out.println(" " + i);
    }
}
public void testDemo1(View v)
{
    System.out.println("number = " + number);
    CallNativcFromJava3();
}
public void testDemo2(View v)
{
    CallNativcFromJava4();
}
public void showNumber(int num)
{
    System.out.println("----->num = " + num);
}
public String showInfo(int num,String str,byte[] array)
{  System.out.println("-----------------------------------------------------------");
    System.out.println("num = "+ num);
    System.out.println("str = " + str);
    for(byte v : array)
    {
        System.out.println(" "+v);
    }
    return null;
}
// 声明本地接口
public native void CallNativcFromJava(byte[] arrray);
public native void CallNativcFromJava2(byte[] arrray);
// 测试Native访问C
public native void CallNativcFromJava3();
public native void CallNativcFromJava4();

}

jni数据类型

基础数据类型

这里写图片描述
引用数据类型

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值