25

以下代码包括从服务器下载文件并将其保存在存储中,当设备具有内部存储时,它可以正常工作。
但是当我用没有内部存储的设备尝试它时,只有外部存储我得到以下异常。

java.io.filenotfoundexception 打开失败的 eacces(权限被拒绝)

public void downloadFile(String dlUrl, String dlName) {
    int count;

    HttpURLConnection con = null;
    InputStream is = null;
    FileOutputStream fos = null;

    try {
        URL url = new URL( dlUrl );
        con = (HttpURLConnection) url.openConnection();
        con.setDoInput(true);
        con.connect();

        is = url.openStream();
        String dir = Environment.getExternalStorageDirectory() + Util.DL_DIRECTORY;
        File file = new File( dir );
        if( !file.exists() ){
            file.mkdir();
        }

        Util.LOG_W(TAG, "Downloading: " + dlName + " ...");

        fos = new FileOutputStream(file + "/" +  dlName);
        byte data[] = new byte[1024];

        while( (count = is.read(data)) != -1 ){
            fos.write(data, 0, count);
        }

        Util.LOG_D(TAG, dlName + " Download Complete!");


    } catch (Exception e) {
        Util.LOG_E(TAG, "DOWNLOAD ERROR = " + e.toString() );
        bServiceDownloading = false;
    }
    finally{
        try {
            if( is != null)
                is.close();
            if( fos != null)
                fos.close();
            if( con != null)
                con.disconnect();
        } catch (Exception e) {
            Util.LOG_E(TAG, "CLOSE ERROR = " + e.toString() );
        }
    }
}

在清单文件中,我有以下内容:

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

任何建议可能是什么原因?顺便说一下Environment.getExternalStorageDirectory()返回/mnt/sdcard/file.mkdir()返回 false。

4

11 回答 11

37

在面向 Android 10 或更高版本的应用上,此属性默认为“false”。

<application android:requestLegacyExternalStorage="true" ... >
    ...
</application>
于 2019-11-08T06:01:52.440 回答
17

This problem seems to be caused by several factors.

Check#1
First add this permission in your manifest file and check if it is working:

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

</application>

  .....

Check#2:

If you are running on an emulator, check the properties to see if it has an SD card.

Check#3:

Disable file transfer from device to computer. If Enabled, the app wont be able to access the SD card.

Check#4:
If still not working, try the following:

 String dir = Environment.getExternalStorageDirectory().getAbsolutePath()

For me the following worked:
The problem is that getExternalStorageDirectory returns /mnt/sdcard whereas I need the actual path of external storage which is /mnt/sdcard-ext and there is no API in android that can get me the absolute path of removable sdcard.
My solution was to hard code the directory as follows:

String dir = "/mnt/sdcard-ext" ;

Since the application is intended to work only on one device, the above did the job.
If you encounter the same problem, use an file explorer application to find out the name of the external directory and hard code it.

于 2013-11-07T01:28:31.503 回答
10

使用READ_EXTERNAL_STORAGE权限从设备读取数据。

于 2013-07-09T05:40:28.623 回答
6

你在模拟器上试过吗?检查属性是否有 SD 卡。我有同样的问题,这是因为模拟器没有SD卡。检查你的有没有。

于 2013-08-28T11:52:52.733 回答
4

我有同样的问题,我通过禁用从设备到计算机的文件传输来解决它。因为如果您启用文件传输,则无法访问 sd 卡来调试应用程序。

于 2013-09-19T17:06:12.933 回答
3
try
Environment.getExternalStorageDirectory().getAbsolutePath()

并且不要忘记添加

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
于 2014-05-23T02:43:31.150 回答
2

我怀疑您正在运行 Android 6.0 Marshmallow (API 23) 或更高版本。如果是这种情况,您必须在尝试读/写外部存储之前实现运行时权限。 https://developer.android.com/training/permissions/requesting.html

于 2017-08-23T10:20:44.197 回答
1

尝试使用 mkdirs 而不是 mkdir。如果您正在创建目录路径并且父目录不存在,那么您应该使用 mkdirs。

于 2016-01-10T08:49:30.237 回答
1

我犯了非常愚蠢的错误。我已经放入了 AndroidManifest.xml

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

并在java文件中添加权限,以务实的方式获得权限。但是 Manifest.permission.READ_EXTERNAL_STORAGE 有错误。请使用Manifest.permission.WRITE_EXTERNAL_STORAGE

ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
于 2018-10-03T12:19:54.563 回答
0

我有同样的问题。我正确使用了清单中的写入和读取权限,但它不起作用!解决方案非常愚蠢:在运行应用程序之前将手机从 PC 上拔下。似乎当您的手机作为“大容量存储”连接到 PC 时,应用程序无法访问外部存储。

于 2016-04-15T20:37:34.057 回答
0

首先在您的清单文件中声明权限:

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

现在在清单文件的应用程序标记的标题中:

android:requestLegacyExternalStorage="true"

现在在清单文件的标记之间为您的应用定义提供程序。作为 :

 <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_path" />
    </provider>

现在在 res 文件夹中创建一个文件夹xml ,如下所示:参考这张图片

现在创建一个 xml 文件provider_path.xml并在其中复制以下代码:

<?xml version="1.0" encoding="utf-8"?>
<path>
<external-path
    name="external_files"
    path="." />

现在在您的活动中:

String filename = null ;
URL url = null;
try {
                        url = new URL("http://websitename.com/sample.pdf");
                        filename = url.getPath();
                        filename = filename.substring(filename.lastIndexOf('/')+1);

                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
  File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"/"+filename);
                    if(file.exists()){
                        Uri uri = FileProvider.getUriForFile(context, "com.example.www"+".provider",file);
                        Intent i = new Intent(Intent.ACTION_VIEW);
                        i.setDataAndType(uri, "application/pdf");
                        i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        context.startActivity(i);
                    }
                    else {
                        //download file here
                        new AlertDialog.Builder(context)
                                .setTitle("Information")
                                .setMessage("Do you want to download this file ?")
                                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }
                                })
                                .setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url+""));
                                        request.setTitle(filename);
                                        request.setMimeType("application/pdf");
                                        request.allowScanningByMediaScanner();
                                        request.setAllowedOverMetered(true);
                                        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                                        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
                                        DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
                                        downloadManager.enqueue(request);
                                    }
                                }).show();

                    }
于 2021-12-26T19:22:57.293 回答