Android Studio中当用到jni层编码时,结合ndk-build,编译.so库是需要.mk文件,常用的语句网上都比较多,本文解决静态库加载编译的问题。
首先注明一点,代码编译依赖库一般分为静态库(如.a、.lib)和动态库(如.so、.dll),其中window系统上编译出的一般为.lib和.dll,linux系统一般为.a和.so。
安卓app中调用,一般是支持linux系统下的库,即.a和.so。
jni中动态库的加载,一般在代码中用dlopen函数加载即可,需要添加
#include <dlfcn.h>
#define lib_name "libkernel.so"
void * Lib_Handle = NULL;
Lib_Handle = dlopen ( lib_name, RTLD_LAZY );
其中RTLD_LAZY一种解方式,可参看dlopen的百度百科。
本文重点:加载静态库.a时,怎么办?
解决方法是先把需要加载的.a文件拷贝到需要编译的jni文件夹下,然后在Android.mk文件中进行配置,下文以加载linux下编译好的libsample_one.a和libsample_two.a文件为例,则在Android.mk文件中添加
include $(CLEAR_VARS)
LOCAL_MODULE := sample_one
LOCAL_SRC_FILES := libsample_one.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sample_two
LOCAL_SRC_FILES := libsample_two.a
include $(PREBUILT_STATIC_LIBRARY)
LOCAL_STATIC_LIBRARIES := sample_one sample_two
多个文件以空格分开。(换行以"\"分开)
(最近调试发现一个问题,结合我之前写的jni编译.so和输出相应java层的.jar包,Android Studio中通过配置build.gradle的方式,编译通过,但是linker报错,网上查看,不知道具体原因,可能是这种.mk文件不适合在AS中实现,望网友指点一二。最后,我通过在cmd中ndk-build的方式编译出了.so文件(在AS的Terminal窗口输入ndk-build也可实现),然后在Eclipse中单独到处java层对应的jar包,Eclipse中导出jar包的方式较AS中通过配置build.gradle实现的方式简单很多,需要学习的网友可以百度)。
完整的Android.mk如下:
# Copyright (C) 2017 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)
# load the static library
include $(CLEAR_VARS)
LOCAL_MODULE := sample_one
LOCAL_SRC_FILES := libsample_one.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := sample_two
LOCAL_SRC_FILES := libsample_two.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := MyTestJni
LOCAL_SRC_FILES := MyTestJni.c \
MyMath.c \
test.c
LOCAL_STATIC_LIBRARIES := sample_one sample_two
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
其中LOCAL_LDLIBS := -llog为jni层向java层调用Log日志输出。
可以中相应的.c文件中添加说明,如在MyTestJni.c中添加
#include "android/log.h"
static const char *TAG="JNI_TEST";
#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
调用时用LOGE("test one"); 或者 char* testStr="hello"; LOGD("jni print: %s",testStr);