当前位置: 首页 > article >正文

DexclassLoader读取dex在Android14上遇到问题

报错如下:

在Android 14(API 级别 34)及以后版本中,DexClassLoader 被进一步限制,只能用于加载只读文件中的代码。这意味着你不能再使用 DexClassLoader 来加载从应用的内部存储空间中读取的文件。

我想通过JNI来修改只读文件,网上查找的方案如下:

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
 
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_yourapp_FileUtils_setFileReadOnly(JNIEnv *env, jobject obj, jstring path_) {
    const char *path = env->GetStringUTFChars(path_, 0);
    int result = chmod(path, S_IRUSR);
    env->ReleaseStringUTFChars(path_, path);
 
    if (result == -1) {
        // 错误处理
        return JNI_FALSE;
    }
 
    return JNI_TRUE;
}

C语言中提示修改成功。但是使用DexClassLoader的时候还是报上面一样的错误,应该是修改已读没有修改成功。

于是我换方案,通过反射调用Java中File类的setReadOnly方法试一下,代码如下:

//反射创建Java中的File对象
JNIEXPORT jobject JNICALL
Java_FileUtils_createFile(JNIEnv *env, jobject obj, jstring path) {
    // 获取File类
    jclass fileClass = (*env)->FindClass(env, "java/io/File");
    if (fileClass == NULL) {
        return NULL; // 类未找到
    }

    // 获取File(String path)构造器
    jmethodID ctorID = (*env)->GetMethodID(env, fileClass, "<init>", "(Ljava/lang/String;)V");
    if (ctorID == NULL) {
        return NULL; // 方法未找到
    }
    // 使用构造器创建File对象
    jobject fileObject = (*env)->NewObject(env, fileClass, ctorID, path);

    return fileObject;
}

//反射调用setReadOnly方法
JNIEXPORT void JNICALL
Java_FileUtils_setJavaFileReadOnly(JNIEnv *env, jobject obj, jstring path) {

    jobject  file = Java_FileUtils_createFile(env,obj,path);

    // 获取File类
    jclass fileClass = (*env)->FindClass(env, "java/io/File");
    if (fileClass == NULL) {
        LOGI("找到File class");
    }
    // 获取setReadOnly方法ID
    jmethodID setReadOnlyID = (*env)->GetMethodID(env, fileClass, "setReadOnly", "()Z");
    if (setReadOnlyID == NULL) {
        LOGI("找到setReadOnly方法");
    }
    //调用方法
  (*env)->CallBooleanMethod(env, file,fileClass,setReadOnlyID);
}

方法者找到了,不报方法找不到的错误了,但最终还是报了其他的错。

搜了一下,用反射调用setReadOnly可能有各种兼容问题:

还是放弃反射调用吧,还是回调到java里设置setReadOnly吧。


http://www.kler.cn/a/290567.html

相关文章:

  • 【CICD】GitLab Runner 和执行器(Executor
  • Qt初识简单使用Qt
  • 软件工程的基础和核心理论概念
  • Android HandlerThread 基础
  • 壹连科技IPO闯关成功!连接器行业上市企业+1
  • Linux如何将文件或目录打成rpm包?-- rpmbuild打包详解
  • Java SPI机制源码
  • Hive锁表、hive查询表是否被锁、hive解锁表
  • Django+vue自动化测试平台(29)--测试平台集成playwright录制pytest文件执行
  • MVC架构模式
  • Java-线程的生命周期7大状态
  • 读写分离深度解析与MaxScale配置指南
  • 2024嵌入式面试:VIVO嵌入式面试题及参考答案(6万字长文)
  • selenium启动总报错 WebDriverManager总是异常
  • Datawhale X 李宏毅苹果书 AI夏令营 - 跟李宏毅学深度学习(入门之线性模型)
  • XR-Frame 实现 始终朝向屏幕(相机)的面片与模型
  • vue路由Router设置父路由默认选中第一个子路由,切换子路由让父路由激活高亮效果不会消失
  • 因 Mysql root 密码过于简单导致 Mysql 连接失败的解决方法
  • C++学习笔记(4)
  • 集成电路学习:什么是MMU存储管理单元
  • Get full article in Google Sheet using Openai
  • Python知识点:如何使用Mock库进行单元测试中的依赖模拟
  • Linux查看系统用户
  • 海康二次开发笔记10-独立Group导入、导出及执行
  • HTTP代理支持UDP协议吗?
  • ROS imu传感器节点