android 调用JNI SO动态库的方法

总结一下:

android 调用JNI 分为静态调用与动态调用(不论动态还是静态前提都是NDK环境已经配置好的前提下)

一、静态主要就是将c(.c)或者c++(cpp)的源文件直接加到项目中进行调用,

然后在CMakeLists.txt中进行配置。

二、动态调用

1、动态调用使用已经编译好的动态库.so文件

2、android调用ndk类

生成后的so文件

public class SerialPort {

p
*/
public static native int GetSOVer(String ar);

static {
System.loadLibrary("serialport");//初始化so库(注意这里添加是需要去掉lib与.so)

}
}

3、.c文件添加

/*
 * Copyright 2009-2011 Cedric Priscal
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <jni.h>
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "M1900_drv.h"
#include "SerialPort.h"
#include "include/tinyalsa/audio_i2s.h"
#include "include/tinyalsa/asoundlib.h"
#include "android/log.h"
#include "newland_linux_so.h"

static const char *TAG = "serial_port";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)

//测试  Java_(固定)_com_littt_util_SerialPort(android包名原来的.更改为_,string ar 传入的字符串参数,JNIEnv *env, jclass固定写法)
JNIEXPORT jint JNICALL
Java_com_littt_util_SerialPort_GetSOVer(JNIEnv *env, jclass clazz, jstring ar) {
	// TODO: implement GetSOVer()
	return 9;//返回一个9的值
}

4、.h头文件中声明

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class android_serialport_api_SerialPort */
#ifndef _Included_android_serialport_api_SerialPort
#define _Included_android_serialport_api_SerialPort
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL
Java_com_littt_util_SerialPort_GetSOVer(JNIEnv *env, jclass clazz,jstring v);
#ifdef __cplusplus
}
#endif
#endif

5、头文件与c文件写好了,就需要在CMake 中添加.c与.h都需要添加

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
        serialport

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        M1900_drv.c
        M1900_drv.h
        audio_i2s.c
       linux_so.cpp
        mixer.c

        include/tinyalsa/asoundlib.h
        include/tinyalsa/audio_i2s.h
        )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
        serialport

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")

6、在build.gradle同样需要配置

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 28
    buildToolsVersion "28.0.3"

    defaultConfig {
        applicationId "com.littt.interphone"
        minSdkVersion 17
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        // cmake
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
            }
        }

    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"

        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    ndkVersion '22.1.7171670'
}
dependencies {
//    implementation 'androidx.appcompat:appcompat:1.2.0'
//    implementation 'com.google.android.material:material:1.2.1'

}

7、如果静态调用可以成功,那么就可以生成动态so库文件

点击图中锤子会进行编译。完成后可以打开如下路径查看

红框中生成后 so文件

7.1、生成的.so文件(工程文件夹模式)目录为app/build/intermediates/ndk/lib,将其复制到另一个工程的app/lib目录下。

7.2、要使用上述的.so文件 ,必须将工程的包名改为生成.so文件时的包名,要不然 编译能通过,但是app不能正常运行。logcat会提示找不到所调用函数的实现。

7.3、将so文件复制到需要的路径下。
7.4、在gradle.properties中最后加一行:android.useDeprecatedNdk=true。

到此这篇关于android 调用JNI SO动态库的文章就介绍到这了,更多相关android 调用JNI SO动态库内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 从源码编译Android系统的Java类库和JNI动态库的方法

    利用源码编译Android系统Java类库 1.编写Java项目和Android.mk文件 ├── Android.mk └── src └── com └── lhw └── framework └── led └── Led.java Led.java文件 package com.lhw.framework.led; /** * LED操作库 * @author Micky Liu */ public class Led { public boolean turnOn() { return

  • Android studio 下JNI编程实例并生成so库的实现代码

    最近需要使用JNI编程,学了下JNI,并且在Android Studio下实现了一个小demo.这期间有一些坑,还好都解决了,想分享出来,希望大家少走弯路.本文中采用的平台是Windows,NDK环境已经搭建好,这方面资料很多,大家可以自行百度. 本文分为两个部分: 1.如何通过编写Jni实现native方法的调用. 2.怎样生成.so动态库提供给第三方使用. 以下是正文: 一,编写jni文件,实现本地方法 1,建立一个新工程,只有一个MainActivity,里面加载库文件并且调用若干本地方法

  • 浅谈Android Studio JNI生成so库

    1.新建Android studio工程 2.新建class:AppKey.java.主要为了保存密钥 代码块 package com...adminapp.lib.utils.jni; /** * Created by seven on 16/9/8. */ public class AppKey { static { System.loadLibrary("AppKey"); } public static native String WechatId(); public stat

  • Android Studio 3.5版本JNI生成SO文件详解

    学习在于记录,把自己不懂得容易忘记得记录下,才是最好得选择. 废话不多说,想要在Android开发中嵌入c/c++代码,直接开始如下步骤 1.创建需要调用的Java类 在你某个指定的包下创建如下类 package com.journey.org; public class JniHello{ static { System.loadLibrary("JniHello") } public static native String welcomeJniStudy(); } 2.创建通用工

  • Android Studio中导入JNI生成的.so库的实现方法

    Android Studio中导入JNI生成的.so库的实现方法 由于在原来的ADT的Eclipse环境中,用ndk_build工具生成了相应的各个.so库文件之后,eclipse工具就会自动把这些库导入到apk中.而Android Studio目前为止(0.86版本)还无法做到那么自动,但是我们可以通过以下方式进行. 首先在Android Studio工程的app目录下创建整个jni目录,jni目录里写Android.mk.Application.mk以及各类C/C++和汇编源文件.然后跟原来

  • android 调用JNI SO动态库的方法

    总结一下: android 调用JNI 分为静态调用与动态调用(不论动态还是静态前提都是NDK环境已经配置好的前提下) 一.静态主要就是将c(.c)或者c++(cpp)的源文件直接加到项目中进行调用, 然后在CMakeLists.txt中进行配置. 二.动态调用 1.动态调用使用已经编译好的动态库.so文件 2.android调用ndk类 生成后的so文件 public class SerialPort { p */ public static native int GetSOVer(Strin

  • Qt之调用C#的动态库的解决方法

    环境:VS2019+Qt5.12 1. CLR库安装 首先,如果你VS2019没有安装CLR库,那么操作步骤为: 打开 Visual Studio Installer 在已安装中点击修改 将使用C++的桌面开发的对V142(14.25)生成工具的C++/CLI支持 点击右下角的修改,安装完成后重启软件即可 2. 新建类库(.NET Framework) 注意:此处请确认选择用于创建C#类库(.dll)的项目 此时解决方案的视图为: 一个简单的测试直接在Class1.cs文件添加内容即可,此测试中

  • Android在JNI中使用ByteBuffer的方法

    本文实例讲述了Android在JNI中使用ByteBuffer的方法.分享给大家供大家参考.具体如下: 一.ByteBuffer 定义 在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时首先要将发送的数据按顺序填入缓冲区) 缓冲区是定长的,基本上它只是一个列表,它的所有元素都是基本数据类型.ByteBuffer是最常用的缓冲区,它提供了读写其他数据类型的方法,且信道的读写方法只接收ByteBuffer. ByteBuffer有以下几

  • golang 调用c语言动态库方式实现

    下面我们自己在 Linux 下做一个动态库(.so 文件 - Shared Object),然在用 Go 来使用它.本文所用的操作系统为 Ubuntu18.04, 以 gcc 作为编译器. 1.实现头文件,声明文件中函数.这里创建一个add.h文件. #ifndef __ADD_H__ #define __ADD_H__ char* Add(char* src, int n); #endif 2.实现add主体函数add.c #include <string.h> #include <s

  • Rust应用调用C语言动态库的操作方法

    目录 外部功能接口FFI UDP套接字的读超时 Rust调用C语言动态库中的函数 避免重复造轮子,使用Rust官方C语言库 外部功能接口FFI 虽然高级(脚本)编程语言的功能丰富,表达能力强,但对底层的一些特殊操作的支持并不完善,就需要以其他编程语言来实现.调用其他编程语言的接口,被称为Foreign Function Interface,直译为外部功能接口.该接口通常是调用C语言实现的外部功能模块,因为C语言接近于全能,几乎任何功能都能够实现:正如同使用汇编语言也可以实现很多功能一样,但开发效

  • Linux下g++编译与使用静态库和动态库的方法

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库(*.a)与动态库(*.so)的生成与使用方式是不同的.刚开始可能会不适应,但是用多了应该会习惯这种使用,因为步骤上并没有VS下配置那么繁琐. 下面就分别总结下linux下生成并使用静态库与动态库的方法:(由于是C++项目,所以编译器用的g++,但是与gcc的使用是相通的) 首先是准备工作,把我们需

  • C#调用非托管动态库中的函数方法

    C#如何调用一个非托管动态库中的函数呢,比如用VC6写的动态库,总之C#调用动态库的过程是比Java调用DLL动态库方便快捷多了,下面举例说明这个过程. 1.创建一个非托管动态库 代码如下: 复制代码 代码如下: //这一句是声明动态库输出一个可供外不调用的函数原型.     extern   "C"  __declspec(dllexport)  int  add( int ,  int ); int  add( int  a, int  b)      {          //实

  • linux中使用boost.python调用c++动态库的方法

    前言 最近开始使用 robot framework 测试c++的动态库,robot framework 是跑在 windows 上面,c++动态库是跑在远程linux主机上面.测试办法是让 robot framework 通过 SSHLIbrary 库执行远程机器上面的 python 脚本,python 脚本调用 C++ 动态库.所以现在要解决的是如何让python调用c++动态库. python调用c++动态库的两种办法 在上网查资料和咨询同事之后,得到两种办法:第一种将C++动态库封装成C接

随机推荐