android studio jni 调用 第三方 非标准 so库

文章目录

        • 1、简介
        • 2、先编译出一个第三方非标准so库
          • 1)android studio 新创建一个项目
          • 2) main 新创建 jni 文件夹
          • 3) 新建 .cpp 文件和 .h 实现 求和功能
          • 4)、编写 CMakeLists.txt 用来编译 cpp 文件到so
          • 5)配置编译环境
          • 6)、编译第三方 非标准 库
        • 3、新项目 引用第三方 so 库
          • 1)新建 android studio 项目
          • 2)新建 java 类,封装想要调用的接口函数
          • 3)Main 文件夹新建 jniLibs 文件夹
          • 4)创建 对应的 jni java 类 文件的 头文件
          • 5) main 文件夹 下新建 jni文件夹,实现底层逻辑
          • 6) 配置环境
          • 7) 编写 自己 so 库的 CMakeLists.txt 文件
          • 8 ) 编译自己的标so 库
          • 9) 主函数调用测试

1、简介

当我们调用别人的非标准的 jni so 库,无法使用 jni 标准接口的时候。我们需要采用间接的方式调用。
(1)比如现在我们有第三方给的 libnative.so 库,无法自己直接 jni 调用
(2)我们自己用 c/c++ 创建一个标准的so 库,比如 mynative.so
(3) 然后用我们自己的mynative.so 库中去调用第三方的libnative.so库
(4) 然后 我们在上层 调用我们自己的mynativeso 库 ,就实现了对第三方 libnativeso 库 方法的调用。

这种方式 我们要先有第三方 的 so 库 和编译库 对应的头文件

2、先编译出一个第三方非标准so库

1)android studio 新创建一个项目

我们先制作一个非标准 jni 库,只要功能实现两个 数相加 ,并返回

2) main 新创建 jni 文件夹

android studio jni 调用 第三方 非标准 so库_第1张图片

3) 新建 .cpp 文件和 .h 实现 求和功能

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

android studio jni 调用 第三方 非标准 so库_第2张图片

4)、编写 CMakeLists.txt 用来编译 cpp 文件到so

在 app 文件下 新建 CMakeLists.txt 文件

android studio jni 调用 第三方 非标准 so库_第3张图片

#指定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)配置编译环境

(1)配置 sdk tool 里 CMake NDK
android studio jni 调用 第三方 非标准 so库_第4张图片

(2)配置 build.gradle(:app)android studio jni 调用 第三方 非标准 so库_第5张图片

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

android studio jni 调用 第三方 非标准 so库_第6张图片
(4)配置好 ndk 路径
android studio jni 调用 第三方 非标准 so库_第7张图片

6)、编译第三方 非标准 库

点击 途中 绿色小锤子 按钮
android studio jni 调用 第三方 非标准 so库_第8张图片
然后就会编译出我们要的so 库

android studio jni 调用 第三方 非标准 so库_第9张图片

3、新项目 引用第三方 so 库

1)新建 android studio 项目
2)新建 java 类,封装想要调用的接口函数

android studio jni 调用 第三方 非标准 so库_第10张图片

package com.example.myjninative;

public class JniCallNative {
    static {
        System.loadLibrary("mynativeso");
    }
    public static native  int  getAddFromNative(int a,int b);
}

3)Main 文件夹新建 jniLibs 文件夹

(1) main 文件夹 新建 jniLibs 文件夹
(2)jniLibs 文件夹 新建so库 对应架构文件夹
(3)拷贝 第三方 so 库 到对应架构文件夹下
android studio jni 调用 第三方 非标准 so库_第11张图片

4)创建 对应的 jni java 类 文件的 头文件

android studio 命令行切换到 java 目录
执行javah -jni + 类文件包名 + 类名
生成 .h 文件

javah -jni com.example.myjninative.JniCallNative

在这里插入图片描述
android studio jni 调用 第三方 非标准 so库_第12张图片
我们可以在 java 目录生成 对应 .h 文件
android studio jni 调用 第三方 非标准 so库_第13张图片
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

5) main 文件夹 下新建 jni文件夹,实现底层逻辑

(1)将上一步 生成 .h 文件 拷贝进来
(2)根据.h 文件 编写 对应的 .cpp 文件 ,在cpp 文件里实现对 第三方 so 库 的引用
(3)将第三方 so 库里用到的 头文件 拷贝进来
android studio jni 调用 第三方 非标准 so库_第14张图片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
6) 配置环境

同上

build.gradle(app )多添加 一段
android studio jni 调用 第三方 非标准 so库_第15张图片

7) 编写 自己 so 库的 CMakeLists.txt 文件

app 文件下新建 CMakeLists.txt

android studio jni 调用 第三方 非标准 so库_第16张图片

#指定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} )

8 ) 编译自己的标so 库

点击 绿色小锤子
android studio jni 调用 第三方 非标准 so库_第17张图片看到 jniLibs 下多了自己的 so 库
android studio jni 调用 第三方 非标准 so库_第18张图片

9) 主函数调用测试

主函数添加 调用 jni 上层 java 接口的函数
android studio jni 调用 第三方 非标准 so库_第19张图片
编译 apk 测试运行

android studio jni 调用 第三方 非标准 so库_第20张图片
发现自己的 java 上层 可以调用到第三方 的 so 库 里加法函数

文件参考:
Android ndk调用非jni标准so方法

你可能感兴趣的:(Android,进阶)