Android ContentProvider openFile:需要提供“修改后的”文件

2024-01-02

我想通过以下方式提供保存在“外部存储”上的图像文件ContentProvider.

这些图像文件被“破坏”——前 50 个字节与某个任意值进行异或。我想在里面做“demangle”ContentProvider以便其他应用程序不需要做特殊处理。

我使用的是 Mininum SDK 版本 14。

这是我的第一次尝试 - 使用管道ParcelFileDescriptor:

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    // basic uri/mode check here
    return openPipeHelper(uri, getType(uri), null, new FileInputStream(getImageFile(uri)), new PipeDataWriter<InputStream>() {
        @Override
        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, final String mimeType, Bundle opts, InputStream input) {
            InputStream fin = new FilterInputStream(input) {
                private int cnt = 0;
                private byte mask;

                @Override
                public int read() throws IOException {
                    byte[] buffer = new byte[1];
                    return read(buffer) == -1 ? -1 : (buffer[0] & 0xff);
                }

                @Override
                public int read(@NonNull byte[] buffer) throws IOException {
                    return read(buffer, 0, buffer.length);
                }

                @Override
                public int read(@NonNull byte[] buffer, int byteOffset, int byteCount) throws IOException {
                    int ret = super.read(buffer, byteOffset, byteCount);
                    if (ret <= 0) return ret;
                    if (cnt == 0) {
                        switch (mimeType) {
                            case "image/png":
                                mask = (byte) (buffer[byteOffset] ^ 137);
                                break;
                            case "image/webp":
                                mask = (byte) (buffer[byteOffset] ^ 'R');
                                break;
                        }
                    }
                    for (int i = byteOffset; i < byteOffset + ret && cnt < 50; i++, cnt++) {
                        buffer[i] ^= mask;
                    }
                    return ret;
                }
            };
            OutputStream fout = new ParcelFileDescriptor.AutoCloseOutputStream(output);
            byte[] buf = new byte[1024 * 1024];
            try {
                while (true) {
                    int n = fin.read(buf);
                    if (n == -1) break;
                    Log.i(TAG, "openFile get n=" + n);
                    fout.write(buf, 0, n);
                    fout.flush();
                }
            } catch (IOException ex) {
                // EPIPE likely means pipe closed on other end; treat it as WAI.
                if (!ex.getMessage().contains("EPIPE")) {
                    Log.w(TAG, "openFile failed", ex);
                }
            } finally {
                try {
                    fin.close();
                } catch (IOException ex) {
                    Log.w(TAG, "openFile failed closing input", ex);
                }
                try {
                    fout.close();
                } catch (IOException ex) {
                    Log.w(TAG, "openFile failed closing output", ex);
                }
            }
        }
    });
}

Result:

  • 与以下产品配合良好ImageView.setImageURI().
  • 不适用于 Android 默认图库(Intent.ACTION_VIEW with setDataAndType())
  • 与 ES 图像查看器配合良好

看来画廊不喜欢“管道流”。

这是第二次尝试 - 读取整个文件,分解并用作ParcelFileDescriptor.fromData():

    File file = getImageFile(uri);
    byte[] buffer = readFully(file);
    String mimeType = getType(uri);
    byte mask;
    switch (mimeType) {
        case "image/png":
            mask = (byte) (buffer[0] ^ 137);
            break;
        case "image/webp":
            mask = (byte) (buffer[0] ^ 'R');
            break;
        default:
            mask = 0;
            break;
    }
    for (int i = 0; i < 50; i++) buffer[i] ^= mask;
    return (ParcelFileDescriptor) ParcelFileDescriptor.class.getMethod("fromData", byte[].class, String.class).invoke(null, buffer, getImageFile(uri).getName());

Result:

  • 不能很好地与ImageView.setImageURI().
  • 与 Android 默认图库配合良好
  • 与 ES 图像查看器配合良好

似乎时不时地,MemoryFile在制作ParcelFileDescriptor.fromData()之前已关闭并处置ImageView.setImageURI()获取数据。

这是第三次尝试 - 将分解的图像写入临时文件:

    // buffer contains readFully and demangled image binary
    try {
        File tmpFile = File.createTempFile("image", getImageExtension(uri));
        OutputStream os = new FileOutputStream(tmpFile);
        try {
            os.write(buffer);
        } finally {
            try {
                os.close();
            } catch (IOException ex2) {
                Log.w(TAG, "openFile(): closing failed", ex2);
            }
        }
        return ParcelFileDescriptor.open(tmpFile, ParcelFileDescriptor.MODE_READ_ONLY);
    } catch (IOException ex2) {
        Log.e(TAG, "openFile(): writing failed", ex2);
        return null;
    }

Result:

  • 与以下产品配合良好ImageView.setImageURI().
  • 与 Android 默认图库配合良好
  • 与 ES 图像查看器配合良好

但是,我不喜欢这个解决方案,因为很难确定何时可以删除临时文件。

这三个解决方案都有其缺陷,我找不到完美的解决方案。做这些事情的“正确”方法是什么?


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android ContentProvider openFile:需要提供“修改后的”文件 的相关文章

  • Java - JPanel 内有边距和 JTextArea

    我想创建这样的东西 主面板有其边距 x 并且 TextArea 位于该面板的中心 几乎填满了面板 底部是另一个具有自定义尺寸 高度 y 的面板 可以使用某些快捷方式将其切换为可见和不可见 底部面板有 FlowLayout 和几个元素 问题是
  • LocalDate 减去 period 得到错误的结果

    LocalDate减去一个Period 如 28年1个月27天 得到错误的结果 但减去一个Period 只有天单位 如 10282 天 得到正确的结果 有什么需要注意的吗 public static void main String arg
  • 将现有 eclipse 项目导出到 war 文件时出现“模块名称无效”

    我正在尝试将现有 Eclipse 项目导出到 war 文件 但无论我在 WAR Export 对话框页面中输入什么 系统总是返回 模块名称无效 我不知道如何解决这个问题 谢谢您的帮助 我有同样的问题 我修复了它 请按照以下步骤操作 您可以创
  • 从 HttpClient 3 转换为 4

    我已经成功地对所有内容进行了更改 但以下内容除外 HttpClient client HttpPost method client new DefaultHttpClient method new HttpPost url InputStr
  • 更改 JComboBox 中滚动条的大小

    有谁知道如何手动更改 jComboBox 中的滚动条大小 我已经尝试了一大堆东西 但没有任何效果 好吧 我明白了 您可以实现 PopUpMenuListener 并使用它 public void popupMenuWillBecomeVis
  • 如何使用 MotionLayout 调整 TextView 的大小

    我正在尝试创建一个CollapsingToolbar动画使用MotionLayout 我已经成功地将所有内容设置为动画 使其表现得像CollapsingToolbar具有高度的灵活性 这意味着我可以轻松创建很棒的动画 而无需编写大量代码 我
  • 调整 SwipeRefreshLayout 高度,将 View 置于其底部

    I have SwipeRefreshLayout里面一个RelativeLayout 问题是SwipeRefreshLayout占据了屏幕上的所有位置 我需要放置一个视图after这个观点 看图片 https i stack imgur
  • 多线程——更快的方法?

    我有一堂有吸气剂的课程getInt 和一个二传手setInt 在某个领域 比如说领域 Integer Int 一个类的一个对象 比如说SomeClass The setInt 这里是同步的 getInt isn t 我正在更新的值Int来自
  • 运行 Android 应用程序时出现错误

    我已经使用 Eclipse 创建了一个 Android 应用程序 但应用程序未在 AVD 上运行 它显示 不幸的是已停止工作 日志猫消息如下 07 29 04 59 50 789 W dalvikvm 784 threadid 1 thre
  • JAXB 编组器无参数默认构造函数

    我想从 java 库中编组一个 java 对象 当使用 JAXB marschaller 编组 java 对象时 我遇到了一个问题 A 类没有无参数默认构造函数 我使用Java Decompiler来检查类的实现 它是这样的 public
  • Android项目中使用java获取电脑的IP地址

    我在用ksoap2 android http code google com p ksoap2 android 我需要使用java获取IP地址 这样我就不必每次都手动输入它 我所说的 IP 地址是指 例如 如果我这样做ipconfig使用命
  • 如果我的应用程序安装在 SD 卡上,私人数据也在那里吗?

    我假设应用程序的私有数据 例如 SharedPreferences 和 SQLite 数据库 位于手机的内部存储而不是 SD 卡上 即使应用程序本身安装在 SD 卡上 我在任何地方都找不到对此的简单明确的确认 有人可以确认一下吗 是的 私有
  • Android Jetpack Compose 尺寸随持续时间变化的动画

    如何在 Jetpack Compose 中添加内容大小更改动画的持续时间 尝试使用Modifier animateContentSize 并通过动画规格具有持续时间 但它只是突然进入或退出 没有观察到持续时间 Column Modifier
  • 如何将库添加到 LIBGDX 项目的依赖项 gradle

    一切都在问题中 我已经尝试了在 SO 和其他网站中找到的所有答案 但没有运气 这就是我迄今为止尝试过的 adding compile fileTree dir lib include jar 到我的 build gradle adding
  • CXF:通过 SOAP 发送对象时如何排除某些属性?

    我使用 Apache CXF 2 4 2 当我将数据库中的某个对象返回给用户时 我想排除一些属性 例如密码 我怎样才能做到这一点无需创建临时的班级 有这方面的注释吗 根据 tomasz nurkiewicz 评论我应该使用 XmlTrans
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • Android - 如何简单地拖放按钮?

    我在这里找到了一个适合初学者的教程 http androidrox wordpress com 2011 05 13 android sample app drag and drop image using touch http andro
  • Android Volley - 发布请求 - 无法在线工作

    我试图通过 Volley 发出 POST 请求 它在我的本地主机中工作得很好 但是当我将它移动到网络服务器时 响应为空 Java代码 RequestQueue queue Volley newRequestQueue this String
  • 如何减少 Android 中浮动 editText 提示和 editText 框之间的空间?

    我有一个带有浮动提示的 EditText 但我想知道如何减少浮动提示和 EditText 框之间的空间 现在我的用户界面看起来像https i stack imgur com ltfra jpg https i stack imgur co
  • 如何使用注释处理 Hibernate 和 Spring 中的连接查询?

    我正在使用 Spring 和 Hibernate 以及 MySQL 开发应用程序 我是 Hibernate 新手 完成了基本任务 现在我需要在选择查询中应用联接以使用注释从多个表中获取数据 我已经搜索过但仍然没有任何想法 这是我的数据库表和

随机推荐

  • Firefox 表示无法从以下位置下载搜索插件

    背景故事 我正在尝试动态生成开放搜索 http www opensearch org Specifications OpenSearch Extensions Suggestions 1 1Firefox 的搜索插件基于用户输入的值 作为较
  • 递归搜索二进制文件目录中的十六进制序列?

    我用来搜索一些十六进制值的当前命令 例如0A 8b 02 涉及 find type f not name png exec xxd p grep 0a8b02 xargs 0 P 4 鉴于以下目标 是否可以改进这一点 递归搜索文件 显示偏移
  • 在框架头中找不到 swift 文件

    我正在尝试创建一个简单的框架来快速测试 我已经在 Objective C 中用 创建框架 发布了这个问题before https stackoverflow com questions 27652648 i created a framew
  • git 快进一次提交

    9dbd857 hotfix correct java jdk path feature add ansible galaxy requirements file requirements yml adds maven and nodejs
  • 如何用c++移动鼠标

    我想用 C 脚本移动鼠标光标 我在 Parallels 内的 Windows 7 中使用 Visual C 2010 Express 并创建了一个控制台应用程序 我知道 SetCursorPos 方法 但它不起作用 它什么也不做 我设法用
  • 段落换行后有空格

    我使用浅黄色框在 HTML 页面上显示编程内容 类似于这一页 http api rubyonrails org classes ActionView Helpers UrlHelper html method i link to 为了制作一
  • Flex 正则表达式 到 Java 正则表达式

    最近 我正在寻求帮助 以使用 Flex 中的 RegEx 提取 URL 的某些模式 很少有人好心地帮助我完成它 See this https stackoverflow com questions 7358756 how to extrac
  • 将 MongoDb _id 从字符串更改为 ObjectId

    我们的文档最初是使用 id 的 StringObjectIdGenerator 类型存储的 较新的数据将使用默认的 ObjectIdGenerator 保存 我们希望能够通过将 id 转换为新的数据类型来迁移现有数据 这可能吗 是的 可以更
  • 如何使用 Python 对不同前缀同时运行 AWS S3 同步命令

    我正在尝试编写一个 python 脚本 它使用 subprocess 模块将文件从一个 s3 存储桶复制到另一个 但是 为了提高性能 我尝试并行运行具有不同前缀的单独同步命令 到目前为止我所尝试的脚本没有终止 并且我不确定子进程是否同时运行
  • 推断类型相等的 if 和 else 的约束

    我正在尝试填补以下代码片段中的漏洞 import Data Proxy import GHC TypeLits import Data Type Equality import Data Type Bool import Unsafe Co
  • 如何在 Java 中使用正则表达式模式匹配字符串的结尾?

    我想要一个与字符串末尾匹配的正则表达式模式 我正在实现一种词干算法 该算法将删除单词的后缀 例如 对于单词 Developers 它应该与 s 匹配 我可以使用以下代码来做到这一点 Pattern p Pattern compile s M
  • 代码分析 CA1060 修复

    我的应用程序中有以下代码 DllImport user32 dll private static extern int GetWindowLong IntPtr hwnd int index DllImport user32 dll pri
  • 按两个数字对列名进行排序

    我最近得到了这个惊人的答案 https stackoverflow com a 72141622 8071608来自 JBGruber 用于对具有双数值的字符串列进行排序 这适用于帖子底部的两个数据集 library magrittr or
  • Rails——创造再创造!方法,FoR 3 教程

    所以我知道 bang 感叹号 和非 bang 方法之间的区别通常是该方法是否会修改对象本身或返回一个单独的修改对象而保持原始对象不变 然后 在本书第 6 章构建用户模型时 我遇到了User create方法 该方法创建一个新模型并将其保存到
  • 从谷歌选择器选择文件后立即下载文件

    我只是想实现 Google Drive Picker API 以便下载用户通过 Google Drive Picker 提交的文件 在后台 我使用了 Google 选择器 效果很好 但后来我无法下载该文件 首先从单个文件开始 这是我的代码
  • 为什么径向树布局绘图算法会产生交叉边?

    根据 Andy Pavlo 先生的出版物 我正在实施径向布局绘图算法 第18页 问题是 我的结果包含交叉边 这是令人无法接受的 我找到了一些解决方案 类似的问题link https stackoverflow com questions 3
  • Koa.js - 提供静态文件和 REST API

    我是 koa js 库的新手 我需要一些帮助 我正在尝试使用 koa 制作简单的 REST 应用程序 我有一个静态 html 和 javascript 文件 我想在路线上提供服务 和 REST API 访问 api 这是我的项目目录树 pr
  • 启动 Windows 服务并启动 cmd

    我是否需要启用交互式桌面才能工作 启动 EXE 或 cmd 窗口的正确代码是什么 即使我已启用该服务与桌面交互 我仍然无法启动该服务 我将使用聊天引擎 这样作为 Windows 服务更容易管理 我的代码有什么问题吗 using System
  • 调试发布构建类型而不生成签名的 APK

    我有一个具有两种构建类型的项目设置 debug and release 在我的应用程序模块中 我有三个不同的目录 debug release and main 我想做的是测试中的代码release目录 但我似乎能做到这一点的唯一方法是生成一
  • Android ContentProvider openFile:需要提供“修改后的”文件

    我想通过以下方式提供保存在 外部存储 上的图像文件ContentProvider 这些图像文件被 破坏 前 50 个字节与某个任意值进行异或 我想在里面做 demangle ContentProvider以便其他应用程序不需要做特殊处理 我