【问题标题】:external storage not available外部存储不可用
【发布时间】:2018-01-08 10:37:01
【问题描述】:

我想创建新文件并写入/读取应用程序设置。 isExternalStorageAvailable() 返回 false 并且应该为 true。 Android 模拟器外部内存 = 200mb。

 boolean isExternalStorageAvailable() {
        String extStorageState = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(extStorageState)) {
            return true;
        }
        return false;
    }

添加了清单文件的权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (!isExternalStorageAvailable() || isExternalStorageReadOnly()) {
        saveButton.setEnabled(false);
        System.out.println("Available: "+isExternalStorageAvailable()+", ReadOnly: "+isExternalStorageReadOnly());
    }
    else {
        myExternalFile = new File(getExternalFilesDir(filepath), filename);
    }
}

【问题讨论】:

  • 我试过journaldev.com/9400/…没有成功
  • 请记住,我不熟悉 Android,但 isExternalStorageAvailable() 是否有可能返回 false,因为它根本不存在并且 不是该程序没有使用它的权限?我的建议是验证 Environment.getExternalStorageState() 返回的外部存储类型。
  • 这里可以看到代码+模拟器+logcat:i.imgur.com/Gn5LlOn.png
  • 请不要通过破坏您的帖子为人们增加工作量。通过在 Stack Exchange (SE) 网络上发帖,您已在 CC BY-SA 3.0 license 下授予 SE 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 SE 政策,帖子的非破坏版本是分发的版本。因此,任何破坏行为都将被撤销。

标签: java android file emulation external


【解决方案1】:

要获取所有外部存储路径,可以使用:

    File[] extSDCardPaths = null;
    try {
        extSDCardPaths = ContextCompat.getExternalFilesDirs(ctx, null);
    } catch (Exception e) {
        // handle
    }

    for (File f : extSDCardPaths) {
        if (Environment.isExternalStorageRemovable(f)) {
            // check if anything found
        }
    }

如果extSDCardPaths 返回某些内容,则可以使用 ext 存储。

以上仅适用于 > 4.4(KitKat)

以下 hack 可用作较低操作系统版本的后备:

String[] fallback = {"/storage/sdcard1/", "/mnt/ext_card/", "/mnt/extSdCard/", "/storage/extsdcard/",
            "/mnt/extsdcard/", "/storage/extSdCard/", "/mnt/external_sd", "/storage/MicroSD/",
            "/storage/external_SD/", "/storage/ext_sd/", "/storage/removable/sdcard1/", "/mnt/sdcard/external_sd/",
            "/storage/ext_sd/", "/mnt/emmc/", "/data/sdext/", "/sdcard/sd/"};

   for (String path : fallback) {
        if (new File(path).exists()) {
                // found an ext. dir
            break;
        }
   }

【讨论】:

【解决方案2】:

如果您的应用程序以棉花糖或更高版本为目标并运行,您必须获得对外部存储的读/写权限,您必须在清单中声明权限后明确向用户请求权限。

  1. 确保你的清单中有这个:<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  2. 明确检查权限。如果未提供,请索取:

    public void checkPermissionReadStorage(Activity activity){
             if (ContextCompat.checkSelfPermission(activity,      
    Manifest.permission.READ_EXTERNAL_STORAGE) !=     
    PackageManager.PERMISSION_GRANTED) {
    
            // Should we show an explanation?
            if (ActivityCompat.shouldShowRequestPermissionRationale(activity,
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {
    
                // Show an expanation to the user *asynchronously* -- don't block
                // this thread waiting for the user's response! After the user
                // sees the explanation, try again to request the permission.
    
            } else {
    
                // No explanation needed, we can request the permission.
    
                ActivityCompat.requestPermissions(activity,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        MY_PERMISSIONS_REQUEST_READ_STORAGE);
    
                // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
                // app-defined int constant. The callback method gets the
                // result of the request.
            }
        }
    }
    
  3. 接收权限响应:

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case PermissionManager.MY_PERMISSIONS_REQUEST_READ_STORAGE:
                //premission to read storage
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
    
                    // Permission granted. Call your storage related code here
    
                } else {
    
                    // permission denied.
                    // Handle permission failed here.
                }
                return;
    
    
            // other 'case' lines to check for other
            // permissions this app might request
        }
    }
    

代码取自here

【讨论】:

  • 我有 SDK 版本 15,所以应该可以在没有此代码的情况下工作。但无论如何我很快就会测试。
  • 如果您不针对 api 23 或更高版本,则使用上述方法是无用的,因为一旦安装应用程序就会授予权限。可能是您遇到了不同的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
相关资源
最近更新 更多