NDK16_Android.mk集成动态库和静态库

NDK开发汇总

一 生成一个简单库文件so、a

NDK16_Linux中使用NDK编译安卓可用的.c
NDK16_NDK编译生成so并CMAKE集成
配置环境变量

export CC=android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc
export AAA="--sysroot=/home/bao/android-ndk-r17c/platforms/android-21/arch-arm -isystem /home/bao/android-ndk-r17c/sysroot/usr/include -isystem /home/bao/android-ndk-r17c/sysroot/usr/include/arm-linux-androideabi"

生成动态库

$CC $AAA -fPIC -shared main.c -o libTest.so

生成静态库

$CC $AAA -fpic -c test.c -o libTest.o
/home/bao/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc-ar r libTest.a libTest.o

二 Android.mk集成so库问题

  1. AS新建一个项目,support C++不勾选
  2. 配置build.gradle
android {
    compileSdkVersion 29
    defaultConfig {
        applicationId "com.example.ray.demo17_mk"
        minSdkVersion 17
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

        // 指导我们的 源文件 编译
        externalNativeBuild{
            ndkBuild{

                // armeabi-v7a
                abiFilters 'armeabi-v7a'

            }
        }
        //        externalNativeBuild.ndkBuild(new Action<CoreExternalNativeCmakeOptions>() {
//            @Override
//            void execute(CoreExternalNativeCmakeOptions ndkBuildOptions) {
//                // 你希望编译你的 c/c++ 源文件 编译几种cpu(arm、x86 )
//                ndkBuildOptions.abiFilters.add("armeabi-v7a")
//                ndkBuildOptions.abiFilters.add("x86")
//            }
//        })


        // 应该打包几种cpu
        //比如: 集成了第三方库 ,第三方库中提供了 arm的 提供了 x86的
        // 可以在此处 指导 只打包 arm
        // 生成出来的apk 就只会包含 arm的
        ndk{
            abiFilters 'armeabi-v7a'
        }
    }

    //配置 native 的编译脚本路径
//    externalNativeBuild.ndkBuild(new Action<NdkBuildOptions>() {
//        @Override
//        void execute(NdkBuildOptions ndkBuildOptions) {
//            ndkBuildOptions.path = "src/main/cpp/Android.mk"
//    }
//    })

    externalNativeBuild{
        ndkBuild{
            path   "src/main/cpp/Android.mk"
        }
    }
  1. 创建并配置Android.mk+ 预编译库的引入(拷贝so并配置)
#源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。
LOCAL_PATH := $(call my-dir)
# $(info "LOCAL_PATH:======== ${LOCAL_PATH}");


# 预编译库的引入
include $(CLEAR_VARS)
LOCAL_MODULE := Test
LOCAL_SRC_FILES :=libTest.so
include $(PREBUILT_SHARED_LIBRARY)


#引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量
#不会清理 LOCAL_PATH 变量
include $(CLEAR_VARS)
#存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格
#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。
LOCAL_MODULE := native-lib
#包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开
LOCAL_SRC_FILES := native-lib.c \
c.c
#编译native-lib模块需要链接 Test模块
# Test模块是一个预编译库模块
LOCAL_SHARED_LIBRARIES :=Test
#LOCAL_LDLIBS    += -llog
#构建动态库
include $(BUILD_SHARED_LIBRARY)
  1. c中声明并调用so中的方法
#include <jni.h>

extern int test();
//#include <android/log.h>

//如果包名中有_,为避免误解,用_1表示_
void Java_com_example_ray_demo17_1mk_MainActivity_nativeTest(JNIEnv * env, jobject instance) {
  //  __android_log_print(ANDROID_LOG_ERROR,"jni","libTest.so 里面的test方法:%d",test());
    test();
}
  1. java层调用(生成的apk有两个so)
public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("Test");
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        nativeTest();
    }

    native void nativeTest();
}
  • Android 6.0 以下需要引入
  static {
        System.loadLibrary("Test");
        System.loadLibrary("native-lib");
    }
  • Android 6.0以上报错,指向了电脑本地地址,动态库用不了
    java.lang.UnsatisfiedLinkError: dlopen failed: library "D:/workspace/Demo17_MK/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/libTest.so" not found

注意:

  • 从6.0开始 使用Android.mk 如果来引入一个预编译动态库 有问题
  • 在4.4上 如果load一个动态库 ,需要先将这个动态库的依赖的其他动态库load进来
  • 在6.0以下 System.loadLibrary 不会自动为我们加载依赖的动态库
  • 6.0以上 System.loadLibrary 会自动为我们加载依赖的动态库

三 集成静态库

使用二中的项目及配置,修改相应配置

  1. Android.mk中 .so改成.a,SHARED改成STATIC
#源文件在的位置。宏函数 my-dir 返回当前目录(包含 Android.mk 文件本身的目录)的路径。
LOCAL_PATH := $(call my-dir)
# $(info "LOCAL_PATH:======== ${LOCAL_PATH}");


# 预编译库的引入
include $(CLEAR_VARS)
LOCAL_MODULE := Test
LOCAL_SRC_FILES :=libTest.a
include $(PREBUILT_STATIC_LIBRARY)


#引入其他makefile文件。CLEAR_VARS 变量指向特殊 GNU Makefile,可为您清除许多 LOCAL_XXX 变量
#不会清理 LOCAL_PATH 变量
include $(CLEAR_VARS)
#存储您要构建的模块的名称 每个模块名称必须唯一,且不含任何空格
#如果模块名称的开头已是 lib,则构建系统不会附加额外的前缀 lib;而是按原样采用模块名称,并添加 .so 扩展名。
LOCAL_MODULE := native-lib
#包含要构建到模块中的 C 和/或 C++ 源文件列表 以空格分开
LOCAL_SRC_FILES := native-lib.c \
c.c
#编译native-lib模块需要链接 Test模块
# Test模块是一个预编译库模块
LOCAL_STATIC_LIBRARIES :=Test
LOCAL_LDLIBS    += -llog
#构建动态库
include $(BUILD_SHARED_LIBRARY)
  1. 调用处进行修改
#include <jni.h>

extern int test();
#include <android/log.h>

//如果包名中有_,为避免误解,用_1表示_
void Java_com_example_ray_demo17_1mk_MainActivity_nativeTest(JNIEnv * env, jobject instance) {
   __android_log_print(ANDROID_LOG_ERROR,"jni","libTest.so 里面的test方法:%d",test());
// test();
}

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        nativeTest();
    }

    native void nativeTest();
}

  1. 运行正常,apk中只有一个so库,这也是动态库和静态库的区别
    静态库只有使用到的,才会打包进来,打包好的库文件比较小

猜你喜欢

转载自blog.csdn.net/baopengjian/article/details/107611842
今日推荐