【问题标题】:Best practice for handling writing to external sd card?处理写入外部 SD 卡的最佳实践?
【发布时间】:2014-11-13 05:37:26
【问题描述】:

我的应用程序允许用户浏览他们的文件系统以选择保存文件的位置。不幸的是,4.4 用户不再能够保存到外部 SD 卡。我在网上找到的所有解决方法都被称为“不是特别好的想法”,但其他应用程序目前已成功保存到外部 sd 卡,所以我认为这些解决方法正在使用中。

是否有解决此问题的安全/智能解决方法或推荐的最佳做法?

一些在 4.4.2 设备上引发异常的代码:

public class SdSample extends Activity 
{
    public void onCreate(Bundle bundle)
    {
        super.onCreate(bundle);

        File external = new File("/storage/extSdCard/DCIM/");
        File textFile = new File(external, "textfile.txt");

        try
        {
            textFile.createNewFile();

            FileOutputStream fos = new FileOutputStream(textFile);
            fos.write("Hello".getBytes());
            fos.close();
        }
        catch (Exception e)
        {
            //java.io.IOException: open failed: EACCES (Permission denied)
            Log.e("", Log.getStackTraceString(e));
        }
    }
}

【问题讨论】:

    标签: android


    【解决方案1】:

    AFAIK 只有使用媒体内容提供程序的 MediaFile hack。但它不适用于所有设备。例如。在这里它在三星 Galaxy Note3 Neo 上失败了。在这里我找到了 MediaFile hack:http://forum.xda-developers.com/showthread.php?t=2634840

    官方解决问题的方法是Storage Access Framework: http://developer.android.com/guide/topics/providers/document-provider.html

    在 Android 4.4 上,这仅适用于用户必须选择的单个文件。至少您可以完全访问该文件,即使在其他应用程序的数据目录中(在 SD 上)也是如此。但据我了解,这是不可能的,例如让用户选择一个目录,然后在以后拥有对该目录的完全访问权限。

    这应该与 ACTION_OPEN_DOCUMENT_TREE 一起提供,但它是 API21。而且我希望在带有 SD 插槽的设备上安装 Lollipop,但还无法测试 ;-) 这里有人使用 Moto G 或 LG G3 吗? :) http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT_TREE

    【讨论】:

    • 您好,非常感谢您的回复。我尝试在 Galaxy Note3 上运行您的 MainActivity 测试应用程序,但它无法创建初始测试目录,并发出通知“无法创建基本目录:/storage/extSdCard/MediaWrite”。此外,当尝试在其他地方使用您的 MediaFile 类时(不使用您的测试应用程序),我得到 FileNotFoundExceptions。你认为这是因为我使用的设备(我会尝试另一个)吗?在这种情况下,有什么方法可以使这种解决方法起作用吗?
    • 另外,我在 Galaxy s4 上进行了尝试,结果相同。
    • 我认为 MediaFile 类不值得再花时间了。我刚刚在已植根且 SD 问题已手动解决的 Galaxy S5 上进行了尝试,但在那里,MediaFile hack 不起作用。所以要么存储访问框架,要么让用户根设备。
    • 知道其他应用程序如何解决这个问题吗?例如,应用程序 EZPDF 似乎找到了一种有效的解决方法......
    【解决方案2】:

    不确定这是否对您有很大帮助,但这是我必须在 SD 卡上写入内容时使用的方法。这是我在iosched project 中找到的代码的略微修改版本。它返回一个文件夹,您可以在该文件夹下创建子文件夹和文件。它也适用于不同的 Android 版本。

    @TargetApi(Build.VERSION_CODES.KITKAT)
    public static File getBestAvailableFilesRoot(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // In KitKat we can query multiple devices.
            // TODO: optimize for stability instead of picking first one
            File[] roots = context.getExternalFilesDirs(null);
            if (roots != null) {
                for (File root : roots) {
                    if (root == null) {
                        continue;
                    }
                    if (Environment.MEDIA_MOUNTED.equals(Environment.getStorageState(root))) {
                        return root;
                    }
                }
            }
    
        } else if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            // Pre-KitKat, only one external storage device was addressable
            return context.getExternalFilesDir(null);
        }
    
        // Worst case, resort to internal storage
        return context.getFilesDir();
    }
    

    Android 5.0 adds more support 在存储用户文件的位置。你也可以看看那个新的 API。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 2018-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多