【问题标题】:App crashes on devices with removable sd card when it is not inserted未插入可移动 sd 卡的设备上的应用程序崩溃
【发布时间】:2015-10-28 03:54:24
【问题描述】:

我的应用程序将从其他设备接收到的文件存储在外部存储中。它适用于带有不可移动 SD 卡的设备

问题出在 Galaxy Tab4 上,当没有插入外部 SD 卡时。

我正在使用以下行来获取文件路径

String filePath=Environment.getExternalStorageDirectory()+"/BFT/";

我想要做的是,如果外部 sd 卡是可移动的并且没有插入,我想在设备存储中创建上述目录(就像 Galaxy s4 中提供的 16 GB)。

我很困惑,因为在 Galaxy s4 中它工作正常,但在使用 Environment.getExternalStorageDirectory()+"/BFT/" 时它存储在此目录中

This is where it is stored on S4

如何使它在 tab4 或任何其他设备上工作,当外部 sd 卡可移动且未插入并且我使用上述行时,可能会崩溃。

我只想在设备上创建一个文件夹,无论其存储架构是什么。赞赏具体代码或至少是什么导致错误(我知道找不到目录。但是为什么?)。

【问题讨论】:

  • 您只需在操作其目录之前检查 ExternalStorage 是否可用。

标签: android android-sdcard


【解决方案1】:

使用前需要获取外部存储目录的状态

getExternalStorageState() 返回主要共享/外部存储媒体的当前状态。

Returns
one of MEDIA_UNKNOWN, MEDIA_REMOVED, MEDIA_UNMOUNTED, MEDIA_CHECKING, MEDIA_NOFS, MEDIA_MOUNTED, MEDIA_MOUNTED_READ_ONLY, MEDIA_SHARED, MEDIA_BAD_REMOVAL, or MEDIA_UNMOUNTABLE.

此外,ExternalStorage 并不总是意味着外部

注意:不要被这里的“外部”这个词弄糊涂了。这个目录 最好将其视为媒体/共享存储。它是一个文件系统 可以容纳相对大量的数据,并且可以共享 所有应用程序(不强制执行权限)。传统上这是 SD 卡,但它也可以作为内置存储实现 不同于受保护的内部存储的设备,并且可以 作为文件系统安装在计算机上。

有关External Storage的更多信息

【讨论】:

  • 知道了...但是如果它没有安装在tab4中...我仍然想将它存储在设备内存中(在我的情况下为16 gb)。即使外部存储不可用,我也只想以任何方式存储它
  • 您在设备上存在 BFT 文件夹之前创建它。
  • 我尝试在设备存储上创建它。但是使用 Environment.getExternalStorageDirectory+"/BFT/" 没有找到它,因为没有像你说的那样安装 sd 卡。但是如果我想使用那个设备存储呢?
  • I tried creating that on the device storage. 告诉我们您是如何创建的?
  • 手动我的意思是(我手动创建它)。该文件夹已经存在,我只是想将其存储在其中。在 Galaxy tab4 的设备存储中,我创建了这个文件夹。但是当我尝试在其中保存文件时......应用程序崩溃
【解决方案2】:

原来 Environment.getExternalDirectory() 在某些设备上返回可移动 sd 卡路径,而在其他设备上显示设备存储(两者都是外部存储而不是内部)。

为了显示已安装的外部存储列表,我使用了此类的 getStorageList(),然后选择了一个可用的外部存储。

public class StorageUtils {

private static final String TAG = "StorageUtils";

public static class StorageInfo {

    public final String path;
    public final boolean readonly;
    public final boolean removable;     
    public final int number;

    StorageInfo(String path, boolean readonly, boolean removable, int number) {
        this.path = path;
        this.readonly = readonly;
        this.removable = removable;         
        this.number = number;
    }

    public String getDisplayName() {
        StringBuilder res = new StringBuilder();
        if (!removable) {
            res.append("Internal SD card");
        } else if (number > 1) {
            res.append("SD card " + number);
        } else {
            res.append("SD card");
        }
        if (readonly) {
            res.append(" (Read only)");
        }
        return res.toString();
    }
}

public static List<StorageInfo> getStorageList() {

    List<StorageInfo> list = new ArrayList<StorageInfo>();
    String def_path = Environment.getExternalStorageDirectory().getPath();
    boolean def_path_removable = Environment.isExternalStorageRemovable();
    String def_path_state = Environment.getExternalStorageState();
    boolean def_path_available = def_path_state.equals(Environment.MEDIA_MOUNTED)
                                || def_path_state.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
    boolean def_path_readonly = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY);

    HashSet<String> paths = new HashSet<String>();
    int cur_removable_number = 1;

    if (def_path_available) {
        paths.add(def_path);
        list.add(0, new StorageInfo(def_path, def_path_readonly, def_path_removable, def_path_removable ? cur_removable_number++ : -1));
    }

    BufferedReader buf_reader = null;
    try {
        buf_reader = new BufferedReader(new FileReader("/proc/mounts"));
        String line;
        Log.d(TAG, "/proc/mounts");
        while ((line = buf_reader.readLine()) != null) {
            Log.d(TAG, line);
            if (line.contains("vfat") || line.contains("/mnt")) {
                StringTokenizer tokens = new StringTokenizer(line, " ");
                String unused = tokens.nextToken(); //device
                String mount_point = tokens.nextToken(); //mount point
                if (paths.contains(mount_point)) {
                    continue;
                }
                unused = tokens.nextToken(); //file system
                List<String> flags = Arrays.asList(tokens.nextToken().split(",")); //flags
                boolean readonly = flags.contains("ro");

                if (line.contains("/dev/block/vold")) {
                    if (!line.contains("/mnt/secure")
                        && !line.contains("/mnt/asec")
                        && !line.contains("/mnt/obb")
                        && !line.contains("/dev/mapper")
                        && !line.contains("tmpfs")) {
                        paths.add(mount_point);
                        list.add(new StorageInfo(mount_point, readonly, true, cur_removable_number++));
                    }
                }
            }
        }

    } catch (FileNotFoundException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    } finally {
        if (buf_reader != null) {
            try {
                buf_reader.close();
            } catch (IOException ex) {}
        }
    }
    return list;
}
}

在处理具有多个外部存储挂载点的较新设备(如三星的 Galaxy 系列)时会遇到此问题。

【讨论】:

    猜你喜欢
    • 2013-12-14
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 2022-10-31
    • 2012-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多