精华内容
下载资源
问答
  • Android 加载so库
    2019-03-13 14:43:07

    加载libs目录下的so库,代码如下

    sourceSets.main.jniLibs.srcDirs = ['libs']

     

    更多相关内容
  • Android加载so库

    2021-01-19 21:03:48
    1. 说明    早期的Android系统几乎只支持ARMv5的CPU架构,你知道现在它支持多少种...应用程序二进制接口(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指

    1. 说明

       早期的Android系统几乎只支持ARMv5的CPU架构,你知道现在它支持多少种吗?7种
    Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。
    应用程序二进制接口(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。在Android 系统上,每一个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64。

    各版本分析如下:
    • mips / mips64: 极少用于手机可以忽略
    • x86 / x86_64: x86 架构的手机都会包含由 Intel 提供的称为 Houdini 的指令集动态转码工具,实现 对 arm .so 的兼容,再考虑 x86 1% 以下的市场占有率,x86 相关的两个 .so 也是可以忽略的
    • armeabi: ARM v5 这是相当老旧的一个版本,缺少对浮点数计算的硬件支持,在需要大量计算时有性能瓶颈
    • armeabi-v7a: ARM v7 目前主流版本
    • arm64-v8a: 64位支持

    2. Android设备如何加载.so文件

       当一个应用安装在设备上,只有该设备支持的CPU架构对应的.so文件会被安装。不同CPU架构的Android手机加载时会在libs下找自己对应的目录,从对应的目录下寻找需要的.so文件;如果没有对应的目录,就会去armeabi下去寻找,如果已经有对应的目录,但是如果没有找到对应的.so文件,也不会去armeabi下去寻找了。
       以x86设备为例,x86设备会在项目中的 libs文件夹寻找是否含有x86文件夹,如果含有x86文件夹,则默认为该项目有x86对应的so可运行文件,只有x86文件夹而文件夹下没有so,程序运行也是会出现findlibrary returned null的错误的;如果工程本身不含有x86文件夹,则会寻找armeabi或者armeabi-v7a文件夹,兼容运行。以armeabi-v7a设备为例,该Android设备当然优先寻找libs目录下的armeabi-v7a文件夹,同样,如果只有armeabi-v7a文件夹而没有 so也是会报错的;如果找不到armeabi-v7a文件夹,则寻找armeabi文件夹,兼容运行该文件夹下的so,但是不能兼容运行x86的so。所以项目中如果只含有x86的so,在armeabi和armeabi-v7a也是无法运行的。以上就是不同CPU架构运行时加载so的策略。

    3. 适配不同的平台

       目前主流的Android设备是armeabi-v7a架构的,然后就是x86和armeabi了。如果同时包含了 armeabi,armeabi-v7a和x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的so,这是较为完美的一种解决方案,但是同时也会导致包变大。
       armeabi-v7a是可以兼容armeabi的,而v7a的CPU支持硬件浮点运算,目前绝大对数设备已经是armeabi-v7a了,所以为了性能上的更优,就不要为了兼容放到armeabi下了。x86也是可以兼容armeabi平台运行的,另外需要指出的是,打出包的x86的so,总会比armeabi平台的体积更小,对于性能有洁癖的童鞋们,还是建议在打包so的时候支持x86。

    4. 第三方平台的.so库怎么处理

       第三方的类库只提供了armeabi下的.so文件,我们项目里适配了armeabi-v7a和x86,如果不在对应的文件下放对应的.so文件,就可能导致某些Android设备会出一些问题,我们可以复制armeabi下得.so文件到不同的文件夹下。如果第三方提供了不同平台的.so文件,则复制不同平台的.so文件到项目中对应的文件夹下即可。
       关于.so文件之前有一个坑,svn会把提交的so文件过滤掉,在接第三方SDK的时候通过SVN更新了文档,但是没有注意到少了几个so文件,浪费了大把的时间去找原因。记得去掉svn对so的忽略!!!

    5. 总结

    • 在项目libs目录下创建armeabi,armeabi-v7a,x86,mips,arm64- v8a,mips64,x86_64目录,并放入对应版本的so库,程序运行会根据本身CPU版本查找对应版本的so库使用;
    • 在build.gradle文件的android{} 里加入如下配置
      sourceSets{
          main{
              jniLibs.srcDirs = ['libs']
          }
      }
    • 如果是为了兼容只创建并将so库放入了armeabi文件下就需要在build.gradle文件的defaultConfig{} 里加入如下配置,强行指定程序去armeabi目录下查询so库
      ndk {
          abiFilters "armeabi"
      }
    • 注意:如果以上情况的场景是SDK要使用so库,然后程序要集成SDK,则需要在SDK程序中加入sourceSets{ main{ jniLibs.srcDirs = ['libs'] } }配置,在要引入SDK的程序中加入ndk { abiFilters "armeabi" }配置。
    展开全文
  • 之前写过将jar包和so库封装到jar包中的文章,但是没有考虑别人调用时需要加载so库的问题。因为so库放入jar之后,so就不是一个独立的.so文件了,用System.load()加载就会提示找不到这个库,所以要想加载这个so 就需要...
  • android项目中如何加载已有so库 一起学习android 开发
  • Android加载外部so库

    2021-05-26 11:51:14
    正文需求:需要加载其他厂商编译好的so库,需要从外部加载。方法一:直接将so库拷贝到app私有目录下,然后使用以下代码加载。String soPath = Environment.getExternalStorageDirectory().toString() + "/libnative-...

    前言

    本篇作为记录,方便以后查阅。

    正文

    需求:需要加载其他厂商编译好的so库,需要从外部加载。

    方法一:

    直接将so库拷贝到app私有目录下,然后使用以下代码加载。

    String soPath = Environment.getExternalStorageDirectory().toString() + "/libnative-lib.so";

    File file = new File(soPath);

    if (file.exists()){

    File dir = context.getDir("libs", Context.MODE_PRIVATE);

    String targetDir = dir.getAbsolutePath() + "/libnative-lib.so";

    FileUtils.copySdcardFile(file.toString(), targetDir);

    System.load(targetDir);

    }

    缺点:麻烦,不建议使用

    方法二:

    创建android native项目后,在Project视图下,app/src/main下创建jniLibs。如果对应的so只有32位arm的。需要在build.gradle文件下加入以下内容。

    ndk{

    abiFilters "armeabi-v7a"

    }

    1fe1d10d99db

    image.png

    方法三:

    使用自定义配置,在Project的视图下,app目录下创建libs目录,然后将其他apk中的lib下的so库连目录一起拷贝过去,然后在build.gradle中加入以下代码

    sourceSets {

    main {

    jniLibs.srcDirs = ['libs']

    }

    }

    展开全文
  • 安卓JVM加载so库流程 好久没有写点东西发了,工作中的事情有点杂,也找不到整块东西可以写的。 最近调查了一个问题,稍微追了一下流程,这里记录一下。 1. 问题背景 由于我们支持的设备相对比竞品,zygote进程多占用...

    安卓JVM加载so库流程

    好久没有写点东西发了,工作中的事情有点杂,也找不到整块东西可以写的。

    最近调查了一个问题,稍微追了一下流程,这里记录一下。

    1. 问题背景

    由于我们支持的设备相对比竞品,zygote进程多占用了好几倍的内存空间。通过dump meminfo后发现,我们的设备在so库,ttf,和unkonwn mmap的内存空间相比竞品一共大了20多M,其中so库多了15M左右。

    通过查看zygote进程的smaps,确定了占用空间最大的几个so库确实是我们自己的。虽然确定了内存占用大的原因,还是得把这些so库是加载在zygote进程中的时机确定了才行。

    我的第一反应就是在zygote启动时,加载sharedLibrary()时,把这些库加载了,于是去看了这部分源码,并没有。

    通过反复调试以及追踪源码,最后发现是在JVM启动的过程中加载了这些so库,这些so库的配置在“system/etc/public.libraries.txt”下。

    在这里插入图片描述

    这个文件里配置的都是public的so库,能够被普通app访问的。类似的配置文件还有“vendor/etc/”下面的,还有一些其他的配置地方,我没有深入去看,想要看的盆友可以自己去看源码或者注释。

    下面我就带大家一起看看虚拟机加载这些so库的流程。

    2. JVM加载so库流程

    调用栈:

    frameworks/base/cmds/app_process/app_main.cpp

    ​ ---->runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote);

    frameworks/base/core/jni/AndroidRuntime.cpp

    ​ ---->AndroidRuntime::startVm

    ​ —>JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs)

    art/runtime/jni/java_vm_ext.cc

    ​ —>android::InitializeNativeLoader();

    system/core/libnativeloader/native_loader.cpp

    ​ ---->Initialize()

    ​ ---->ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg)

    其中,public_native_libraries_system_config 为 system/etc/public.libraries.txt

    这部分流程是在安卓设备开机过程中的,在执行ZygoteInit.main()之前会先启动java虚拟机的,这样fork其他java进程的时候,java环境就已经有了,不用再创建虚拟机了。

    最后贴一下Initialize()函数:

    void Initialize() {
    //一旦public命名空间被初始化,运行这个代码就没有意义了——它对当前的public库列表没有任何影响。
        if (initialized_) {
          return;
        }
    
        std::vector<std::string> sonames;
        const char* android_root_env = getenv("ANDROID_ROOT");
        std::string root_dir = android_root_env != nullptr ? android_root_env : "/system";
        std::string public_native_libraries_system_config =
                root_dir + kPublicNativeLibrariesSystemConfigPathFromRoot;
        std::string llndk_native_libraries_system_config =
                root_dir + kLlndkNativeLibrariesSystemConfigPathFromRoot;
        std::string vndksp_native_libraries_system_config =
                root_dir + kVndkspNativeLibrariesSystemConfigPathFromRoot;
    
        std::string product_public_native_libraries_dir = "/product/etc";
    
        std::string error_msg;
        LOG_ALWAYS_FATAL_IF(
            !ReadConfig(public_native_libraries_system_config, &sonames, always_true, &error_msg),
            "Error reading public native library list from \"%s\": %s",
            public_native_libraries_system_config.c_str(), error_msg.c_str());
    
    //对于可调试的平台构建,使用ANDROID_ADDITIONAL_PUBLIC_LIBRARIES环境变量将库添加到列表中。这仅用于平台测试。
        if (is_debuggable()) {
          const char* additional_libs = getenv("ANDROID_ADDITIONAL_PUBLIC_LIBRARIES");
          if (additional_libs != nullptr && additional_libs[0] != '\0') {
            std::vector<std::string> additional_libs_vector = base::Split(additional_libs, ":");
            std::copy(additional_libs_vector.begin(), additional_libs_vector.end(),
                      std::back_inserter(sonames));
          }
        }
    
    //删除运行时命名空间中的公共库。这些库列在public.android.txt中,但我们不希望android的其余部分在默认命名空间中打开这些库。
          //例如,libicuuc。因此从运行时名称空间公开给类装入器名称空间。
          //不幸的是,它没有稳定的C符号,并且默认的命名空间应该只在libandroidicus .so中使用稳定的符号。http://b/120786417
        removePublicLibsIfExistsInRuntimeApex(sonames);
    
        // android_init_namespaces()期望加载所有的公共库,以便仅通过soname找到它们。
        // TODO(迪米特里·):这有点误导,因为我们不知道供应商公共库是否将从 /vendor/lib打开,我们可能最终会从/system/lib或/product/lib加载它们
          
        for (const auto& soname : sonames) {
          LOG_ALWAYS_FATAL_IF(dlopen(soname.c_str(), RTLD_NOW | RTLD_NODELETE) == nullptr,
                              "Error preloading public library %s: %s", soname.c_str(), dlerror());
        }
    
        system_public_libraries_ = base::Join(sonames, ':');
    
        // read /system/etc/public.libraries-<companyname>.txt which contain partner defined
        // system libs that are exposed to apps. The libs in the txt files must be
        // named as lib<name>.<companyname>.so.
        sonames.clear();
        ReadExtensionLibraries(base::Dirname(public_native_libraries_system_config).c_str(), &sonames);
        oem_public_libraries_ = base::Join(sonames, ':');
    
        // read /product/etc/public.libraries-<companyname>.txt which contain partner defined
        // product libs that are exposed to apps.
        sonames.clear();
        ReadExtensionLibraries(product_public_native_libraries_dir.c_str(), &sonames);
        product_public_libraries_ = base::Join(sonames, ':');
    
        // Insert VNDK version to llndk and vndksp config file names.
        insert_vndk_version_str(&llndk_native_libraries_system_config);
        insert_vndk_version_str(&vndksp_native_libraries_system_config);
    
        sonames.clear();
        ReadConfig(llndk_native_libraries_system_config, &sonames, always_true);
        system_llndk_libraries_ = base::Join(sonames, ':');
    
        sonames.clear();
        ReadConfig(vndksp_native_libraries_system_config, &sonames, always_true);
        system_vndksp_libraries_ = base::Join(sonames, ':');
    
        sonames.clear();
        // This file is optional, quietly ignore if the file does not exist.
        ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames, always_true, nullptr);
    
        vendor_public_libraries_ = base::Join(sonames, ':');
      }
    
    展开全文
  • Android开发教程之动态加载so库文件的方法,我想对于静态加载 so 库文件,大家都已经很熟悉了,这里就不多说了。在 Android 开发中调用动态库文件(*.so)都是通过 jni 的方式,而静态加载往往是在 apk 或 jar 包中...
  • Android 开发中如何动态加载 so 库文件(转载) 动态加载的优点 静态加载,不灵活,apk 包有可能大。所以采用动态加载 so 库文件,有以下几点好处: 灵活,so 文件可以动态加载,不是绑定死的,修改方便,so 库有...
  • Android so库动态加载总结

    千次阅读 2020-12-31 22:09:09
    //加载so库 if (b && new File(soPath).exists()) { final String soName = soPath.substring(soPath.lastIndexOf("/") + 1, soPath.lastIndexOf(".")).substring(3); /* final String soName = soPath.substring...
  • android加载指定路径so库文件

    千次阅读 2021-06-04 14:35:29
    System.load("/data/data/com.example.myapplication/files/libc++_shared.so"); System.load("/data/data/com.example.myapplication/files/libaaa.so"); } public static void initNativeDirectory(Application ...
  • 在面试程序员岗位时,我们往往需要经历一个编程面试过程,雇主会借此考验面试者的技术...x86设备能够很好的运行ARM类型函数,但并不保证100%不发生crash,特别是对旧设备。64位设备(arm64-v8a, x86_64, mips64).
  • Android NDK开发动态加载so,采用System.load方法实现
  • 1、在做ijk视频播放器的时候,要加载ijk的so库,但是在加载的时候出现了问题,视频一播放APP便会crash。报错截图如下:![图片说明](https://img-ask.csdn.net/upload/201905/27/1558935735_435331.png) 2、我查了很...
  • Android加载SO库分析.

    2016-09-06 09:06:02
    111
  • ========================= 很多设备都支持多于一种的ABI。例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二...如何查看当前设备支持那些版本的so库? ===================== 我们可以通过Build.SUPPORTED
  • 不过框架本身并不支持so本地加载使用,加载时会直接报错,因为实际上运行环境是电脑机器,而我们打出的so文件是给手机上用的所以当然会报错。虽然在GitHub上很多人问过关于使用so的问题但基本都建议说不要在单元...
  • 依赖这些,需要添加其SDK,有时需要用到jni层的So文件,比如百度地图等。那么问题来了,如果两个不同的之间的so文件发生冲突这么办?比如:单独添加地图的,运行没有问题。单独添加一个视频,运行没有问题。...
  • 本人在网上找了一些资料编写了一个jni库,用来显示yuv数据,里面用到了一些android源码的库文件如下:#include#include#include#include#include#include#include#include所以对Android.mk做了修改,包含Android源码...
  • 这篇文章通过实战案例,介绍了一种有条理的组织Native层代码层级结构的方法。并且,在良好的代码... 为什么在Native层动态加载so库随着Android App发展的不断变化,App的性能和系统API框架外的功能拓展显得越来越...
  • 某些低版本智能电视盒子系统上,APP调用System.loadLibrary会导致卡死的现象,经过定位为gnustl的问题,该示例可以稳定复现出问题
  • 安卓App在启动或运行时经常会遇到.so动态库加载失败的情况,其中具体...2.在程序运行过程中,已经加载好的.so库被卸载,导致使用的时候找不到符号,这种情况下就要在运行过程中,需要用到库的时候重新去加载 第2种情...
  • AndroidStudio动态so库加载方式

    千次阅读 2022-04-27 10:15:19
    1、粗暴型 在main目录 添加文件夹,命名为jniLibs(注意大小写也要完全一样),打包时会自动打包,这种方式简单粗暴 2、自定义型 在main下面自 定义一个...把so库放到assert目录下,然后应用运行时,根据硬件情...
  • 安卓so库动态载入

    千次阅读 2019-08-17 18:00:41
    从asset目录加载so库,安装时不导出so库,不会导致安装失败,运行时生成并载入) com.google.android.finsky.cu.k.onReceive(20): Error -504 while installing sc.game.farm: INSTALL_FAILED_INVALID_APK:...
  • 随着业务的增大,我们的业务代码也随之增多,包的...结合最近在做的公司的项目,觉得动态加载so文件是一个很好精简apk包的方法。举个例子,视频播放器的SDK(如IJKplayer,VLC player),他们的各种视频的解码器一...
  • 最近在项目中加载so文件的时候遇到一些问题,在此记录下来希望可以帮助到大家. so文件 如果说对so文件分类的话大致就64和32位so文件了,在android的libs或者jnilibs目录下你可能会发现这几种存放so文件的目录。...
  • 用于加载GIF文件Android库
  • Android 加载 SO UnsatisfiedLinkError 错误的原因及解决方案 追风 发布于 2016-05-02  Android 应用开发者应该对 UnsatisfiedLinkError 这种类型的错误比较熟悉了,这个问题一直困扰着广大的开发者,那么有...
  • android studio加载so文件的疑问记录,很多人遇到这个问题,自己各种尝试得出一片结论,乐于分享。在0.4.0版本时我总结了一篇文章,android studio V0.4.0调整。之前的理解有点不到位,把最近的理解记录下,,大家帮...
  • 在linux/android开发时,我们经常会遇到第三方的so库,如何加载这些so库呢,下面以helloworld的简单例程进行详细讲解,为了方便移植和管理,所有涉及加载实现相关的代码都放在so.cpp和so.h模块,实现代码如下: ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 129,206
精华内容 51,682
关键字:

安卓加载so库