Android NDK开发(二)编写计算器so文件之动态注册

Android NDK开发(二)编写计算器so文件之动态注册,第1张

Android NDK开发(二)编写计算器so文件之动态注册

一、创建空白项目

 二、创建控件(2个输入框、4个按钮分别id为:add,sub,mul,div)

 三、为控件添加事件:

package com.example.ndk_dongtaizhuce;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    //声明变量
    private EditText first;
    private EditText second;

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

    private float one;
    private float two;
    //加载JNI文件
    static {
        System.loadLibrary("jisuanqi");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化控件
        init();

        //开始运算
        yunsuan();
    }

    private void yunsuan(){
        //为按钮添加事件
        View.onClickListener cl = new View.onClickListener() {
            @Override
            public void onClick(View view) {
                switch (view.getId()){
                    case R.id.add:
                        //获取两个编辑框的值
                        one = Float.parseFloat(first.getText().toString());
                        two = Float.parseFloat(second.getText().toString());
                        //显示
                        Toast.makeText(MainActivity.this,add(one,two)+"",Toast.LENGTH_LONG).show();
                        break;
                    case R.id.sub:
                        //获取两个编辑框的值
                        one = Float.parseFloat(first.getText().toString());
                        two = Float.parseFloat(second.getText().toString());
                        Toast.makeText(MainActivity.this,sub(one,two)+"",Toast.LENGTH_LONG).show();
                        break;
                    case R.id.mul:
                        //获取两个编辑框的值
                        one = Float.parseFloat(first.getText().toString());
                        two = Float.parseFloat(second.getText().toString());
                        Toast.makeText(MainActivity.this,mul(one,two)+"",Toast.LENGTH_LONG).show();
                        break;
                    case R.id.div:
                        //获取两个编辑框的值
                        one = Float.parseFloat(first.getText().toString());
                        two = Float.parseFloat(second.getText().toString());
                        Toast.makeText(MainActivity.this,div(one,two)+"",Toast.LENGTH_LONG).show();
                        break;
                    default:
                        break;
                }
            }
        };
        add.setonClickListener(cl);
        sub.setonClickListener(cl);
        mul.setonClickListener(cl);
        div.setonClickListener(cl);
    }

    //初始化控件
    private void init(){
        //绑定两个编辑框
        first = (EditText) findViewById(R.id.editText);
        second = (EditText) findViewById(R.id.editText2);

        //绑定四个按钮
        add = (Button) findViewById(R.id.add);
        sub = (Button) findViewById(R.id.sub);
        mul = (Button) findViewById(R.id.mul);
        div = (Button) findViewById(R.id.div);
    }

    //定义native方法,实现在so层
    public native float add(float one,float two);
    public native float sub(float one,float two);
    public native float mul(float one,float two);
    public native float div(float one,float two);


}

在app目录下创建新目录命名为JNI,创建jisuanqi.c文件

  编写以下代码:

#include //引入头文件
//功能函数
jfloat addc(JNIEnv* env,jobject obj,jfloat a,jfloat b){
    return a + b;
}

jfloat subc(JNIEnv* env,jobject obj,jfloat a,jfloat b){
    return a - b;
}

jfloat mulc(JNIEnv* env,jobject obj,jfloat a,jfloat b){
    return a * b;
}

jfloat divc(JNIEnv* env,jobject obj,jfloat a,jfloat b){
    return a / b;
}

//绑定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){
    //获取类
    jclass clazz = (*env)->FindClass(env,"com/example/ndk_dongtaizhuce/MainActivity");
    //注册方法                 env:this、clazz:类、nativeMethod:注册方法、注册函数个数
    if((*env)->RegisterNatives(env,clazz,nativeMethod,sizeof(nativeMethod)/sizeof(nativeMethod[0]))!=JNI_OK){
        return JNI_ERR;
    }
    return JNI_OK;
}
//使用JNI_OnLoad进行动态注册
JNIEXPORT jint JNICALL JNI_onLoad(JavaVM* vm,void* reserved){
    JNIEnv* env;
                    //vm,void**:二级指针,JNI_VERSION_1_4:jni版本
    if( (*vm)->GetEnv(vm,(void**)&env,JNI_VERSION_1_4)!=JNI_OK){
        return JNI_ERR;
    }

    if(registerNative(env)!=JNI_OK){
        return JNI_ERR;
    }
    return JNI_VERSION_1_4;
}

 新建Android.mk和Application.mk

#Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := jisuanqi	#模块名称
LOCAL_SRC_FILES := jisuanqi.c #源文件  .c或者.cpp
LOCAL_ARM_MODE := arm #编译后的指令集 ARM指令
LOCAL_LDLIBS += -llog #依赖库
include $(BUILD_SHARED_LIBRARY) #指定编译文件的类型

#Application.mk文件
APP_ABI := all

 cmd来到当前文件夹下:ndk-build

 表示成功。

一、静态注册和动态注册的区别:

静态方法文件名过长:Java+包名+类名+方法名(native方法)

例:Java_com_example_demo_1jni_MainActivity_getstring

调用native方法时速度慢。

动态方法:有JNINativeMethod函数映射表,调用时查找速度快,方法名可以自定义。

JNI_OnLoad方法在启动so文件时最先调用,并注册方法到环境。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5683553.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存