前言
简单记录一下,方便自己查阅。
PS: Android jni开发主要依赖Android开发平台,sdk和ndk三个部分
Android SDK : Version 31JAVA Sdk : java1.8NDK : android-ndk-r21d上面只是举个例子,具体环境需要自己搭建。
静态注册
静态注册:先由Java得到本地方法的声明,然后再通过JNI实现该声明方法。
- 优点: 理解和使用方式简单, 属于傻瓜式操作, 使用相关工具按流程操作就行, 出错率低
- 缺点: 当需要更改类名,包名或者方法时, 需要按照之前方法重新生成头文件, 灵活性不高
动态注册
动态注册:动态注册JAVA的Native方法,使得c/c++里面方法名 可以和 java 的Native方法名可以不同, 动态注册是将将二者方法名关联起来,以后在修改Native方法名时,只需修改动态注册关联的方法名称即可
- 优点: 灵活性高, 更改类名,包名或方法时, 只需对更改模块进行少量修改, 效率高
- 缺点: 对新手来说稍微有点难理解, 同时会由于搞错签名, 方法, 导致注册失败
正文
直入正题。本文介绍的是JNI静态注册。
第一步
新建一个Android 工程,这里命令为MyDeviceABI
然后新增一个DeviceABI.java
package com.biumall.mydeviceabi; publicclassDeviceABI{ static { //so库名也定义为DeviceABI System.loadLibrary("DeviceABI"); } // 定义一个接口publicstaticnative String getDeviceABI();} 第二步
使用Android Studio的Terminal
进入DeviceABI.java所在的目录,然后:
javac DeviceABI.java然后退到MyDeviceABI\src\main\java目录下,执行
javah com.biumall.mydeviceabi.DeviceABI生成
com_biumall_mydeviceabi_DeviceABI.h我这里会改名字,具体看自己
DeviceABI.h第三步
在MyDeviceABI工程根目录中创建jni目录
MyDeviceABI\jni把DeviceABI.h(这里是生成的,没有改变)放入jni。
然后在jni目录中创建DeviceABI.c文件(从DeviceABI.h复制再改动的)
DeviceABI.c,完整版如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include<jni.h>/* Header for class com_biumall_mydeviceabi_DeviceABI */#ifndef _Included_com_biumall_mydeviceabi_DeviceABI#define _Included_com_biumall_mydeviceabi_DeviceABI#ifdef __cplusplusextern"C" {#endif/* * Class: com_biumall_mydeviceabi_DeviceABI * Method: getDeviceABI * Signature: ()Ljava/lang/String; */// 此处开始有改动,其他的都是拷贝DeviceABI.hJNIEXPORT jstring JNICALL Java_com_biumall_mydeviceabi_DeviceABI_getDeviceABI(JNIEnv * env){ #if defined(__arm__)#if defined(__ARM_ARCH_7A__)#if defined(__ARM_NEON__)#if defined(__ARM_PCS_VFP)#define ABI "armeabi-v7a/NEON (hard-float)"#else#define ABI "armeabi-v7a/NEON"#endif#else#if defined(__ARM_PCS_VFP)#define ABI "armeabi-v7a (hard-float)"#else#define ABI "armeabi-v7a"#endif#endif#else#define ABI "armeabi"#endif#elif defined(__i386__)#define ABI "x86"#elif defined(__x86_64__)#define ABI "x86_64"#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */#define ABI "mips64"#elif defined(__mips__)#define ABI "mips"#elif defined(__aarch64__)#define ABI "arm64-v8a"#else#define ABI "unknown"#endifreturn (*env)->NewStringUTF(env, "Compiled with ABI " ABI "."); }// 改动结束#ifdef __cplusplus}#endif#endifPS: 如果你要复制,请记得改变函数名,这里函数涉及到包名。
第四部
这部分主要是新增Android.mk和Application.mk文件。
Android.mk
LOCAL_PATH := $(call my-dir)include$(CLEAR_VARS) LOCAL_MODULE := DeviceABILOCAL_SRC_FILES := DeviceABI.c include$(BUILD_SHARED_LIBRARY)Application.mk
APP_ABI := all具体配置就不细说,后续会总结、
第五步
进入 MyDeviceABI\jni> 然后执行 ndk-build
如果程序或者配置没问题,就编译正常。
E:\MyDeviceABI\jni>ndk-build [arm64-v8a] Compile : DeviceABI <= DeviceABI.c[arm64-v8a] SharedLibrary : libDeviceABI.so[arm64-v8a] Install : libDeviceABI.so => libs/arm64-v8a/libDeviceABI.so[x86_64] Compile : DeviceABI <= DeviceABI.c[x86_64] SharedLibrary : libDeviceABI.so[x86_64] Install : libDeviceABI.so => libs/x86_64/libDeviceABI.so[mips64] Compile : DeviceABI <= DeviceABI.c[mips64] SharedLibrary : libDeviceABI.so[mips64] Install : libDeviceABI.so => libs/mips64/libDeviceABI.so[armeabi-v7a] Compile thumb : DeviceABI <= DeviceABI.c[armeabi-v7a] SharedLibrary : libDeviceABI.so[armeabi-v7a] Install : libDeviceABI.so => libs/armeabi-v7a/libDeviceABI.so[armeabi] Compile thumb : DeviceABI <= DeviceABI.c[armeabi] SharedLibrary : libDeviceABI.so[armeabi] Install : libDeviceABI.so => libs/armeabi/libDeviceABI.so[x86] Compile : DeviceABI <= DeviceABI.c[x86] SharedLibrary : libDeviceABI.so[x86] Install : libDeviceABI.so => libs/x86/libDeviceABI.so[mips] Compile : DeviceABI <= DeviceABI.c[mips] SharedLibrary : libDeviceABI.so[mips] Install : libDeviceABI.so => libs/mips/libDeviceABI.so我的编译成功后,libs中出现对应的so库等。
├─arm64-v8a├─armeabi├─armeabi-v7a├─mips├─mips64├─x86└─x86_64因为我的存在libs,最后一步配置就是直接引用。
第六步
配置 so库,网上很多种,看自己习惯。
在工程中的build.gradle,新增如下内容:
android{compileSdkVersion31//略sourceSets{main{jniLibs.srcDirs = ['libs']}}}可能存在问题
下面是我偷懒,复制时,出现的问题
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.biumall.mylog.DeviceABI.getDeviceABI() (tried Java_com_biumall_mylog_DeviceABI_getDeviceABI and Java_com_biumall_mylog_DeviceABI_getDeviceABI__) at com.biumall.mylog.DeviceABI.getDeviceABI(Native Method) at com.biumall.mylog.MainActivity$1.onClick(MainActivity.java:21) 这里是由于包名路径不对,导致找不到,所以不建议直接复制。

