web-dev-qa-db-fra.com

IllegalArgumentException: la colonne '_data' n'existe pas

Dans Nougat, cette fonction ne fonctionne pas.

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();
        }
    }
}

Journal d'accident:

Java.lang.RuntimeException: Unable to start activity ComponentInfo{class path}: Java.lang.IllegalArgumentException: column '_data' does not exist
   at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2659)
   at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2724)
   at Android.app.ActivityThread.-wrap12(ActivityThread.Java)
   at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1473)
   at Android.os.Handler.dispatchMessage(Handler.Java:102)
   at Android.os.Looper.loop(Looper.Java:154)
   at Android.app.ActivityThread.main(ActivityThread.Java:6123)
   at Java.lang.reflect.Method.invoke(Method.Java)
   at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:867)
   at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:757)
Caused by Java.lang.IllegalArgumentException: column '_data' does not exist
   at Android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.Java:333)
   at Android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.Java:87)
   at com.package.SaveImageActivity.getRealPathFromURI()
   at com.package.SaveImageActivity.onCreate()
   at Android.app.Activity.performCreate(Activity.Java:6672)
   at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1140)
   at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2612)
   at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2724)
   at Android.app.ActivityThread.-wrap12(ActivityThread.Java)
   at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1473)
   at Android.os.Handler.dispatchMessage(Handler.Java:102)
   at Android.os.Looper.loop(Looper.Java:154)
   at Android.app.ActivityThread.main(ActivityThread.Java:6123)
   at Java.lang.reflect.Method.invoke(Method.Java)
   at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:867)
   at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:757)

Cette fonction fonctionne correctement sur les appareils antérieurs à Android N. Je lis l'article fichier: // Le schéma n'est plus autorisé à être associé à Intent sur targetSdkVersion 24 (Android Nougat) . Mais n'a pas pu trouver de solution. Alors s'il vous plaît aider.

17
vidha

Cette fonction fonctionne correctement dans les appareils antérieurs à Android N

Cela fonctionne pour très peu de valeurs Uri, peut ne pas avoir de résultat (par exemple, pour les éléments indexés par MediaStore qui ne sont pas des fichiers locaux) et peut ne pas avoir de résultat utilisable (par exemple, pour des fichiers stockés sur un support amovible).

Alors s'il vous plaît aider.

Utilisez une ContentResolver et openInputStream() pour obtenir une InputStream sur le contenu identifié par la Uri. Idéalement, utilisez ce flux directement, quel que soit ce que vous essayez de faire. Ou bien, utilisez cette InputStream et une certaine FileOutputStream sur un fichier que vous contrôlez pour créer une copie du contenu, puis utilisez ce fichier.

24
CommonsWare

Conformément à la réponse donnée par CommonsWare, le code de solution est le suivant:

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();
    }
}

J'espère que ceci vous aide.

L'origine de IOUtils.copy provient de ce site: https://www.developerfeed.com/copy-bytes-inputstream-outputstream-Android/ (Il faudra peut-être un peu changer l'exception, mais cela fonctionne au besoin)

29
vidha

@Redturbo Je ne peux pas écrire de commentaire, j'écris ici

IOUtils.copyStream(inputStream, outputStream);

TEMP_DIR_PATH - N'importe quel chemin de répertoire, quelque chose comme ça

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

// Le code suivant fonctionne sous 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();
}
0
satyawan hajare