确定共享数据时是否超过 1MB 限制

Determine if 1MB limit is exceeded when sharing data

我有一个类似于资源管理器的应用程序,允许用户共享文件夹、多个文件夹和多个文件。共享意图最后会保存所有共享文件的列表。

如果用户共享一个包含 1000 个文件的文件夹,这就太多了。但是我如何确定是否可以共享用户 select 编辑的文件数量?

我想检查是否可以共享用户 selected 的文件数量,如果不能,我想告诉他他 selected 了很多文件并达到了 android极限。在最好的情况下,我想告诉他他的共享意图是 2.5MB,限制是 1MB,所以他可以自己估计他应该有多少文件 select...

问题

编辑

消除混淆:

我并没有直接在意图中共享文件,而只是共享文件的URI 或相对路径。因此 URI 的长度或相对路径的长度对于意图的大小很重要,但如果它指向大文件或小文件则不重要。

1MB 限制对 Intent 有效(我认为是 parceled Intent),如果 Intent 包含大量数据,它将无提示地失败,这就是问题所在

我正在寻找可重复使用的解决方案,适用于任何目的!我有时会添加共享目标,有时不会。

为什么不调用 shell 命令来获取文件的大小?

它不会准确确定意图大小,但会为您提供一个不错的预测。

try {
    Process process = Runtime.getRuntime().exec("ls -l");
    BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
} catch (InterruptedException e) {
    e.printStackTrace();
}

确保您不使用 awk 和其他在某些设备上可能不可用的内容。 对于目录大小,您需要使用不同于 ls.

的内容

意图:

您可以将该意图对象写入 Parcel and use dataSize() 方法以获取该意图中包含的序列化数据大小。之后一定要recycle()包裹。

    final Intent testIntent = getIntent();
    final Parcel testParcel = Parcel.obtain();
    try {
        testParcel.writeParcelable(testIntent,0);
        Log.i("TEST", String.format("Intent size: %s", testParcel.dataSize()));
    }finally {
        testParcel.recycle();    
    }

对于文件:

如果您可以从 Intent 中检索文件名列表,那么您可以查询每个文件的大小并将其加起来:

sizeBytes += new File(filePath).length();

对于一个目录,您需要遍历并将其下所有文件的大小相加。您可以为此使用 DirectoryWalker class。

在上面加上一个合理的最坏情况数字可能更有意义。 “You have shared too many files (1005/1000 files)”将是一条有用的消息。当您指的是文件名的长度而不是文件的大小时,告诉用户他们共享了太多字节会让人感到困惑。

最坏情况下的文件名是127 characters or 255 bytes

1MB/256 = 4096

因此,我认为 4000 是有风险的,但 2000-3000 应该没问题,具体取决于其余负载的大小。

如果您认为这对您的用户来说还不够,那么您需要一个不同的解决方案,而不是一个警告。

您可以做的是保持对正在select编辑的文件名长度的引用以避免以后循环遍历它们

1 character = 1 byte. so, about 1000 characters equal 1 kilobyte.

所以基于此,您可以限制用户 selection 并能够在他们 select 处理文件时实际告诉他们,他们达到了文件的最大数量 select(一般消息)。示例代码:

private int maxLength = 0;

    onSelectFile(File file){
        maxLength += file.getName().length()
        if(maxLength < 1mb ){//display massage and dont add the new selected file}
    }

我相信没有直接的方法来检查它,但您可以对其进行手动操作以获得您的意图的大小。

考虑到 Intent implements Parcelable 你应该能够得到一个 Parcel,写入它,并在 sending/launching 意图之前检查它的大小。类似的东西:

Intent intent = ....
... do your intent and fill with the URI data.

Parcel parcel = Parcel.obtain();
intent.writeToParcel(parcel, 0);
int size = parcel.dataSize(); // HERE IS THE NUMBER YOU WANT TO CHECK
parcel.recycle(); // don't forget to return the parcel to the system
parcel = null;

我不确定该大小是否以字节为单位,但应该是。如果你想要官方文档,请在此处 https://developer.android.com/reference/android/os/Parcel.html

根据用户体验说明,您可能希望在用户选择内容时不断检查大小,这样一旦达到限制,您就可以阻止用户选择任何额外的内容,这样就不会浪费用户时间.