如何从使用android 10及更高版本中的范围存储保存在外部存储中的文件名中获取URI?

问题描述

在SDK 29之前,这是找到Uri的正确方法,但现在它对于大于28的sdk将不再起作用。假设我使用如下范围存储来保存BITMAP: >

@RequiresApi(api = Build.VERSION_CODES.Q)
@NonNull
private Uri saveBitmap(@NonNull final Context context,@NonNull final Bitmap bitmap,@NonNull final Bitmap.CompressFormat format,@NonNull final String mimeType,@NonNull final String displayName,@Nullable final String subFolder) throws IOException {
    String relativeLocation = Environment.DIRECTORY_PICTURES;

    if (!TextUtils.isEmpty(subFolder)) {
        relativeLocation += File.separator + subFolder;
    }

    final ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME,displayName);
    contentValues.put(MediaStore.MediaColumns.MIME_TYPE,mimeType);
    contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH,relativeLocation);

    final ContentResolver resolver = context.getContentResolver();

    OutputStream stream = null;
    Uri uri = null;

    try {
        final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        uri = resolver.insert(contentUri,contentValues);

        if (uri == null) {
            throw new IOException("Failed to create new MediaStore record.");
        }

        stream = resolver.openOutputStream(uri);

        if (stream == null) {
            throw new IOException("Failed to get output stream.");
        }

        if (!bitmap.compress(format,95,stream)) {
            throw new IOException("Failed to save bitmap.");
        }

        return uri;
    } catch (IOException e) {
        if (uri != null) {
            // Don't leave an orphan entry in the MediaStore
            resolver.delete(uri,null,null);
        }

        throw e;
    } finally {
        if (stream != null) {
            stream.close();
        }
    }
}

此代码适用于SDK 但是,如何使用文件名获取URI(该文件名保存在SDK版本29及更高版本的外部存储器中?)

private String getFilePathUri(String enteredFileName) {

    String file_uri_string = Environment.getExternalStorageDirectory() + "/"
            + AppConstants.APP_FOLDER + "/" + enteredFileName + ".jpg";
    AppUtils.showLog(TAG,file_uri_string + "");
    return file_uri_string;

}

解决方法

Android 10及更高版本::此处uri根据给定的displayName给出了file_id。

/**
 * Returns the Uri which can be used to delete/work with images in the photo gallery.
 * @param displayName Path to IMAGE on SD card
 * @return Uri in the format of... content://media/external/images/media/[NUMBER]
 */
private Uri getUriFromPath(String displayName) {
    long photoId;
    Uri photoUri = MediaStore.Images.Media.getContentUri("external");

    String[] projection = {MediaStore.Images.ImageColumns._ID};
    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = getContentResolver().query(photoUri,projection,MediaStore.Images.ImageColumns.DISPLAY_NAME + " LIKE ?",new String[] { displayName },null);
    assert cursor != null;
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    photoId = cursor.getLong(columnIndex);

    cursor.close();
    return Uri.parse(photoUri.toString() + "/" + photoId);
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...