[TOC]
故事場(chǎng)景
android通常使用別人的輪子是直接依賴別人的aar,但是如果別人扔給你一個(gè)so和一個(gè).h文件狭魂,我們需要如何使用壹蔓,本工程將演示直接在ndk文件中鏈接so并在工程中使用味咳。
編譯庫(kù)文件
工程結(jié)構(gòu)
hello.h
提供 libhello.so和對(duì)應(yīng)的.h文件 hello.h 如下
#ifndef HELLO_H
#define HELLO_H
#include <stdio.h>
int HelloAdd(int a,int b);
#endif
其中 HelloAdd方法實(shí)現(xiàn)了a+b的操作,接下來(lái)將調(diào)用此函數(shù)實(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)
此示例是演示了動(dòng)態(tài)和靜態(tài)庫(kù)兩種編譯方式
編譯
模塊下有一個(gè)腳本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
使用庫(kù)文件
創(chuàng)建ndk工程
配置工程為cmake編譯
在應(yīng)用的build.gradle中配置
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
當(dāng)前目錄創(chuàng)建CmakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(src/main/cpp/jni)
在對(duì)應(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,直接返回相加值可測(cè)試工程運(yùn)行
#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)
以上庫(kù)的連接文件是動(dòng)態(tài)連接芒澜,意味著當(dāng)前工程就包連接hello庫(kù)仰剿,也需要將hello庫(kù)打包在工程中,因此需要將庫(kù)文件拷貝到"src/main/jniLibs"目錄下痴晦,至此整個(gè)依賴關(guān)系可完成南吮。