一、添加Native Module
选中已有的工程,在菜单选择 file->New->New Module。在弹出的界面选择:
Android Native Library

?自行客制化模块名与包名。包名是用来给APP代码import用的。模块名是生成aar的名字,也是生成模块的文件夹名字。
二、编译通过自动生成的Module
编译的时候可能会遇到不少问题,有以下几个方面要检查:
1,检查CMAKE
native模块的build.gradle 的 android {} 包含下的 externalNativeBuild {} 需要包含:path "src/main/cpp/CMakeLists.txt"。否则c++文件编译不到。这里注意区分android{}下的defaultConfig{} 也有个 externalNativeBuild {}
android {
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
?编译version要注意与?src/main/cpp/CMakeLists.txt里面的 cmake_minimum_required(VERSION 3.10.2) 对应。不能小于它,最好一致。版本要与本地下载的cmake版本一致。如果不一致,可尝试卸载不对应版本。
方法:file->settings->Appearance & Behavior->Android SDK->SDK Tools 删除或者添加

?2,筛选架构
如果不需要编译某些arch,则可以在native模块的build.gradle添加abiFilters:
buildTypes {
release {
ndk {
abiFilters "arm64-v8a", "armeabi-v7a"
}
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
ndk {
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
}
3,app导入模块依赖
?app的build.gradle里面,增加刚才添加模块的依赖。如果刚才我们新建的Module Name是blenativelib,则添加如下代码:
dependencies {
implementation project(path: ':blenativelib')
}
?
三、添加接口
1,添加JAVA接口函数
在blenativelib\src\main\java\org\nercdtv\blenativelib\BleNativeLib.java增加接口
package org.nercdtv.blenativelib;
public class BleNativeLib {
// Used to load the 'blenativelib' library on application startup.
static {
System.loadLibrary("blenativelib");
}
/**
* A native method that is implemented by the 'blenativelib' native library, which is packaged
* with this application.
*/
public native String stringFromJNI();
//add your interface, press ctrl + mouse-left to
//create function in CPP
public native String bleProcessData(byte[] raw);
}
2,在C文件添加函数实现
按住ctrl,鼠标左键点击JAVA文件中新加的函数,在CPP会自动创建对应的接口。
blenativelib\src\main\cpp\blenativelib.cpp
extern "C"
JNIEXPORT jstring JNICALL
Java_org_nercdtv_blenativelib_BleNativeLib_bleProcessData(JNIEnv * env, jobject,
jbyteArray raw) {
// your codes
}
?3,在APP中使用该接口
APP模块的JAVA函数使用方法:
import org.nercdtv.blenativelib.BleNativeLib;
public class MainActivity extends AppCompatActivity implements
View.OnClickListener {
...
static BleNativeLib lib = new BleNativeLib();
relatedFunction () {
byte[] raw = new byte[50];
String out;
out = lib.bleProcessData(raw);
}
....
}
?
四、添加预编译库
1,CMAKE添加库
添加一个静态库为例,在blenativelib\src\main\cpp\CMakeLists.txt 里面添加静态库。其中文件夹proc_data是新建的,静态库是lib_proc_data.a
${CMAKE_CURRENT_SOURCE_DIR} 即当前CMakeLists.txt所在目录。
add_library(
lib_proc_data
STATIC
IMPORTED)
set_target_properties(
lib_proc_data
PROPERTIES IMPORTED_LOCATION
${CMAKE_CURRENT_SOURCE_DIR}/proc_data/lib_proc_data.a )
include_directories( imported-lib/include/ )
?2,CPP代码使用接口
在CPP代码中#include 上面?include_directories声明过的头文件,直接使用函数即可。注意如果库是C编译的,要关注extern "C" 声明。
extern "C"{
#include <lib_proc_data.h>
}
extern "C"
JNIEXPORT jstring JNICALL
Java_org_nercdtv_blenativelib_BleNativeLib_bleProcessData(JNIEnv * env, jobject,
jbyteArray raw) {
std::string str = "1111";
unsigned char data[64];
process_data(data, 64);
return env->NewStringUTF(str.c_str());
}
3. 动态库添加与上述类似,不再描述
五、客制化编译
1,CMAKE区分arch
添加的库,会有arch差别。所以针对不同arch要用开关区分。
宏${ANDROID_ABI} 可以用来区分当前编译时候的arch。可以用来控制编译的库位置,或者编译属性。例如
if(${ANDROID_ABI} MATCHES "arm64-v8a")
target_link_libraries( blenativelib lib_proc_data ${log-lib} )
elseif(${ANDROID_ABI} MATCHES "armeabi-v7a")
target_link_libraries( blenativelib ${log-lib} )
else()
target_link_libraries( blenativelib ${log-lib} )
endif()
?2,代码中区分arch
通过宏判断。参考代码:
extern "C"
JNIEXPORT jstring JNICALL
Java_org_nercdtv_blenativelib_BleNativeLib_bleProcessData(JNIEnv * env, jobject,
jbyteArray raw) {
std::string str = "1111";
unsigned char data[64];
#if defined(__aarch64__)
//process_data(data, 64);
#elif defined (__arm__)
//process_data(data, 64);
#endif
return env->NewStringUTF(str.c_str());
}
?
六、转换为Android.mk
参考一个其他项目的Android.mk。其他关键字或者so依赖具体根据具体问题来写。
LOCAL_PATH:= $(call my-dir)
PACKAGE_MODULE_NAME := NercCmdClient
NERCCMD_NATIVE_LIBRARY_NAME := libnerccmdclientnativelib
################################## libnerccmdclientnativelib.so ################################
include $(CLEAR_VARS)
LOCAL_MODULE:= $(NERCCMD_NATIVE_LIBRARY_NAME)
LOCAL_CFLAGS += -fstack-protector-strong -fno-common -pipe -Wno-inconsistent-missing-override
LOCAL_SRC_FILES:= \
NercCmdClientNativeLib/src/main/cpp/nerccmdclientnativelib.cpp
LOCAL_MODULE_TAGS := optional
LOCAL_SHARED_LIBRARIES := \
libutils \
libcutils \
liblog \
LOCAL_C_INCLUDES := \
$(JNI_H_INCLUDE) \
$(LOCAL_PATH)/.. \
$(SDK_DIR)/source/linux/include \
$(SDK_DIR)/source/linux/api/include \
$(SDK_DIR)/source/linux/drv/include \
$(SDK_DIR)/source/linux/api/msp/include \
#LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_SHARED_LIBRARY)
#################################### NercCmdClientNativeLib.jar ###############################
include $(CLEAR_VARS)
LOCAL_MODULE := NercCmdClientNativeLib
LOCAL_MULTILIB := both
LOCAL_MODULE_TAGS := optional
LOCAL_PRIVATE_PLATFORM_APIS := true
#LOCAL_JAVA_LIBRARIES +=
#LOCAL_STATIC_JAVA_LIBRARIES :=
LOCAL_JNI_SHARED_LIBRARIES := libnerccmdclientnativelib
LOCAL_PACKAGE_NAME := NercCmdClientNativeLib
LOCAL_MANIFEST_FILE := NercCmdClientNativeLib/src/main/AndroidManifest.xml
source_dir := NercCmdClientNativeLib/src/main
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/NercCmdClientNativeLib/$(source_dir)/res
LOCAL_SRC_FILES += $(call all-java-files-under, $(source_dir))
#LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_STATIC_JAVA_LIBRARY)
############################## NercCmdClient.apk ##############################################
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_PRIVATE_PLATFORM_APIS := true
#LOCAL_JAVA_LIBRARIES +=
LOCAL_STATIC_JAVA_LIBRARIES := NercCmdClientNativeLib
#LOCAL_JNI_SHARED_LIBRARIES :=
LOCAL_PACKAGE_NAME := $(PACKAGE_MODULE_NAME)
LOCAL_CERTIFICATE := platform
#LOCAL_CERTIFICATE := testkey platform
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
source_dir := app/src/main
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/$(source_dir)/res
LOCAL_SRC_FILES += $(call all-java-files-under, $(source_dir))
LOCAL_SRC_FILES += $(source_dir)/aidl/org/nercdtv/INerccmd.aidl
LOCAL_STATIC_ANDROID_LIBRARIES := \
androidx.recyclerview_recyclerview \
androidx.preference_preference \
androidx.appcompat_appcompat \
androidx.annotation_annotation \
androidx.legacy_legacy-preference-v14 \
androidx.leanback_leanback-preference \
androidx.leanback_leanback \
androidx-constraintlayout_constraintlayout \
#LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_PACKAGE)
|