Android 7.0以上系统获取文件或图片拿不到正确路径,报错column-data-does-not-exist

时间:2025-01-31 11:43:28

注:本方法也可解决获取相册图片拿不到正确路径问题。

我们项目的使用场景,手机qq打开文件,选择其他打开方式,选择我们自己的应用打开,通过()获取文件地址,后来发现在Android7.0之后的版本,获取到的地址不正确,说文件不存在。日志报错column-data-does-not-exist,

经过一天的折腾,终于在网上找到了一些零碎的知识拼接成了解决办法,具体如下:

判断版本获取路径的方式,在拿到uri之后进行版本判断大于等于24(即Android7.0)用最新的获取路径方式,否则用你之前的方式,

String picPath;
if (.SDK_INT >= 24) {
    picPath = getFilePathFromURI(this,uri);
} else {
    picPath = (this,uri);
}

private String getFilePathFromURI(Context context, Uri contentUri) {
    File rootDataDir = ();
    String fileName = getFileName(contentUri);
    if (!(fileName)) {
        File copyFile = new File(rootDataDir +  + fileName + ".jpg");
        copyFile(context, contentUri, copyFile);
        return ();
    }
    return null;
}

private String getFileName(Uri uri) {
    if (uri == null) return null;
    String fileName = null;
    String path = ();
    int cut = ('/');
    if (cut != -1) {
        fileName = (cut + 1);
    }
    return () + fileName;
}

private void copyFile(Context context, Uri srcUri, File dstFile) {
    try {
        InputStream inputStream = ().openInputStream(srcUri);
        if (inputStream == null) return;
        OutputStream outputStream = new FileOutputStream(dstFile);
        copyStream(inputStream, outputStream);
        ();
        ();
    } catch (Exception e) {
        ();
    }
}

private int copyStream(InputStream input, OutputStream output) throws Exception, IOException {
    final int BUFFER_SIZE = 1024 * 2;
    byte[] buffer = new byte[BUFFER_SIZE];
    BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
    BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
    int count = 0, n = 0;
    try {
        while ((n = (buffer, 0, BUFFER_SIZE)) != -1) {
            (buffer, 0, n);
            count += n;
        }
        ();
    } finally {
        try {
            ();
        } catch (IOException e) {
        }
        try {
            ();
        } catch (IOException e) {
        }
    }
    return count;
}

RealPathFromUriUtils工具类:

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

/**
 * Created by 
 * on 2019/5/20
 */
public class RealPathFromUriUtils {
    /**
     * 根据Uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    public static String getRealPathFromUri(Context context, Uri uri) {
        int sdkVersion = .SDK_INT;
        if (sdkVersion >= 19) { // api >= 19
            return getRealPathFromUriAboveApi19(context, uri);
        } else { // api < 19
            return getRealPathFromUriBelowAPI19(context, uri);
        }
    }

    /**
     * 适配api19以下(不包括api19),根据uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    private static String getRealPathFromUriBelowAPI19(Context context, Uri uri) {
        return getDataColumn(context, uri, null, null);
    }

    /**
     * 适配api19及以上,根据uri获取图片的绝对路径
     *
     * @param context 上下文对象
     * @param uri     图片的Uri
     * @return 如果Uri对应的图片存在, 那么返回该图片的绝对路径, 否则返回null
     */
    @SuppressLint("NewApi")
    private static String getRealPathFromUriAboveApi19(Context context, Uri uri) {
        String filePath = null;
        if ((context, uri)) {
            // 如果是document类型的 uri, 则通过document id来进行处理
            String documentId = (uri);
            if (isMediaDocument(uri)) { // MediaProvider
                // 使用':'分割
                String id = (":")[1];

                String selection = ._ID + "=?";
                String[] selectionArgs = {id};
                filePath = getDataColumn(context, .EXTERNAL_CONTENT_URI, selection, selectionArgs);
            } else if (isDownloadsDocument(uri)) { // DownloadsProvider
                Uri contentUri = (("content://downloads/public_downloads"), (documentId));
                filePath = getDataColumn(context, contentUri, null, null);
            }
        } else if ("content".equalsIgnoreCase(())) {
            // 如果是 content 类型的 Uri
            filePath = getDataColumn(context, uri, null, null);
        } else if ("file".equals(())) {
            // 如果是 file 类型的 Uri,直接获取图片对应的路径
            filePath = ();
        }
        return filePath;
    }

    /**
     * 获取数据库表中的 _data 列,即返回Uri对应的文件路径
     *
     * @return
     */
    private static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
        String path = null;

        String[] projection = new String[]{};
        Cursor cursor = null;
        try {
            cursor = ().query(uri, projection, selection, selectionArgs, null);
            if (cursor != null && ()) {
                int columnIndex = (projection[0]);
                path = (columnIndex);
            }
        } catch (Exception e) {
            if (cursor != null) {
                ();
            }
        }
        return path;
    }

    /**
     * @param uri the Uri to check
     * @return Whether the Uri authority is MediaProvider
     */
    private static boolean isMediaDocument(Uri uri) {
        return "".equals(());
    }

    /**
     * @param uri the Uri to check
     * @return Whether the Uri authority is DownloadsProvider
     */
    private static boolean isDownloadsDocument(Uri uri) {
        return "".equals(());
    }
}

希望能解决你们遇到的问题。