我正在尝试将图像从“下载”文件夹加载到imageView,然后使用改造版本将其上传。但是,我得到java.lang.SecurityException: Permission Denial: reading com.android.providers.downloads.DownloadProvider uri content://downloads/all_downloads/124 from pid=24654,uid=10177 requires android.permission.accESS_ALL_DOWNLOADS,or granturiPermission()
。我尝试从其他文件夹加载图像,但它们工作正常。我最初收到NullPonterException,发现我必须用 content:// downloads / all_downloads 替换 content:// downloads / public_downloads ,现在我收到了此错误。这是到目前为止我尝试过的代码:
预先感谢
FileUtils.java
public class FileUtils {
String getPathFromUri(final Context context,final Uri uri) {
String path = getPathFromLocalUri(context,uri);
if (path == null) {
path = getPathFromRemoteUri(context,uri);
}
return path;
}
@SuppressLint("NewApi")
public static String getPathFromLocalUri(final Context context,final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
if (isKitKat && DocumentsContract.isDocumenturi(context,uri)) {
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
} else if (isDownloadsDocument(uri)) {
Log.d("isDownload","Yes");
final String id = DocumentsContract.getDocumentId(uri);
if (!TextUtils.isEmpty(id)) {
try {
final Uri contenturi =
Contenturis.withAppendedId(
Uri.parse("content://downloads/all_downloads"),Long.valueOf(id));
return getDataColumn(context,contenturi,null,null);
} catch (NumberFormatException e) {
return null;
}
}
} else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contenturi = null;
if ("image".equals(type)) {
contenturi = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contenturi = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contenturi = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[] {split[1]};
return getDataColumn(context,selection,selectionArgs);
}
} else if ("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
return getDataColumn(context,uri,null);
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
private static String getDataColumn(
Context context,Uri uri,String selection,String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getcontentResolver().query(uri,projection,selectionArgs,null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getcolumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return null;
}
private static String getPathFromRemoteUri(final Context context,final Uri uri) {
// The code below is why Java now has try-with-resources and the Files utility.
File file = null;
InputStream inputStream = null;
OutputStream outputStream = null;
boolean success = false;
try {
inputStream = context.getcontentResolver().openInputStream(uri);
file = File.createTempFile("image_picker","jpg",context.getcacheDir());
outputStream = new FileOutputStream(file);
if (inputStream != null) {
copy(inputStream,outputStream);
success = true;
}
} catch (IOException ignored) {
} finally {
try {
if (inputStream != null) inputStream.close();
} catch (IOException ignored) {
}
try {
if (outputStream != null) outputStream.close();
} catch (IOException ignored) {
// If closing the output stream fails,we cannot be sure that the
// target file was written in full. Flushing the stream merely moves
// the bytes into the OS,not necessarily to the file.
success = false;
}
}
return success ? file.getPath() : null;
}
private static void copy(InputStream in,OutputStream out) throws IOException {
final byte[] buffer = new byte[4 * 1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer,bytesRead);
}
out.flush();
}
private static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getauthority());
}
private static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getauthority());
}
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getauthority());
}
private static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getauthority());
}
}
pickImage方法:
//Gallery
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void openGallery() {
if (ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
activityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},READ_STORAGE_PERMISSION);
} else {
Intent intent = new Intent(Intent.actION_OPEN_DOCUMENT);
intent.setflags(Intent.flaG_GRANT_READ_URI_PERMISSION);
intent.setType("image/*");
startactivityForResult(intent,GALLERY_CODE);
}
}
清单:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.accESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.accESS_ALL_DOWNLOADS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsrtl="true"
android:theme="@style/Apptheme"
android:usesCleartextTraffic="true">
.......
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationid}"
android:exported="false"
android:granturiPermissions="true"
tools:replace="android:authorities">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"
tools:replace="android:resource" />
</provider>
</application>
provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>