so层Java层绑定函数_动态注册


一、编写java代码

  1.java代码编写如下:

package com.example.mypc.myxphook;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Button add;
    private Button sub;
    private Button mul;
    private Button div;

    private float oneParam;
    private float twoParam;

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


    //Actity创建事件
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        go();
    }
    //调用go方法来计算并且给出
    private void go(){
       final View.OnClickListener cl = new View.OnClickListener(){
            @Override
            public void onClick(View v){
                //获取第一个编辑框的内容
                EditText e1 = (EditText) findViewById(R.id.editText);
                oneParam = Float.parseFloat(e1.getText().toString());
                //获取第二个参数
                EditText e2 = (EditText) findViewById(R.id.editText2);
                twoParam = Float.parseFloat(e2.getText().toString());
                switch (v.getId()){
                    case R.id.button2 :
                        Toast.makeText(getApplicationContext(),"计算结果为:"+String.valueOf(add(oneParam,twoParam)),Toast.LENGTH_LONG).show();
                        break;
                    case R.id.button3 :
                        Toast.makeText(getApplicationContext(),"计算结果为:"+String.valueOf(sub(oneParam,twoParam)),Toast.LENGTH_LONG).show();
                        break;
                    case R.id.button4 :
                        Toast.makeText(getApplicationContext(),"计算结果为:"+String.valueOf(mul(oneParam,twoParam)),Toast.LENGTH_LONG).show();
                        break;
                    case R.id.button5 :
                        Toast.makeText(getApplicationContext(),"计算结果为:"+String.valueOf(div(oneParam,twoParam)),Toast.LENGTH_LONG).show();
                        break;
                    default:
                        Toast.makeText(getApplicationContext(),"未找到对应的执行函数...",Toast.LENGTH_LONG);
                        break;
                }
            }

        };
        //设置加法按钮的点击事件
        add.setOnClickListener(cl);
        //设置减法按钮的点击事件
        sub.setOnClickListener(cl);
        //设置减法按钮的点击事件
        mul.setOnClickListener(cl);
        //设置减法按钮的点击事件
        div.setOnClickListener(cl);
    }

    //初始化控件
    private void init(){
        //绑定四个按钮
        add = (Button) findViewById(R.id.button2);
        sub = (Button) findViewById(R.id.button3);
        mul = (Button) findViewById(R.id.button4);
        div = (Button) findViewById(R.id.button5);
    }

    //Native层的加法
    public native float add(float one,float two);
    //Native层的减法
    public native float sub(float one,float two);
    //Native层的乘法
    public native float mul(float one,float two);
    //Native层的除法
    public native float div(float one,float two);
}


  2.xml布局代码编写如下:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    tools:layout_editor_absoluteY="81dp">

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="+"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/button4"
        app:layout_constraintStart_toStartOf="@+id/button4"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="55dp"
        android:text="-"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="@+id/button2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="@+id/button2" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="41dp"
        android:layout_marginTop="30dp"
        android:text="*"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button2" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="/"
        android:textSize="24sp"
        android:textStyle="bold"
        app:layout_constraintStart_toStartOf="@+id/button3"
        app:layout_constraintTop_toBottomOf="@+id/button3" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginTop="51dp"
        android:text="第一个数:"
        android:textColor="@android:color/holo_red_light"
        android:textStyle="bold"
        app:layout_constraintEnd_toStartOf="@+id/editText"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginTop="27dp"
        android:text="第二个数:"
        android:textColor="@android:color/holo_red_light"
        android:textStyle="bold"
        app:layout_constraintEnd_toStartOf="@+id/editText2"
        app:layout_constraintHorizontal_chainStyle="packed"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />

    <EditText
        android:id="@+id/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="14dp"
        android:ems="10"
        android:inputType="number"
        app:layout_constraintBaseline_toBaselineOf="@+id/textView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView" />

    <EditText
        android:id="@+id/editText2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="14dp"
        android:ems="10"
        android:inputType="number"
        app:layout_constraintBaseline_toBaselineOf="@+id/textView2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/textView2" />
</android.support.constraint.ConstraintLayout>

Java代码1

java代码2

java代码3


  3.编写so层代码也就是C代码如下:
//
// Created by MyPC on 2020/4/17.
//
#include <jni.h>



//c语言实现加法,返回结果
jfloat addc(JNIEnv* env, jobject obj, jfloat one, jfloat two){
    return one+two;
}

//c语言实现减法,返回结果
jfloat subc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one-two;
}

//c语言实现乘法,返回结果
jfloat mulc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one*two;
}

//c语言实现除法,返回结果
jfloat divc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one/two;
}

//定义数组双向绑定c层函数名和java函数名
JNINativeMethod nativeMethod[]={
    {"add","(FF)F",(void*)addc},
    {"sub","(FF)F",(void*)subc},
    {"mul","(FF)F",(void*)mulc},
    {"div","(FF)F",(void*)divc}
};
//注册函数
jint registerNative(JNIEnv* env){
    //获取java类
    jclass clazz = (*env)->FindClass(env,"com/example/mypc/myxphook/MainActivity");
    //动态注册函数 也可以说是绑定函数C与JAVA
    jint res = (*env)->RegisterNatives(env,clazz,nativeMethod,sizeof(nativeMethod)/sizeof(nativeMethod[0]));
    //判断是否注册成功
    if(res != JNI_OK){
        return JNI_ERR;
    }
    return JNI_OK;
}
//使用JNI_OnLoad函数动态注册函数
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){

    JNIEnv* env;
    //获取env返回状态
    jint res =(*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4);
    //判断是否成功
    if(res != JNI_OK){
        return JNI_ERR;
    }else if(registerNative(env) != JNI_OK){
        return JNI_ERR;
    }
    //注册成功必须返回JNI版本号
    return  JNI_VERSION_1_4;
}

C代码1

C代码2



  4.运行结果如下:

加法运算结果 减法运算结果

乘法运算结果 除法运算结果



总结:首先编写Java层代码,定义好native函数以及返回值类型和参数,然后编写C代码,流程如下:

   1.引入jni.h头文件
#include <jni.h>

   2.编写对应Java层的native函数的实现
//c语言实现加法,返回结果
jfloat addc(JNIEnv* env, jobject obj, jfloat one, jfloat two){
    return one+two;
}

//c语言实现减法,返回结果
jfloat subc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one-two;
}

//c语言实现乘法,返回结果
jfloat mulc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one*two;
}

//c语言实现除法,返回结果
jfloat divc(JNIEnv* env,jobject obj, jfloat one, jfloat two){
    return one/two;
}

   3.定义双向绑定的数组,代码如下:
//定义数组双向绑定c层函数名和java函数名,第一个是java层函数名,第二个函数名签名,第三个c层的函数
JNINativeMethod nativeMethod[]={
    {"add","(FF)F",(void*)addc},
    {"sub","(FF)F",(void*)subc},
    {"mul","(FF)F",(void*)mulc},
    {"div","(FF)F",(void*)divc}
};

   3.开始绑定双向函数,代码如下:
//注册函数
jint registerNative(JNIEnv* env){
    //获取java类,传入env 和 类名
    jclass clazz = (*env)->FindClass(env,"com/example/mypc/myxphook/MainActivity");
    //动态注册函数 也可以说是绑定函数C与JAVA,env,class,绑定函数的数组,数组的长度
    jint res = (*env)->RegisterNatives(env,clazz,nativeMethod,sizeof(nativeMethod)/sizeof(nativeMethod[0]));
    //判断是否注册成功
    if(res != JNI_OK){
        return JNI_ERR;
    }
    return JNI_OK;
}

   4.默认加载的JNI_Onload函数内调用注册函数,代码如下:
//使用JNI_OnLoad函数动态注册函数
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved){

    JNIEnv* env;
    //获取env返回状态
    jint res =(*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4);
    //判断是否成功
    if(res != JNI_OK){
        return JNI_ERR;
    }else if(registerNative(env) != JNI_OK){//这里就调用了上面的注册方法
        return JNI_ERR;
    }
    //注册成功必须返回JNI版本号
    return  JNI_VERSION_1_4;
}

在浏览的同时希望给予作者打赏,来支持作者的服务器维护费用.一分也是爱~