【问题标题】:How to get the path to the lib folder for an installed package如何获取已安装软件包的 lib 文件夹的路径
【发布时间】:2011-02-05 21:56:53
【问题描述】:

共享库 .so 文件放在 lib/armeabi 的一个 apk 文件中。

我已阅读安装后的库被提取到 /data/data/application_package/lib

如何在运行时在我的应用程序中获取此目录的确切路径? 应用程序是否可以读取此目录?还是只允许可执行访问? 如果它是可读的 - 这对于受版权保护的应用程序仍然适用吗?

【问题讨论】:

    标签: android android-ndk


    【解决方案1】:

    在 API 级别 9 中添加

    getContext().getApplicationInfo().nativeLibraryDir;

    【讨论】:

      【解决方案2】:

      您可以通过以下方式获得确切的路径:

      String libraryPath = getContext().getApplicationInfo().dataDir + "/lib";
      

      应用程序可以读取目录及其文件。

      unix 权限设置为rwxr-x--x。所以应用程序 同一组可以读取文件。

      【讨论】:

      • 当我们在这里的时候,还有 ApplicationInfo.nativeLibraryDir :-)
      • 我曾经使用过这个 (.dataDir + "/lib"),但最近这不起作用,而 nativeLibraryDir
      【解决方案3】:

      如果您使用的是原生活动和 C++:

      void ANativeActivity_onCreate(ANativeActivity* app, void*, size_t) {
          const jclass contextClass = app->env->GetObjectClass(app->clazz);
          const jmethodID getApplicationContextMethod =
              app->env->GetMethodID(contextClass, "getApplicationContext", "()Landroid/content/Context;");
          const jobject contextObject =
              app->env->CallObjectMethod(app->clazz, getApplicationContextMethod);
          const jmethodID getApplicationInfoMethod = app->env->GetMethodID(
              contextClass, "getApplicationInfo", "()Landroid/content/pm/ApplicationInfo;");
          const jobject applicationInfoObject =
              app->env->CallObjectMethod(contextObject, getApplicationInfoMethod);
          const jfieldID nativeLibraryDirField = app->env->GetFieldID(
              app->env->GetObjectClass(applicationInfoObject), "nativeLibraryDir", "Ljava/lang/String;");
          const jobject nativeLibraryDirObject =
              app->env->GetObjectField(applicationInfoObject, nativeLibraryDirField);
          const jmethodID getBytesMethod = app->env->GetMethodID(
              app->env->GetObjectClass(nativeLibraryDirObject), "getBytes", "(Ljava/lang/String;)[B");
          const auto bytesObject = static_cast<jbyteArray>(app->env->CallObjectMethod(
              nativeLibraryDirObject, getBytesMethod, app->env->NewStringUTF("UTF-8")));
          const size_t length = app->env->GetArrayLength(bytesObject);
          const jbyte* const bytes = app->env->GetByteArrayElements(bytesObject, nullptr);
          const std::string libDir(reinterpret_cast<const char*>(bytes), length);
      

      【讨论】:

        【解决方案4】:
        String libpath = getApplicationInfo().nativeLibraryDir;
        

        使用的类:import android.content.pm.ApplicationInfo;

        【讨论】:

          【解决方案5】:
          String libraryPath = context.getFilesDir().getParentFile().getPath() + "/lib";
          

          为了更好的兼容性,请使用以下函数:

          @TargetApi(Build.VERSION_CODES.GINGERBREAD)
          public static String getLibraryDirectory(Context context) {
              int sdk_level = android.os.Build.VERSION.SDK_INT;
          
              if (sdk_level >= Build.VERSION_CODES.GINGERBREAD) {
                  return context.getApplicationInfo().nativeLibraryDir;
              } 
              else if (sdk_level >= Build.VERSION_CODES.DONUT) {
                  return context.getApplicationInfo().dataDir + "/lib";
              }
          
              return "/data/data/" + context.getPackageName() + "/lib";
          }
          

          【讨论】:

          • 您确定可以从该位置加载本机库吗?
          • 是的,我已经在我的应用程序中检查过了。有什么问题?
          • 不适用于运行 5.1.1 的 HTC M9+。 lib 链接在那里,但没有指向正确的目录。 Crossie 的解决方案是 (getContext().getApplicationInfo().nativeLibraryDir;)
          • 感谢您的评论。而且,如果你有 lib 链接,你也可以轻松访问该库,这不能满足你的需求吗? @kshepherd
          【解决方案6】:

          可能一个设备支持不同的 CPU_ABI,所以最好获取包含所有子库目录的 nativeRootLibraryDir:

          public static String getNativeLibraryDirectory(Context context) {
              int sdk_level = android.os.Build.VERSION.SDK_INT;
          
              if (sdk_level >= Build.VERSION_CODES.GINGERBREAD) {
                  try {
                      String secondary = (String) ApplicationInfo.class.getField("nativeLibraryRootDir").get(context.getApplicationInfo());
                      return secondary;
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return null;
              }
              else if (sdk_level >= Build.VERSION_CODES.DONUT) {
                  return context.getApplicationInfo().dataDir + "/lib";
              }
          
              return "/data/data/" + context.getPackageName() + "/lib";
          }
          

          【讨论】:

            猜你喜欢
            • 2011-09-02
            • 2019-09-22
            • 1970-01-01
            • 2012-06-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-10-17
            相关资源
            最近更新 更多