Android Studio中编写jni代码并生成so文件和jar包

本文详细介绍如何通过JNI实现Java与Native方法的互相调用,包括编写JNI测试代码、生成和配置C文件、构建Android.mk及Application.mk文件、在MainActivity中调用测试,以及生成so文件和jar包的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实现:点击按钮,实现java与Native方法互调

1)
编写JNI测试代码

public class JNITest {
	static {
		System.loadLibrary("Hello");
	}
 
	public native String test();
 
}

2)生成JNITest对应的c文件,实现交互
A:生成.c文件
在这里插入图片描述
javah -jni 包名.类名

把生成的.h文件重命名并改后缀为.c,这里名称要和JNITest类中的System.loadLibrary("Hello");参数命名一致,故改名为Hello.c
B:创建jni目录,创建必要文件
在这里插入图片描述
main目录下新建jni文件,创建Adnroid.mk和Application.mk,刚才生成的Hello.c也移动至jni目录下
Android.mk文件是有语法的,详情自行查阅Android.mk语法,
Android.mk文件内容如下:固定写法

# 号为注释
#定义必须以LOCAL_PATH为开始,my-dir 则由Build System提供,固定写法
LOCAL_PATH := $(call my-dir)
#CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile,负责清理工作
include $(CLEAR_VARS)
#LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格
LOCAL_MODULE    := Hello
#LOCAL_SRC_FILES变量必须包含将要打包如模块的C/C++ 源码。
LOCAL_SRC_FILES := Hello.c
# 注明是动态编译,静态编译为BUILD_STATIC_LIBRARY
include $(BUILD_SHARED_LIBRARY)

Application.mk内容:

# 支持的CPU架构,也可以指定生成的架构,指定则使用下面注释的代码
APP_ABI :=all
# APP_ABI :=armeabi-v7a x86 arm64-v8a

注意,生成的Hello.c需要更改,这里贴出对应方法生成的代码,改造如下

JNIEXPORT jstring JNICALL Java_zz_hao_jni_JNITest_test
  (JNIEnv*  env, jobject jobj){
    char*  text = "hello,调用JNI成功~";
    return  (*env)-> NewStringUTF(env,text);
};

C:build.gradle文件中增加配置

android{
	.....
	//每次编译中执行Android.mk并使用ndk编译生成so文件并打入APK包,本地必须要下载ndk
	//如果自己生成so文件,则不需要一下代码
	externalNativeBuild {
        ndkBuild {
            path file('src/main/jni/Android.mk')
        }
    }
}

至此,jni相关配置已完成
3)
MainActivity中调用测试

  findViewById(R.id.btn_jni).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivity.this, new JNITest().test(), Toast.LENGTH_SHORT).show();
            }
        });
生成so文件,根据已经编写好的jni文件来生成

可能有的小伙伴会有疑问,上面的jni代码,对我们来讲,多少有些陌生,平时项目中也没有见到有jni文件夹、Android.mark、xxxx.c…等等一些c代码。确实,项目中一般不会出现这些文件,取而代之的是so文件,大家对so文件一定不陌生,引入一些三方库,比如百度地图、音乐播放器、等等一些,这些三方库在lib文件夹下,会有不同架构的so文件。
那么这些so文件是怎么产生的呢,就是根据上面编写的jni,生成的so文件
so文件打包的都是C代码,jar包则是.class文件,怎么理解jni,so库,ndk呢,下面举例说明,促进我们的理解

jni代码好比是小麦,so文件是面粉,NDK则是加工面粉的机器。

中午想吃顿面条,去超市买点面粉回来自己做。这个时候自然超市给的是面粉,不会给点小麦,在给个磨面的机器,让我们回家自己磨面吧。所以一般我们使用的时候,也都是用的so文件,第三方已经用NDK工具把jni代码加工成了so文件,提供给我们。

接下来我们要自己用磨面机来把小麦加工成面粉

正文:生成so文件

1) 首先我们要下载NDK(磨面之前必须得有磨面机嘛),并配置好环境变量,在黑窗口运行命令ndk-build来验证是否配置正确

2)在jni目录下运行黑窗口,执行ndk-build命令,这里会执行Android.mk文件。执行完成,会自动生成lib文件和相应的so文件

正文:生成jar包

我们可以把本示例中的JNITest类生成jar包

首先,对应一下目录结构,该jni相关代码都是在一个Library中,如果要单独类生成jar包,则需要新建一个Library,在该Library的build.gradle下配置以下代码

android{
	//生成jar包
    task makeJar(type: Copy) {
        delete 'build/outputs/test.jar'
        from('build/intermediates/packaged-classes/release/') //jar文件来源
        into('build/libs/') //生成路径
        include('classes.jar')
        rename('classes.jar', 'test.jar') //命名为network.jar
    }
    makeJar.dependsOn(build)
}

执行命令 gradlew makeJar
编译完成后在build-libs目录下,可以看到我们生成的jar包

报错:

ERROR: ABIs [armeabi] are not supported for platform. Supported ABIs are [armeabi-v7a, arm64-v8a, x86, x86_64].
配置了armeabi架构,ndk在编译的时候不支持,只支持 [armeabi-v7a, arm64-v8a, x86, x86_64].这四种的哪个架构。
很有可能A电脑没有报错,B电脑报这个错,(NDK版本不一致导致)因为从NDK r17版本开始,已经不再支持armeabi、mips、mips64这三种ABI了。如果要用armeabi,需要下载小于r17的ndk版本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值