android 动态加载多个so(包含so引用so)

0、目标so为a 被引用so为b a引用b

1、被引用的so b

  • 需要有头文件,包含extern “C” 定义函数

2、生成待使用的目标so a

  • cmakelist.txt 中要指定 .h头文件位置 参考:
include_directories( libs/jni/include/ )
  • cmakelist.txt 中要指定被引用的so 位置 (注意路径:使用相对路径可能报错 jinjar err missing and no known rule to make it) 参考:
add_library( # Sets the name of the library.
             extest-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             IMPORTED )

set_target_properties( # Specifies the target library.
                       extest-lib

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       D:/work/test/extest1/app/libs/jni/${ANDROID_ABI}/libextest-lib.so
                       )
  • 配置目标依赖 参考:

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       extest-lib
                       ${log-lib} )

3、app中使用 so

  • 动态加载so ,可以so放在sdcard 任意目录,然后复制到app安装目录下,再使用system.load()执行加载。(注意加载顺序:先加载被引用的so b,再加载目标so a,否则会报错:b not found
//防止重复加载
private List<String> loadSoList = new ArrayList<>();

 public void loadSo(String name) {
        Log.e("TAG","loadSo:"+name);
        File file = new File("/sdcard/" + name + ".so");
        String path = getDir("libs", MODE_PRIVATE).getAbsolutePath() + "/" + name + ".so";
        Log.e("TAG", "getdirPath: " + getDir("libs", MODE_PRIVATE).getAbsolutePath() + "to path:" + path);
        File to = new File(path);
        if (!to.exists()) {
            if (file.exists()) {
                Log.e("TAG", "so exit");
                copy(file, to);
            }
        }

        if (!loadSoList.contains(name)) {
            System.load(path);
            loadSoList.add(name);
        }
    }

public static void copy(File from, File to) {
        try {
            FileInputStream fileInputStream = new FileInputStream(from);
            FileOutputStream fileOutputStream = new FileOutputStream(to);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }

            fileInputStream.close();
            fileOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

4、注意事项

  • ndk中配置的目录,对应的依赖so也需要提供相应的版本
ndk {
            abiFilters  'arm64-v8a'
        }
    原文作者:tpkeeper
    原文地址: https://www.jianshu.com/p/00e7d382725b
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞