处理写入外部SD卡的最佳做法?

时间:2014-11-12 21:11:17

标签: android

我的应用程序允许用户浏览其文件系统以选择保存文件的位置。不幸的是,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));
        }
    }
}

2 个答案:

答案 0 :(得分:1)

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

解决问题的官方方法是存储访问框架: http://developer.android.com/guide/topics/providers/document-provider.html

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

这应该是ACTION_OPEN_DOCUMENT_TREE,但它是API21。而且我在一个装有SD插槽的设备上安装棒棒糖,还不能测试;-)这里有人使用Moto G还是LG G3? :) http://developer.android.com/reference/android/content/Intent.html#ACTION_OPEN_DOCUMENT_TREE

答案 1 :(得分:0)

不确定这对你有多大帮助,但这就是我在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。