簡體   English   中英

如何從android pie中的內容uri獲取文件路徑

[英]How to get file path from content uri in android pie

我正在嘗試使用改造 2.0 上傳圖像。 onActivityResult中獲取 uri 后,我試圖從 uri 中獲取路徑,它給出了 null。 相同的代碼在棒棒糖之前的設備中完美運行。

String[] filePathColumn = { MediaStore.Image.Media.DATA };
Cursor cursor = context.getContentResolver().query(inputUri,
                filePathColumn, null, null, null);
if (cursor != null) {
   cursor.moveToFirst();
   int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
   String filePath = cursor.getString(columnIndex);
   cursor.close();
// filePath is always null
   if (filePath != null && !filePath.isEmpty()) {
       file = new File(filePath);
   }
}

這是完全有效的代碼,用於從使用所有api的內容提供商處拍攝最后一張照片:

      public ArrayList<String> getNewPicturesUri(JobParameters parameters) {
    ArrayList<String> newPictures = new ArrayList<>();

    if (parameters.getTriggeredContentAuthorities() != null) {
        if (parameters.getTriggeredContentUris() != null) {
            ArrayList<String> ids = new ArrayList<>();
            for (Uri uri : parameters.getTriggeredContentUris()) {
                List<String> path = uri.getPathSegments();
                if (path != null && path.size() ==
                        Media.EXTERNAL_CONTENT_URI.getPathSegments().size() + 1) {
                    ids.add(path.get(path.size() - 1));
                }
            }

            if (ids.size() > 0) {
                StringBuilder selection = new StringBuilder();
                for (int i = 0; i < ids.size(); i++) {
                    if (selection.length() > 0) {
                        selection.append(" OR ");
                    }
                    selection.append(MediaStore.Images.ImageColumns._ID);
                    selection.append("='");
                    selection.append(ids.get(i));
                    selection.append("'");
                }

                Cursor cursor = null;
                try {
                    String[] projection = new String[]{
                            MediaStore.Images.ImageColumns._ID,
                            MediaStore.Images.ImageColumns.DATA};

                    cursor = getContentResolver().query(
                            Media.EXTERNAL_CONTENT_URI,
                            projection, selection.toString(), null, null);

                    if (cursor != null) {
                        while (cursor.moveToNext()) {
                            newPictures.add(cursor.getString(PROJECTION_DATA));
                        }
                    }
                } catch (SecurityException exception) {
                    FirebaseCrash.report(exception);
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                }
            }
        }
    }
    return newPictures;
}

這可能會有所幫助

import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.webkit.MimeTypeMap
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale.getDefault

/**
 * This class will create a temporary file in the cache if need.
 *
 * When the uri already have `file://` schema we don't need to create a new file.
 * The temporary file will always override a previous one, saving memory.
 * Using the cache memory(context.cacheDir) we guarantee to not leak memory
 *
 * @param context used to access Android APIs, like content resolve, it is your activity/fragment.
 * @param uri the URI to load the image from.
 * @param uniqueName If true, make each image cropped have a different file name, this could cause
 * memory issues, use wisely.
 *
 * @return string value of the File path.
 */
 fun getFilePathFromUri(context: Context, uri: Uri, uniqueName: Boolean): String =
    if (uri.path?.contains("file://") == true) uri.path!!
    else getFileFromContentUri(context, uri, uniqueName).path

private fun getFileFromContentUri(context: Context, contentUri: Uri, uniqueName: Boolean): File {
    // Preparing Temp file name
    val fileExtension = getFileExtension(context, contentUri) ?: ""
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", getDefault()).format(Date())
    val fileName = ("temp_file_" + if (uniqueName) timeStamp else "") + ".$fileExtension"
    // Creating Temp file
    val tempFile = File(context.cacheDir, fileName)
    tempFile.createNewFile()
    // Initialize streams
    var oStream: FileOutputStream? = null
    var inputStream: InputStream? = null

    try {
        oStream = FileOutputStream(tempFile)
        inputStream = context.contentResolver.openInputStream(contentUri)

        inputStream?.let { copy(inputStream, oStream) }
        oStream.flush()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        // Close streams
        inputStream?.close()
        oStream?.close()
    }

    return tempFile
}

private fun getFileExtension(context: Context, uri: Uri): String? =
    if (uri.scheme == ContentResolver.SCHEME_CONTENT)
        MimeTypeMap.getSingleton().getExtensionFromMimeType(context.contentResolver.getType(uri))
    else uri.path?.let { MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(File(it)).toString()) }

@Throws(IOException::class)
private fun copy(source: InputStream, target: OutputStream) {
    val buf = ByteArray(8192)
    var length: Int
    while (source.read(buf).also { length = it } > 0) {
        target.write(buf, 0, length)
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM