前言:
在Ubutu上编译出来的.so文件,怎么添加到Android项目中去使用呢?目前:可以通过
Makefile方式和CMake方式引入预编译静动态库(静态库.a 动态库.so)到项目中去使用。就目前而言CMake是Goole推荐使用方式,但是加入接手一个老的NDK项目是MakeFile方式,看不懂就GePi了,所以这里我们还是介绍一下MakeFile方式将静动态库加入到AS中,完成NDK项目的开发。废话不多说,直接撸步骤了:
一、创建一个普通工程
1、在src/main目录下创建一个ndkBuild文件夹
2、在此文件中创建一个Android.mk文件
用于配置相关信息
3、在此文件中创建一个test.c的源文件
备注:创建文件是注意选择源文件类型为.c的文件(本人在这里比较傻逼,选择的c++,但是后缀名改成.c,编译的时候老是失败)
4、将编译好的的.so库复制到src/main目录下
如图所示目录结构:
image.png
二、配置相关Makefile信息
1、编辑Android.mk文件
LOCAL_PATH := $(call my-dir)
#预编译库的引入 (提前编译好的库)
include $(CLEAR_VARS)
LOCAL_MODULE := Main
LOCAL_SRC_FILES := libMainTest.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := test.c
# 编译hello-jni模块 需要链接 Test 模块
# Test模块是一个预编译库模块
LOCAL_STATIC_LIBRARIES := Main
include $(BUILD_SHARED_LIBRARY)
2、编辑grade(app)文件
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.cd.empsun.makefile"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//设置好
externalNativeBuild{
ndkBuild{
abiFilters 'armeabi-v7a'
}
}
}
//引入Android.mk的路径
externalNativeBuild{
ndkBuild{
path 'src/main/ndkBuild/Android.mk'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
3、编辑test.c文件
#include <jni.h>
//引入预编译动态库的方法进行调用
extern int main(int a);
JNIEXPORT int JNICALL
Java_com_cd_empsun_makefile_MainActivity_nativeTest(JNIEnv *env, jobject instance) {
return main(23);
}
4、使用编译好的.so库里面的函数
public class MainActivity extends AppCompatActivity {
//加载动态库
static {
System.loadLibrary("MainTest");
System.loadLibrary("test");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("TAG",nativeTest()+"");
}
native int nativeTest();
}
本结果运行在Android 5.1 系统上
01-15 01:23:17.506 6650-6650/com.cd.empsun.makefile E/TAG: 26
再次运行在Android 8.0系统上
Process: com.cd.empsun.makefile, PID: 28444
java.lang.UnsatisfiedLinkError: dlopen failed: library "D:/Demo/Demo_mk/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libMainTest.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
at java.lang.System.loadLibrary(System.java:1660)
at com.cd.empsun.makefile.MainActivity.<clinit>(MainActivity.java:10)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1178)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3082)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
报错提示:没有找到libMainTest.so库文件
通过ndk-denpends.exe工具查看test.so依赖情况发现
1、在AS上打开Terminal工具进入NDK所在盘(本人NDK安装目录是在C盘)
输入:c:
输入:cd C:\Users\chen\AppData\Local\Android\Sdk\ndk-bundle
提前将build好的apk包解压出来,将编译好的libtest.so库复制进ndk-depends.cmd所在的目录下
输入:ndk-depends.cmd libtest.so
Terminal输出的信息
C:\Users\chen\AppData\Local\Android\Sdk\ndk-bundle>ndk-depends.cmd libtest.so
WARNING: Could not find library: D:/Demo/Demo_mk/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libMainTest.so
libtest.so
libstdc++.so
libm.so
libdl.so
libc.so
D:/Demo/Demo_mk/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libMainTest.so
C:\Users\chen\AppData\Local\Android\Sdk\ndk-bundle>
看以清楚知道,其实我们的APK包里面就没有libMainTest.so库,所以APP在8.0上会出现奔溃的现象。so...
从6.0开始 使用Android.mk 如果来引入一个预编译动态库 存在问题
在4.4上 如果load一个动态库 ,需要先将这个动态库的依赖的其他动态库load进来
在6.0以下 System.loadLibrary 不会自动为我们加载依赖的动态库
在6.0以上 System.loadLibrary 会自动为我们加载依赖的动态库
这个问题不好兼容,怎么办呢?
1、使用静态库
2、使用CMake
三、配置CMake
1、在src/main目录下创建一个cmake文件夹
include:里面包含需要一些头文件
cmakeTest.c:需要编译的源文件
2、在app目录下创建一个文件:CmakeLists.txt
# 指定cmake最小支持版本的方法
cmake_minimum_required(VERSION 3.6)
# -I 引入相关头文件
include_directories(src/main/cmake/include)
#引入 XX 目录的cmakelist #add_subdirectory(XX)
file(GLOB source src/main/cmake/*.c src/main/cmake/*.cpp src/main/cmake/a/*.cpp )
# cmakeTest: 变量名 最终会生成的so名字
# SHARED: 动态库 STATIC:静态库
add_library(cmakeTest SHARED ${source})
# 有问题!!!
#add_library(Test2 SHARED IMPORTED)
#set_target_properties(Test2 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libTest.so)
#和makefile不同,cmake 有其他办法引入动态库 让他没问题
# c++: CMAKE_CXX_FLAGS
# set 方法 定义一个变量
#CMAKE_C_FLAGS = "${CMAKE_C_FLAGS} XXXX"
# -L: 库的查找路径 libTest.so
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}")
# 链接 (不能换位置)
# 要生成的目标 so
# 编译hello-jni模块 需要链接(依赖) Test 模块
target_link_libraries(cmakeTest MainTest log)
3、编辑grade(app)
defaultConfig {
applicationId "com.cd.empsun.makefile"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild{
// ndkBuild{
// abiFilters 'armeabi-v7a'
// }
cmake{
abiFilters 'armeabi-v7a'
}
}
}
externalNativeBuild{
// ndkBuild{
// path 'src/main/ndkBuild/Android.mk'
// }
cmake{
path 'CMakeLists.txt'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
4、编辑cmakeTest.c文件
#include <jni.h>
extern int main();
JNIEXPORT jint JNICALL
Java_com_cd_empsun_makefile_MainActivity_nativeTest(JNIEnv *env, jobject instance) {
return main(200);
}
4、引用编译好的libcmakeTest.so
public class MainActivity extends AppCompatActivity {
static {
//System.loadLibrary("MainTest");
System.loadLibrary("cmakeTest");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("TAG",nativeTest()+"");
}
native int nativeTest();
}
Android 8.0.0系统:
11-14 14:25:10.587 8103-8103/com.cd.empsun.makefile E/TAG: 202
Android 5.1.1系统:
01-15 05:45:27.817 14814-14814/com.cd.empsun.makefile E/TAG: 202












网友评论