当我只能处理文件或文件路径时,如何处理SAF? [英] How to handle SAF when I can only handle File or file-path?

查看:128
本文介绍了当我只能处理文件或文件路径时,如何处理SAF?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

直到Android Q,如果我们想获取有关APK文件的信息,可以使用 WRITE_EXTERNAL_STORAGE

Up until Android Q, if we wanted to get information about an APK file, we could use WRITE_EXTERNAL_STORAGE and READ_EXTERNAL_STORAGE to get access to the storage, and then use PackageManager.getPackageArchiveInfo function on the file-path.

存在类似的情况,例如使用 ZipFile类> 压缩文件,可能还有无数的框架API和第三方库.

Similar cases exist, such as using ZipFile class on a compressed file, and probably countless framework APIs and third party libraries.

Google最近宣布了对Android Q的大量限制.

Google announced a huge amount of restrictions recently on Android Q.

其中一个称为 范围存储 ,当访问设备上的所有文件时,这会破坏存储权限.它使您可以处理媒体文件,也可以使用受限制的Storage-Access-Framework( SAF ),该应用程序不允许应用使用File API和文件路径访问和使用文件.

One of them is called Scoped Storage, which ruins storage permission when it comes to accessing all files the device has. It lets you either handle media files, or use the very restricted Storage-Access-Framework (SAF) which can't allow apps to reach and use files using File API and file-paths.

发布Android Q Beta 2时,它因此破坏了很多应用程序,包括Google.原因是默认情况下已将其打开,这会影响所有应用程序,无论它们是否针对Android Q.

When Android Q Beta 2 was published, it broke a lot of apps because of it, including of Google. The reason was that it was turned on by default, affecting all apps, whether they target Android Q or not.

原因是许多应用程序,SDK和Android框架本身-都经常使用File API.在许多情况下,它们也不支持InputStream或SAF相关的解决方案.一个例子就是我写过的APK解析例子(PackageManager.getPackageArchiveInfo).

The reason is that many apps, SDKs and Android framework itself - all use File API quite often. On many cases, they also don't support InputStream or SAF-related solutions. An example for this is exactly the APK parsing example I wrote about (PackageManager.getPackageArchiveInfo).

但是,在Q beta 3上,情况有所变化,因此目标Q的应用将具有范围存储,并且有一个标志将其禁用,并且仍然照常使用常规存储权限和File API.遗憾的是,该标志只是暂时的(请阅读 此处 ),因此延迟了不可避免的时间.

On Q beta 3, however, things changed a bit, so that app that target Q will have the scoped storage, and there is a flag to disable it and still use the normal storage permissions and File API as usual. Sadly the flag is only temporary (read here), so it's delaying the inevitable .

我已经尝试并发现了以下内容:

I've tried and found the next things:

  1. 使用存储权限确实并没有让我读取不是媒体文件的任何文件(我想找到APK文件).好像文件不存在.

  1. Using the storage permission indeed didn't let me read any file that's not media file (I wanted to find APK files). It's as if the files don't exist.

使用SAF,我可以找到APK文件,并通过一些变通办法来找到其真实路径(链接 此处

Using SAF, I could find the APK file, and with some workaround to find its real path (link here), I've noticed that File API can tell me that indeed the file exist, but it couldn't get its size, and the framework failed to use its path using getPackageArchiveInfo . Wrote about this here

我试图对文件进行符号链接(链接

I tried to make a symlink to the file (link here), and then read from the symlink. It didn't help.

对于解析APK文件的情况,我尝试搜索其他解决方案.我发现有2个使用File类处理APK的github存储库( 此处 此处 ),然后使用InputStream代替( 此处 ).遗憾的是,使用InputStream的那个版本很旧,缺少各种功能(例如获取应用程序的名称和图标),并且不会很快更新.此外,拥有一个库需要维护以跟上未来版本的Android,否则将来可能会出现问题,甚至崩溃.

For the case of parsing APK files, I tried to search for alternative solutions. I've found 2 github repositories that handle the APK using a File class (here and here), and one that uses InputStream instead ( here). Sadly the one that uses InputStream is very old, missing various features (such as getting the app's name and icon) and isn't going to be updated anytime soon. Besides, having a library requires maintenance to keep up with future versions of Android, otherwise it might have issues in the future, or even crash.

问题

  1. 通常,使用SAF时是否仍可以使用File API?我不是在谈论根解决方案,也不是在将文件复制到其他地方.我说的是更可靠的解决方案.

  1. Generally, is there a way to still use File API when using SAF ? I'm not talking about root solutions or just copying the file to somewhere else. I'm talking about a more solid solution.

对于APK解析,是否有一种方法可以解决此问题,即框架仅提供文件路径作为参数?有什么解决方法或使用InputStream的方法吗?

For the case of APK parsing, is there a way to overcome this issue that the framework only provides file-path as a parameter? Any workaround or a way to use InputStream perhaps?

推荐答案

当我只能处理文件或文件路径时,如何处理SAF?即使您只能将Java File对象或路径字符串发送到无法修改的库函数,也有可能:

How to handle SAF when I can only handle File or file-path? It is possible, even if you can send only a Java File object, or path string to a library function which you cannot modify:

首先,获取需要处理的文件的Uri(以String形式,类似于"content://..."),然后:

First, obtain a Uri to a file you need to handle (in String form it would be like "content://..."), then:

    try {
        ParcelFileDescriptor parcelFileDescriptor =
                getContentResolver().openFileDescriptor(uri, "r"); // may get FileNotFoundException here
        // Obtain file descriptor:
        int fd = parcelFileDescriptor.getFd(); // or detachFd() if we want to close file in native code
        String linkFileName = "/proc/self/fd/" + fd;
        // Call library function with path/file string:
        someFunc(/*file name*/ linkFileName);
        // or with File parameter
        otherFunc(new File(linkFileName));
        // Finally, if you did not call detachFd() to obtain the file descriptor, call:
        parcelFileDescriptor.close();
        // Otherwise your library function should close file/stream...
    } catch (FileNotFoundException fnf) {
        fnf.printStackTrace(); // or whatever
    }          

这篇关于当我只能处理文件或文件路径时,如何处理SAF?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆