setDestinationInExternalFilesDir() 工作 setDestinationInExternalPublicDir() 不
setDestinationInExternalFilesDir() works setDestinationInExternalPublicDir() doesn't
我正在尝试从 url 下载文件并将其保存到常规下载文件夹。 setDestinationInExternalPublicDir()
不起作用,也不会抛出任何异常。但是 setDestinationInExternalFilesDir()
工作正常。知道是什么原因吗?
我的代码是这样的:
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimeType,
long contentLength) {
if (url.startsWith("data:")) {
save(url);
return;
}
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType(mimeType);
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.addRequestHeader("User-Agent", userAgent);
request.setDescription(getResources().getString(R.string.downloadingMsg));
String filename = URLUtil.guessFileName(url, contentDisposition, mimeType);
request.setTitle(filename);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//DOESN'T WORK
request.setDestinationInExternalPublicDir("Downloads", filename);
//WORKS
//request.setDestinationInExternalFilesDir(getApplicationContext(), "Downloads", filename);
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), R.string.downloadingMsg, Toast.LENGTH_LONG).show();
}
});
和清单文件:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我从 url 下载图像的解决方案。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.CalendarContract;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.UUID;
public class DownloadImage extends AsyncTask<String, Void, Bitmap> implements MediaScannerConnection.MediaScannerConnectionClient {
private Context context;
private File mFile;
private MediaScannerConnection mMs;
public DownloadImage(Context context) {
this.context = context;
}
private Bitmap downloadImageBitmap(String sUrl) {
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap
inputStream.close();
} catch (Exception e) {
Log.d(TAG, "Exception 1, Something went wrong!");
e.printStackTrace();
}
return bitmap;
}
@Override
protected Bitmap doInBackground(String... params) {
return downloadImageBitmap(params[0]);
}
protected void onPostExecute(Bitmap result) {
String fileName = UUID.randomUUID().toString();
getFilePath(fileName + ".jpg", result, context);
}
public void getFilePath(String name, Bitmap bitmap2, Context context) {
Bitmap bitmap = bitmap2;
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();//Downloads folder path
File myDir = new File(root);
myDir.mkdirs();
String fname = name.replaceAll("-", "");
File file = new File(myDir, fname);
if (file.exists()) {
file.delete();
}
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
Toast.makeText(context, "Error occurred", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show();
mFile = file;
mMs = new MediaScannerConnection(context, this);//finding image in gallery after download
mMs.connect();
}
@Override
public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), null);
}
@Override
public void onScanCompleted(String path, Uri uri) {
mMs.disconnect();
}
}
运行 这个 class 在 Activity:
DownloadImage downloadImage = new DownloadImage(this);
downloadImage.execute("url");
UPD1:
我认为您可以使用此代码下载文件。
所以,我终于可以让 setDestinationInExternalPublicDir() 函数正常工作了。感谢 CommonsWare。通过关注 Commonsware 的评论和回答 ,我了解到在 android 版本 6+ 上,即使在清单文件中声明了权限,也应该在运行时请求它们。你猜怎么着,我正在使用 android 7...就是这样,我得到了 permission denied 错误。
所以我在我的 onCreate()
函数中添加了这些行,它也会提示用户在运行时获得权限(最终解决了我的问题):
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
int PERMISSION_REQUEST_CODE = 1;
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
}
}
}
我正在尝试从 url 下载文件并将其保存到常规下载文件夹。 setDestinationInExternalPublicDir()
不起作用,也不会抛出任何异常。但是 setDestinationInExternalFilesDir()
工作正常。知道是什么原因吗?
我的代码是这样的:
webView.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimeType,
long contentLength) {
if (url.startsWith("data:")) {
save(url);
return;
}
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType(mimeType);
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
request.addRequestHeader("User-Agent", userAgent);
request.setDescription(getResources().getString(R.string.downloadingMsg));
String filename = URLUtil.guessFileName(url, contentDisposition, mimeType);
request.setTitle(filename);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//DOESN'T WORK
request.setDestinationInExternalPublicDir("Downloads", filename);
//WORKS
//request.setDestinationInExternalFilesDir(getApplicationContext(), "Downloads", filename);
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), R.string.downloadingMsg, Toast.LENGTH_LONG).show();
}
});
和清单文件:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
我从 url 下载图像的解决方案。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.CalendarContract;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.UUID;
public class DownloadImage extends AsyncTask<String, Void, Bitmap> implements MediaScannerConnection.MediaScannerConnectionClient {
private Context context;
private File mFile;
private MediaScannerConnection mMs;
public DownloadImage(Context context) {
this.context = context;
}
private Bitmap downloadImageBitmap(String sUrl) {
Bitmap bitmap = null;
try {
InputStream inputStream = new URL(sUrl).openStream(); // Download Image from URL
bitmap = BitmapFactory.decodeStream(inputStream); // Decode Bitmap
inputStream.close();
} catch (Exception e) {
Log.d(TAG, "Exception 1, Something went wrong!");
e.printStackTrace();
}
return bitmap;
}
@Override
protected Bitmap doInBackground(String... params) {
return downloadImageBitmap(params[0]);
}
protected void onPostExecute(Bitmap result) {
String fileName = UUID.randomUUID().toString();
getFilePath(fileName + ".jpg", result, context);
}
public void getFilePath(String name, Bitmap bitmap2, Context context) {
Bitmap bitmap = bitmap2;
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();//Downloads folder path
File myDir = new File(root);
myDir.mkdirs();
String fname = name.replaceAll("-", "");
File file = new File(myDir, fname);
if (file.exists()) {
file.delete();
}
try {
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
Toast.makeText(context, "Error occurred", Toast.LENGTH_SHORT).show();
return;
}
Toast.makeText(context, "Success", Toast.LENGTH_SHORT).show();
mFile = file;
mMs = new MediaScannerConnection(context, this);//finding image in gallery after download
mMs.connect();
}
@Override
public void onMediaScannerConnected() {
mMs.scanFile(mFile.getAbsolutePath(), null);
}
@Override
public void onScanCompleted(String path, Uri uri) {
mMs.disconnect();
}
}
运行 这个 class 在 Activity:
DownloadImage downloadImage = new DownloadImage(this);
downloadImage.execute("url");
UPD1: 我认为您可以使用此代码下载文件。
所以,我终于可以让 setDestinationInExternalPublicDir() 函数正常工作了。感谢 CommonsWare。通过关注 Commonsware 的评论和回答
所以我在我的 onCreate()
函数中添加了这些行,它也会提示用户在运行时获得权限(最终解决了我的问题):
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
int PERMISSION_REQUEST_CODE = 1;
if (ContextCompat.checkSelfPermission(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
} else {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
}
}
}