前置知识

ARM是嵌入式设备的主流品牌,A系列针对的是高性能的设备比如手机

架构名称

支持指令集

位数

性能

适用设备

当前状态

arm64-v8a

ARMv8-A

64位

高性能和高能效

现代设备(主流架构)

主流,强烈推荐

armeabi-v7a

ARMv7-A

32位

中等性能

较旧设备或低端设备

次主流,逐渐被替代

armeabi

ARMv5TE

32位

性能较低

非常旧的设备

已废弃,不再使用

走进JNI

 https://github.com/jp1017/HelloJni?tab=readme-ov-file

java层代码

// 定义包名,用于组织和管理代码
package github.jp1017.hellojni;

// 导入需要使用的Android类
import android.os.Bundle;                                  // 用于传递数据
import android.support.design.widget.FloatingActionButton; // Material Design浮动按钮
import android.support.design.widget.Snackbar;            // Material Design提示条
import android.support.v7.app.AppCompatActivity;          // 应用程序活动基类
import android.support.v7.widget.Toolbar;                 // 工具栏组件
import android.util.Log;                                  // 日志工具
import android.view.Menu;                                 // 菜单
import android.view.MenuItem;                             // 菜单项
import android.view.View;                                 // 视图基类
import android.widget.Toast;                              // 提示框组件

// MainActivity类,继承自AppCompatActivity
public class MainActivity extends AppCompatActivity {

    /**********************************   JNI 开始 *********************************/
    /**
     * 静态代码块加载库
     * 在类加载时就会执行,加载名为"hello_jni"的native库
     */
    static {
        System.loadLibrary("hello_jni");
    }

    // 声明native方法,使用静态注册方式
    public native String staticRegFromJni();      //静态方法注册,实现在C代码中

    // 声明native方法,使用动态注册方式
    public native String dynamicRegFromJni();     //动态方法注册,实现在C代码中

    /**********************************   JNI 结束  *********************************/

    // Activity创建时调用的方法
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // 调用父类的onCreate方法
        super.onCreate(savedInstanceState);
        // 设置界面布局
        setContentView(R.layout.activity_main);
        // 初始化工具栏
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // 初始化浮动按钮
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        // 设置按钮点击监听器
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 创建并显示一个Snackbar提示条
                Snackbar.make(
                        view,                    // 指定Snackbar的显示位置(通常是当前视图)
                        "替换为你的操作",         // 显示的提示文本
                        Snackbar.LENGTH_LONG     // 显示时长:LENGTH_LONG约2.5秒
                )
                        .setAction(
                                "操作",          // 操作按钮的文本
                                null            // 按钮点击监听器,null表示不执行任何操作
                        )
                        .show();                // 显示Snackbar
            }
        });
    }

    // 创建选项菜单
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // 加载菜单布局文件,将菜单项添加到操作栏
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    // 处理菜单项选择事件
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // 获取被点击的菜单项ID
        int id = item.getItemId();

        // 处理设置菜单项的点击
        if (id == R.id.action_settings) {
            return true;
        }

        // 如果不是设置菜单,交由父类处理
        return super.onOptionsItemSelected(item);
    }

    /**
     * 按钮点击事件处理方法
     * @param view 被点击的视图对象
     */
    public void onClick(View view) {
        // 根据被点击的按钮ID执行相应操作
        switch (view.getId()) {
            case R.id.bt_static:
                // 调用静态注册的native方法并记录日志
                Log.d("日志", staticRegFromJni());
                // 显示Toast提示
                Toast.makeText(this, staticRegFromJni(), Toast.LENGTH_SHORT).show();
                break;

            case R.id.bt_dynamic:
                // 调用动态注册的native方法并记录日志
                Log.d("日志", dynamicRegFromJni());
                // 显示Toast提示
                Toast.makeText(this, dynamicRegFromJni(), Toast.LENGTH_SHORT).show();
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.

c层代码

#include <jni.h>


/*********     静态注册方法 staticRegFromJni   ***********/
//方法名:Java_完整包名类名_方法名();
/**
 * env : 代表Java环境, 通过这个环境可以调用Java中的方法。类似
 * obj : 代表调用JNI方法的对象, 即MainActivity对象。类似this指针
 */
JNIEXPORT jstring JNICALL Java_github_jp1017_hellojni_MainActivity_staticRegFromJni(JNIEnv * env, jobject obj)
{
    return (*env) -> NewStringUTF(env, "静态注册调用成功"); //C 的字符串转成 Java 的字符串返回。JNI本质上也是一种c和java的中间库,它可以调用C方法。JNI函数表(JNINativeInterface)是一个包含了所有 JNI 函数指针的结构体,它就像是一个"功能目录表"。将字符串关联到对应多线程env
}


/*********     动态注册方法 dynamicRegFromJni   ***********/

static jstring nativeDynamicRegFromJni(JNIEnv *env, jobject obj)
{
    return (*env) -> NewStringUTF(env, "动态注册调用成功");
}

//方法数组,正是这个,可以动态调用任意 native 方法 ,dynamicRegFromJni是java的方法,()Ljava/lang/String;是java的方法签名

JNINativeMethod nativeMethod[] = {
         
         {"dynamicRegFromJni", "()Ljava/lang/String;", (void*)nativeDynamicRegFromJni}};

// JNIEXPORT      // JNI导出标记,让这个函数可以被Java层调用
// jint           // 返回一个整数(Java的int)
// JNICALL