[TOC]
故事場景
android通常使用別人的輪子是直接依賴別人的aar,但是如果別人扔給你一個so和一個.h文件,我們需要如何使用,本工程將演示直接在ndk文件中鏈接so并在工程中使用。
編譯庫文件
工程結(jié)構(gòu)

hello.h
提供 libhello.so和對應(yīng)的.h文件 hello.h 如下
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
int HelloAdd(int a,int b);
#endif
其中 HelloAdd方法實現(xiàn)了a+b的操作,接下來將調(diào)用此函數(shù)實現(xiàn)功能。
hello.cpp
#include "hello.h"
int HelloAdd(int a,int b)
{
int result=a+b;
printf("HelloAdd:result=%d \n",result);
return result;
}
CmakeLists.txt
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
INSTALL(TARGETS hello hello_static
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
INSTALL(FILES hello.h DESTINATION include/hello)
此示例是演示了動態(tài)和靜態(tài)庫兩種編譯方式
編譯
模塊下有一個腳本cmake_build_all.sh,直接在終端執(zhí)行
cmake_build_all.sh libhello.so
則可輸出以下文件:

注意:cmake_build_all.sh腳本信賴于環(huán)境變量ANDROID_SDK_PATH的配置,比如:
export ANDROID_SDK_PATH=/Users/Shared/ShareLib/Android/sdk
使用庫文件
創(chuàng)建ndk工程
配置工程為cmake編譯
在應(yīng)用的build.gradle中配置
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
當前目錄創(chuàng)建CmakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(src/main/cpp/jni)
在對應(yīng)的“src/main/cpp/jni”文件下再創(chuàng)建以下文件

其中CmakeLists.txt文件的內(nèi)容為
cmake_minimum_required(VERSION 3.4.1)
add_library(math_test SHARED math_test.cc)
創(chuàng)建有native方法的java類MathTest
package com.sen.ndk.buildexternso;
public class MathTest {
public static native int add(int a, int b);
static {
System.loadLibrary("math_test");
}
}
因此需要定義Java_com_sen_ndk_buildexternso_MathTest_add方法
定義math_test.h文件
#ifndef BUILDEXTERNSO_MATH_TEST_H
#define BUILDEXTERNSO_MATH_TEST_H
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jint JNICALL Java_com_sen_ndk_buildexternso_MathTest_add
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif //BUILDEXTERNSO_MATH_TEST_H
創(chuàng)建math_test.cc文件,目前還未使用so,直接返回相加值可測試工程運行
#include "math_test.h"
JNIEXPORT jint JNICALL Java_com_sen_ndk_buildexternso_MathTest_add
(JNIEnv * env, jobject jo, jint a, jint b){
return a+b;
}
使用hello.so文件
拷貝hello.h文件
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
extern int HelloAdd(int a,int b);
#endif
更新main.cpp
#include "hello.h"
int HelloAdd(int a,int b)
{
int result=a+b;
printf("HelloAdd:result=%d \n",result);
return result;
}
更新cmake文件
cmake_minimum_required(VERSION 3.4.1)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
add_library(hello SHARED IMPORTED)
set_target_properties(hello PROPERTIES IMPORTED_LOCATION
${PROJECT_LIBS_DIR}/${ANDROID_ABI}/libhello.so)
add_library(math_test SHARED math_test.cc)
target_include_directories(math_test PUBLIC ${hello_INCLUDE})
TARGET_LINK_LIBRARIES(math_test hello)
以上庫的連接文件是動態(tài)連接,意味著當前工程就包連接hello庫,也需要將hello庫打包在工程中,因此需要將庫文件拷貝到"src/main/jniLibs"目錄下,至此整個依賴關(guān)系可完成。