android studio 添加JNI模块与.a文件的方法与经验分享

  • Post author:
  • Post category:其他


一、添加Native Module

选中已有的工程,在菜单选择 file->New->New Module。在弹出的界面选择:


Android Native Library

自行客制化模块名与包名。还有blenativelib.cpp BleNativeLib.java等。包名是用来给APP代码import用的。模块名是生成aar的名字,也是生成模块的文件夹名字。本例是blenativelib

二、编译通过自动生成的Module

编译的时候可能会遇到不少问题,有以下几个方面要检查:

1,检查CMAKE

native模块blenativelib的build.gradle ->  android {} -> externalNativeBuild {} 需要包含:path “src/main/cpp/CMakeLists.txt”。否则c++文件gradle编译不到。这里注意区分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代码导入native模块blenativelib依赖

APP的build.gradle里面,增加刚才添加模块的依赖。如刚才我们新建的Module Name是blenativelib,则添加如下代码:

dependencies {
    implementation project(path: ':blenativelib')

}

三、添加接口

1,native模块blenativelib添加JAVA接口函数

在blenativelib\src\main\java\com\fiill\blenativelib\BleNativeLib.java增加接口

package com.fiill.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,在CPP文件添加函数实现

按住ctrl,鼠标左键点击JAVA文件中新加的函数,在CPP会自动创建对应的接口。

blenativelib\src\main\cpp\blenativelib.cpp

extern "C"
JNIEXPORT jstring JNICALL
        Java_com_fiill_blenativelib_BleNativeLib_bleProcessData(JNIEnv * env, jobject,
        jbyteArray raw) {
// your codes
}

3,在APP中使用该接口

APP模块的JAVA函数使用方法:

import com.fiill.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_com_fiill_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_com_fiill_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)



版权声明:本文为suixin______原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。