目录
前言
之前其实写过,代码不见了,为了走一下流程,重新简单的写了一个。
PS:设计NDK环境配置这里不介绍哈
正文
静态注册
先由Java得到本地方法的声明,然后再通过实现该声明方法。
-
优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低
-
缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高
实战
定义Hello.java
加载Hello.so和native方法
package com.biumall.jni.one; public class Hello { //1. load Hello.so static { System.loadLibrary("Hello"); } // 2. define native hello() public static native String hello(); }
javac编译class
通过javac编译Hello.class,然后javah编译
进入Hello.java目录
#当前位置:BiuJniStatic\src\main\java\com\biumall\jni\one javac Hello.java
会在当前目录下生成
Hello.class
javah编译.h头文件
回退到 java目录
#当前位置:BiuJniStatic\src\main\java javah com.biumall.jni.one.Hello
会在当前目录生成
com_biumall_jni_one_Hello.h
创建JNI
工程更目录创建JNI目录
BiuJniStatic/jni
把上面com_biumall_jni_one_Hello.h头文件拷贝到jni目录,并改名为
Hello.h
Hello.h拷贝一份为Hello.c
Hello.c也可以改为Hello.cpp,cpp中需要用C++写,否则会报错。
如果Hello.c中用了C++语法就会提示
error: member reference base type 'JNIEnv' (aka 'const struct JNINativeInterface *') is not a structure or union]
反过了Hello.cpp中用C语言写也会有类似的提示。
编写Hello.c
下面代码新增log打印,新增的活修改的都有备注
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_biumall_jni_one_Hello */ //---- add start ----- #include <android/log.h> //---- add end ----- #ifndef _Included_com_biumall_jni_one_Hello #define _Included_com_biumall_jni_one_Hello #ifdef __cplusplus extern "C" { #endif /* * Class: com_biumall_jni_one_Hello * Method: hello * Signature: ()Ljava/lang/String; */ //---- modify start ----- //LOG_TAG #define LOG_TAG "from_static_jni_" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) JNIEXPORT jstring JNICALL Java_com_biumall_jni_one_Hello_hello (JNIEnv * env , jclass jclazz){ // [hello.c如果用C] LOGE("Java_com_biumall_jni_one_Hello_hello()"); return (*env)->NewStringUTF(env, "Hello World !!!! --- from JNI "); // [hello.cpp如果用C++] // 如果hello.c中用了这个,无法build过,提示[error: member reference base type 'JNIEnv' (aka 'const struct JNINativeInterface *') is not a structure or union] //return env->NewStringUTF((char *)"Hello World !---from JNI"); }; //---- modify end ----- #ifdef __cplusplus } #endif #endif
PS : 上面---- 等备注的都是有更新的地方,其他的都是Hello.h一样。
配置Application.mk和Android.mk
Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_LDLIBS := -llog LOCAL_MODULE := Hello LOCAL_SRC_FILES := Hello.c include $(BUILD_SHARED_LIBRARY)
-
LOCAL_MODULE : 为生成so库的名字
-
LOCAL_SRC_FILES : 为需要编译的源文件
Application.mk
APP_ABI := all
all表示全部平台,可编译出如下so库
├─arm64-v8a ├─armeabi ├─armeabi-v7a ├─mips ├─mips64 ├─x86 └─x86_64
当然,可以指定编译指定平台的so。
# 指定生成armeabi-v7a APP_ABI := armeabi-v7a # 或者指定多个[多个用空格分开] APP_ABI := armeabi-v7a arm64-v8a
编译JNI
进入
BiuJniStatic/jni
输入
ndk-build
如果ndk配置没问题,根目录会出现libs目录,也就生成对应的so库。
build.gradle配置so库
# BiuJniStatic/build.gradle android { compileSdkVersion 31 // 略 sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
编译运行,就可以测试Java调用JNI方法了。
参考文章
-
《》
-
《》
-
《》
历史上的今天
暂无评论...
随机推荐
Java的反射简介
前言本文主要参考其他作者的文章,然后自己整理一下,原文写得很仔细,但还得自己走一遍流程。感谢大佬分享。正文什么是Java的反射机制java允许开发者在程序运行过程中操作(访问和修改)类的各种属性以及方法。获取Class类对象java给我们提供了三种方式获取Class类对象。Sour...
bat脚本的变量初始化
前言 简单记录一下bat脚本(批处理文件)初始化变量和计数的使用。记录于此,方便自己查阅。正文初始化变量# 初始化count为0set /a count=0# 普通字符set read=BiuMall# 有特殊字符set "read=Biu&Mall"#...
再谈onConfigurationChanged
前言Android的onConfigurationChanged()这个方法很常见,之前关于横竖屏和语言切换的也介绍过,今天又一次再介绍一下之前没有介绍的。记录一下,方便自己查阅。也是流水文一篇。正文这里要分Application和Activity(或AppCompatActivity)来...
Android设置语言偏好后应用没有获取对设置的语言
前言之前朋友记录过,如两篇参考文章,今天特意看了一下,竟然有点重复,懒得删了。今天又遇到一种情况,获取不到系统配置的语言选项。记录于此,方便自己查阅。正文根据之前两篇文章,我们知道获取Configuration有如下方式隐藏内容!付费阅读后才能查看!¥1 ¥3多个隐藏块只需支付一次付费阅...
周作人:苦雨
伏园兄:北京近日多雨,你在长安道上不知也遇到否,想必能增你旅行的许多佳趣。雨中旅行不一定是很愉快的,我以前在杭沪车上时常遇雨,每感困难,所以我于火车的雨不能感到什么兴味,但卧在乌篷船里,静听打篷的雨声,加上欸乃的橹声以及“靠塘来,靠下去”的呼声,却是一种梦似的诗境。倘若更大胆一点,仰卧在脚划小船内...
adb shell dumpsys audio使用
前言工作中也常用到Android的shell命令adb shell dumpsys audio至于这个命令能做啥,接下来我们简单的讲解一下PS : 本文在Android 9.0上测试的,4.2时dumpsys audio不一定有这么多信息正文dumpsys audio出来的信息有很...