作者:谭东
软件环境:Windows+Android Studio+CMake
这里记录一下自己编写的简单C++方法,然后再编写JNI方法,最后通过CMake编译成全平台so库使用。
整个项目结构:
为了方便,我们可以用Android Studio的创建Native C++这个来创建项目,这样会自动给我们生成一个比较完善的目录结构。
首先我们需要在项目的app/libs下新建一个include目录。这个目录的作用就是用来包含我们的C/C++库,当然也可以自己编写C/C++方法逻辑。例如这里我们放置了两个库JsonCpp库的libjson目录和自己写的libencrypt源码目录。一个完整的C/C++库源码一般包含.c/.cpp和.h文件。.c/.cpp为源码逻辑实现文件,.h为抽象的方法头文件。
我们看下自己写的encrypt.cpp文件:
#include "encrypt.h"
#include <string>
std::string getEncryptString(std::string text) {
return "Encrypt:" + text + ":endl";
}
头文件encrypt.h:
#ifndef ENCRYPTLIB_ENCRYPT_H
#define ENCRYPTLIB_ENCRYPT_H
#define _GLIBCXX_USE_CXX11_ABI 0
#include <string>
std::string getEncryptString(std::string text);
#endif //ENCRYPTLIB_ENCRYPT_H
很简单,我就是想测试下so库调用我们的C++方法。
编写JNI方法,调用我们的libencrypt库的方法:
#include <jni.h>
#include <string>
#include "../../../libs/include/libencrypt/encrypt.h"
extern "C" {
using namespace std;
//这个方法为定义的调用我们的libencrypt写的C++方法
JNIEXPORT jstring JNICALL
Java_com_google_encryptlib_MainActivity_getEncryptText(JNIEnv *env,
jobject, jstring text) {
std::string license = getEncryptString(
env->GetStringUTFChars(text, 0));//env->GetStringUTFChars(text, NULL)
return env->NewStringUTF(license.c_str());
}
}
编写配置CMakeLists.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)
# 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.
set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)
message("test ndk message")
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
add_library( # Sets the name of the library.
encrypt
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
../../../libs/include/libencrypt/encrypt.cpp)
#file(GLOB SRC_LIST "*.cpp" "../../../libs/include/libjson/*.cpp")
#add_library( # Sets the name of the library.
# json
#
# # Sets the library as a shared library.
# SHARED
#
# # Provides a relative path to your source file(s).
# ${SRC_LIST})
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
add_library(json
SHARED
IMPORTED)
set_target_properties(json
PROPERTIES IMPORTED_LOCATION
../../../../src/main/jniLibs/${ANDROID_ABI}/libjson.so)
message(${ANDROID_ABI})
# 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.
native-lib
encrypt
json
# Links the target library to the log library
# included in the NDK.
${log-lib})
include_directories(libs/include)
build.gradle文件:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.google.encryptlib"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}