調用so文件有兩種方式,一種是標準的jni文件,另外一種不是jni標準。jni標準可以直接用jni標準來調用,非jni標準的需要外面包裹一層jni標準才能調用。下面就演示怎麼用。
NKD可以用ndk-build來編譯,也可以用cmake來編譯。這裏用的是cmake。
CMakeList.txt內容。
# 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)
# 這裏設置外部代碼根目錄
set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../distribution)
#調用第三方so文件
add_library(slzr-lib SHARED IMPORTED)
set_target_properties(slzr-lib PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/slzr/lib/${ANDROID_ABI}/libslzr.so)
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#主so文件配置
add_library(native-lib
SHARED
#這裏設置需要引入的c文件
# ${distribution_DIR}/slzr/src/libposapplication.cpp
native-lib.cpp)
#這裏設置生成so文件的輸出目錄,可以不設置
set_target_properties(native-lib
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
"${distribution_DIR}/native-lib/lib/${ANDROID_ABI}")
#這裏設置外部源碼位置
target_include_directories(native-lib PRIVATE
# ${distribution_DIR}/slzr/src
${distribution_DIR}/slzr/include)
find_library(log-lib
log)
target_link_libraries(native-lib
slzr-lib #第三方so文件
${log-lib})
CMakeList裏面設置了第三方的so庫地址。
值得注意的是set_target_properties設置需要放到對應的add_library的下面。target_link_libraries需要加入第三方so文件的名稱。
我這裏直接生成一個測試的非標準的jni文件給項目來調用。
這裏是封裝的c++調用。
#include <jni.h>
#include <string>
#include <stdio.h>
#include <iostream>
#include "stdint.h"
#include <libposapplication_global.h>
#include <libposapplication.h>
#include<android/log.h>
#define LOG_TAG "System.out.c"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
/**
* 封裝c/c++與java的接口
*/
int soso(char *data) {
printf("*********test*********");
std::cout << "Hello World!" << std::endl;
LOGI("這是來自tsoso");
return 1;
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndktest2_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
LOGD("調用了testapp");
testapp();
LOGI("這是來自so裏面的info信息");
IC_test cal;
cal.call_test = soso;
int i = call_back(&cal);
LOGI("這是來自so裏面的info123");
return env->NewStringUTF(hello.c_str());
}
代碼比簡單,testapp();
是so文件裏面的函數。call_back
是so文件裏面回調函數。這裏設置int soso(char *data)
爲回調函數加進去。
下面看下非JNI標準的c代碼。
#include "libposapplication.h"
#include<stdio.h>
#include<iostream>
#include"stdint.h"
LibPosApplication::LibPosApplication()
{
printf("測試lib");
}
LIBPOSAPPLICATIONSHARED_EXPORT void testapp()
{
printf("*********test*********");
std::cout<<"Hello World!"<<std::endl;
LOGI("這是來自testapp");
}
extern "C"{
LIBPOSAPPLICATIONSHARED_EXPORT int call_back(IC_test *body)
{
int ret;
printf("%s\n",__FUNCTION__);
std::cout<<"Hello call_back!"<<std::endl;
ret=(body->call_test)("你好啊");
return 1;
}
}
//回調函數實現
build.gradle裏面設置的並不多,主要是設置一下externalNativeBuild 這個參數值。
android {
defaultConfig {
externalNativeBuild {
cmake {
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
附件:
demo源碼地址