IllegalArgumentException:列'_data'不存在

时间:2017-02-28 12:08:07

标签: android android-7.0-nougat android-7.1-nougat

在Nougat中,此功能无效。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:fab="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Background -->
    <ImageView
        android:id="@+id/cover"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

    <ScrollView
        android:id="@+id/main_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingTop="240dp"
        android:scrollbars="none">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <FrameLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <android.support.v7.widget.CardView
                    android:id="@+id/cardViewId"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="16dp"
                    android:layout_marginLeft="16dp"
                    android:layout_marginRight="16dp"
                    android:layout_marginTop="32dp"
                    card_view:cardCornerRadius="2dp"
                    card_view:cardElevation="2dp"
                    card_view:cardPreventCornerOverlap="false"
                    card_view:cardUseCompatPadding="true"
                    card_view:contentPadding="16dp">

                    <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_marginTop="45dp"
                        android:orientation="vertical"></LinearLayout>
                </android.support.v7.widget.CardView>

                <android.support.v7.FloatingActionButton
                    android:id="@+id/fab"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="top|end"
                    android:layout_marginRight="32dp" />

            </FrameLayout>

            <ImageView
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_alignParentTop="true"
                android:layout_marginLeft="32dp"
                android:scaleType="center"
                tools:src="@drawable/profile" />
        </RelativeLayout>
    </ScrollView>
</FrameLayout>


String path = getRealPathFromURI(this, getIntent().getParcelableExtra(Intent.EXTRA_STREAM));

崩溃日志:

public String getRealPathFromURI(Context context, Uri contentUri) {
    Cursor cursor = null;
    try {
        String[] proj = {MediaStore.Images.Media.DATA};
        cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
        if (cursor == null) return contentUri.getPath();
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

此功能在Android N之前的设备中正常运行。我阅读了文章file:// scheme is now not allowed to be attached with Intent on targetSdkVersion 24 (Android Nougat)。但找不到任何解决方案。所以请帮忙。

4 个答案:

答案 0 :(得分:33)

根据CommonsWare给出的答案,解决方案代码为:

public static String getFilePathFromURI(Context context, Uri contentUri) {
    //copy file and send new file path 
    String fileName = getFileName(contentUri);
    if (!TextUtils.isEmpty(fileName)) {
        File copyFile = new File(TEMP_DIR_PATH + File.separator + fileName);
        copy(context, contentUri, copyFile);
        return copyFile.getAbsolutePath();
    }
    return null;
}

public static String getFileName(Uri uri) {
    if (uri == null) return null;
    String fileName = null;
    String path = uri.getPath();
    int cut = path.lastIndexOf('/');
    if (cut != -1) {
        fileName = path.substring(cut + 1);
    }
    return fileName;
}

public static void copy(Context context, Uri srcUri, File dstFile) {
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
        if (inputStream == null) return;
        OutputStream outputStream = new FileOutputStream(dstFile);
        IOUtils.copyStream(inputStream, outputStream);
        inputStream.close();
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我希望这会对你有所帮助。

IOUtils.copy的来源是来自这个网站:https://www.developerfeed.com/copy-bytes-inputstream-outputstream-android/(可能需要更改一下异常,但它可以根据需要运行)

答案 1 :(得分:26)

  

此功能在Android N之前的设备中正常运行

它适用于非常少的Uri值,可能没有结果(例如,对于由MediaStore索引但不是本地文件的内容),并且可能没有可用的结果(例如,对于可移动存储上的文件。)

  

所以请帮忙。

使用ContentResolveropenInputStream()获取InputStream标识的内容Uri。理想情况下,只需直接使用该流,无论您尝试做什么。或者,在您控制的文件上使用InputStream和一些FileOutputStream来制作内容的副本,然后使用该文件。

答案 2 :(得分:2)

@Redturbo 我不能写评论,我写在这里

IOUtils.copyStream(inputStream, outputStream);

TEMP_DIR_PATH - 您的任何目录路径,类似这样

 File rootDataDir = context.getFilesDir();
 File copyFile = new File( rootDataDir + File.separator + fileName + ".jpg");

答案 3 :(得分:2)

//以下代码在Android N中运行:

private static String getFilePathForN(Uri uri, Context context) {
    Uri returnUri = uri;
    Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
    /*
     * Get the column indexes of the data in the Cursor,
     *     * move to the first row in the Cursor, get the data,
     *     * and display it.
     * */
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
    returnCursor.moveToFirst();
    String name = (returnCursor.getString(nameIndex));
    String size = (Long.toString(returnCursor.getLong(sizeIndex)));
    File file = new File(context.getFilesDir(), name);
    try {
        InputStream inputStream = context.getContentResolver().openInputStream(uri);
        FileOutputStream outputStream = new FileOutputStream(file);
        int read = 0;
        int maxBufferSize = 1 * 1024 * 1024;
        int bytesAvailable = inputStream.available();

        //int bufferSize = 1024;
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);

        final byte[] buffers = new byte[bufferSize];
        while ((read = inputStream.read(buffers)) != -1) {
            outputStream.write(buffers, 0, read);
        }
        Log.e("File Size", "Size " + file.length());
        inputStream.close();
        outputStream.close();
        Log.e("File Path", "Path " + file.getPath());
        Log.e("File Size", "Size " + file.length());
    } catch (Exception e) {
        Log.e("Exception", e.getMessage());
    }
    return file.getPath();
}