当我们调用别人的非标准的 jni so 库,无法使用 jni 标准接口的时候。我们需要采用间接的方式调用。
(1)比如现在我们有第三方给的 libnative.so 库,无法自己直接 jni 调用
(2)我们自己用 c/c++ 创建一个标准的so 库,比如 mynative.so
(3) 然后用我们自己的mynative.so 库中去调用第三方的libnative.so库
(4) 然后 我们在上层 调用我们自己的mynativeso 库 ,就实现了对第三方 libnativeso 库 方法的调用。
这种方式 我们要先有第三方 的 so 库 和编译库 对应的头文件
我们先制作一个非标准 jni 库,只要功能实现两个 数相加 ,并返回
test.cpp
//
// Created by lum on 20-8-8.
//
#include "test.h"
Add::Add(){}
Add::~Add(){}
int Add::add(int x, int y){
return x + y;
}
test.h
#ifndef _TEST_JNI_ADD_H_
#define _TEST_JNI_ADD_H_
class Add{
public :
Add();
~Add();
int add(int x, int y);
};
#endif
在 app 文件下 新建 CMakeLists.txt 文件
#指定cmake最小版本
cmake_minimum_required(VERSION 3.4.1)
#设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
#生成so
add_library( # 设置生成库的名字
nativeso
# 生成动态库
SHARED
# 指定源码文件,这里指定test.cpp文件
src/main/jni/test.cpp )
#依赖的头文件
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni)
find_library( # log库的别名
log-lib
#log库
log )
#链接代码到指定的库
target_link_libraries( # Specifies the target library.
nativeso
# Links the target library to the log library
# included in the NDK.
${log-lib} )
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
buildToolsVersion "30.0.1"
defaultConfig {
applicationId "com.example.myjni"
minSdkVersion 26
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// 添加
externalNativeBuild {
cmake {
cppFlags ""
}
}
//添加
ndk {
abiFilters 'arm64-v8a'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
//添加
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
//添加
packagingOptions {//加上这些代码
pickFirst 'lib/armeabi-v7a/libnativeso.so'
pickFirst 'lib/armeabi-v8a/libnativeso.so'
pickFirst 'lib/arm64-v8a/libnativeso.so'
pickFirst 'lib/x86/libnativeso.so'
pickFirst 'lib/x86_64/libnativeso.so'
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
(3)配置 gradle.properties
添加
android.useDeprecatedNdk=true
点击 途中 绿色小锤子 按钮
然后就会编译出我们要的so 库
package com.example.myjninative;
public class JniCallNative {
static {
System.loadLibrary("mynativeso");
}
public static native int getAddFromNative(int a,int b);
}
(1) main 文件夹 新建 jniLibs 文件夹
(2)jniLibs 文件夹 新建so库 对应架构文件夹
(3)拷贝 第三方 so 库 到对应架构文件夹下
android studio 命令行切换到 java 目录
执行javah -jni + 类文件包名 + 类名
生成 .h 文件
javah -jni com.example.myjninative.JniCallNative
我们可以在 java 目录生成 对应 .h 文件
com_example_myjninative_JniCallNative.h 文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_myjninative_JniCallNative */
#ifndef _Included_com_example_myjninative_JniCallNative
#define _Included_com_example_myjninative_JniCallNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_myjninative_JniCallNative
* Method: getAddFromNative
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_myjninative_JniCallNative_getAddFromNative
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
(1)将上一步 生成 .h 文件 拷贝进来
(2)根据.h 文件 编写 对应的 .cpp 文件 ,在cpp 文件里实现对 第三方 so 库 的引用
(3)将第三方 so 库里用到的 头文件 拷贝进来
jninative.cpp 文件
里面实现对第三方 so 库 方法的引用
//
// Created by lum on 20-8-8.
//
#include
#include
#include //导入需要的.h文件,这个是必须的,如果依赖的第三方库没有.h,需要自己编写
extern "C"
JNIEXPORT jint JNICALL Java_com_example_myjninative_JniCallNative_getAddFromNative
(JNIEnv *, jclass, jint a, jint b){
//生成add对象并调用方法
Add addObj;
int result = addObj.add(a,b);
return result;
}
test.h
第三方 库 里的 使用的头文件
#ifndef _TEST_JNI_ADD_H_
#define _TEST_JNI_ADD_H_
class Add{
public :
Add();
~Add();
int add(int x, int y);
};
#endif
同上
app 文件下新建 CMakeLists.txt
#指定cmake最小版本
cmake_minimum_required(VERSION 3.4.1)
#设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
#生成so
add_library( # 设置生成库的名字
mynativeso
# 生成动态库
SHARED
# 指定源码文件,这里指定test.cpp文件
src/main/jni/jninative.cpp )
#依赖的头文件
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni)
#依赖的add库
add_library(nativeso SHARED IMPORTED)
set_target_properties(nativeso
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libnativeso.so)
find_library( # log库的别名
log-lib
#log库
log )
#链接代码到指定的库
target_link_libraries( # Specifies the target library.
mynativeso
#add库需要链接
nativeso
# Links the target library to the log library
# included in the NDK.
${log-lib} )
点击 绿色小锤子
看到 jniLibs 下多了自己的 so 库
主函数添加 调用 jni 上层 java 接口的函数
编译 apk 测试运行
发现自己的 java 上层 可以调用到第三方 的 so 库 里加法函数
文件参考:
Android ndk调用非jni标准so方法