android studio如何通过 jni 调用第三方非标准 so库
目录
- 1.简述:
- 2.先编译出一个第三方非标准so库
- 1).android studio 新创建一个项目
- 2).main 新创建 jni 文件夹
- 3).新建 .cpp 文件和 .h 实现求和功能,并把文件放在jni目录下
- 4).编写 CMakeLists.txt 用来编译 cpp 文件为so库,在 app文件下新建CMakeLists.txt 文件
- 5).配置项目的build.gradle
- 6).配置 gradle.properties
- 7).编译第三方非标准库,直接运行即可。
- 3.新建项目引用第三方 so 库
- 1)新建 android studio 项目
- 2)新建 Java 类,封装想要调用的接口函数
- 3)Main 文件夹新建 jniLibs 文件夹,并拷贝第三方so到此文件夹下
- 4)创建 对应的 jni java 类文件的头文件
- 5) main 文件夹 下新建 jni文件夹,实现底层逻辑
- 7) 编写 自己 so 库的 CMakeLists.txt 文件
- 8) 配置环境 build.gradle和 gradle.properties
- 9) 编译自己的so库,直接运行即可
- 10) 主函数调用测试
调用第三方的so方法,但这个so内的方法不是标准的jni方法。这就需要我们自己写jni然后链接到第三方so库,通过jni调用so库中的方法。
1.简述:
要先有第三方的so库.so文件和编译库对应的.h头文件
- 我们自己用 c/c++ 创建一个标准的so 库,比如 mynative.so
- 然后用我们自己的mynative.so 库中去调用第三方的libnative.so库
- 我们在上层 调用我们自己的mynativeso 库 ,就实现了对第三方 libnativeso 库 方法的调用。
2.先编译出一个第三方非标准so库
1).android studio 新创建一个项目
我们先制作一个非标准 jni 库,只要功能实现两个数相加 ,并返回相加后的结果。
2).main 新创建 jni 文件夹
3).新建 .cpp 文件和 .h 实现求和功能,并把文件放在jni目录下
test.cpp
#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
4).编写 CMakeLists.txt 用来编译 cpp 文件为so库,在 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} )
5).配置项目的build.gradle
6).配置 gradle.properties
android.useDeprecatedNdk=true
7).编译第三方非标准库,直接运行即可。
3.新建项目引用第三方 so 库
1)新建 android studio 项目
2)新建 java 类,封装想要调用的接口函数
package com.example.demo05; public class JniCallNative { static { System.loadLibrary("mynativeso"); } public static native int getAddFromNative(int a,int b); }
3)Main 文件夹新建 jniLibs 文件夹,并拷贝第三方so到此文件夹下
4)创建 对应的 jni java 类文件的头文件
在Termial控制台中cd到项目目录中的源码目录下,并执行命令生成.h文件
 js; javac -encoding utf-8 -h . JniCallNative.java
执行完成后,会在 java 目录生成 对应 .h 文件
5) main 文件夹 下新建 jni文件夹,实现底层逻辑
- 将上一步 生成 .h 文件 拷贝进来,以及第三方so提供的对应.h头文件也要拷贝到jni目录中
- 根据.h 文件 编写 对应的 .cpp 文件 ,在cpp 文件里实现对 第三方 so 库 的引用
- 自己实现的逻辑中调用第三方.h内容
jninative.cpp 文件
#include <jni.h> #include <string> #include <test.h>//导入需要的.h文件,这个是必须的,如果依赖的第三方库没有.h,需要自己编写 extern "C" JNIEXPORT jint JNICALL Java_com_example_demo05_JniCallNative_getAddFromNative (JNIEnv *, jclass, jint a, jint b){ //生成add对象并调用方法 Add addObj; int result = addObj.add(a,b); return result; }
7) 编写 自己 so 库的 CMakeLists.txt 文件
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}) #生成soandroid 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 python # Links the target library to the log library # included in the NDK. ${log-lib} )
8) 配置环境 build.gradle和 gradle.properties
9) 编译自己的so库,直接运行即可
10) 主函数调用测试
<?XML version="1.0" encoding="utf-8"?> <andrhttp://www.devze.comoidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/tv01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
package com.example.demo05; import android.os.Bundle; import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.appcompatjs.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); TextView textView = findViewById(R.id.tv01); int addFromNative = JniCallNative.getAddFromNative(5, 5); textView.setText(addFromNative + ""); } }
到此这篇关于android studio通过 jni 调用第三方非标准 so库的文章就介绍到这了,更多相关android studio调用so库内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论