作者:譚東
軟件環境: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'
}