ContentResolver doesn't contain just created image in an immediate query after creation of file

删除回忆录丶 提交于 2019-11-29 23:54:40

问题


I'm using this code to copy an image using documentFile.createFile()

private void newcopyFile(File fileInput, String outputParentPath,
                            String mimeType, String newFileName) {

        DocumentFile documentFileGoal = DocumentFile.fromTreeUri(this, treeUri);

        String[] parts = outputParentPath.split("\\/");
        for (int i = 3; i < parts.length; i++) {
            if (documentFileGoal != null) {
                documentFileGoal = documentFileGoal.findFile(parts[i]);
            }
        }
        if (documentFileGoal == null) {
            Toast.makeText(MainActivity.this, "Directory not found", Toast.LENGTH_SHORT).show();
            return;
        }

        DocumentFile documentFileNewFile = documentFileGoal.createFile(mimeType, newFileName);

        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            outputStream = getContentResolver().openOutputStream(documentFileNewFile.getUri());
            inputStream = new FileInputStream(fileInput);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            if (outputStream != null) {
                byte[] buffer = new byte[1024];
                int read;
                if (inputStream != null) {
                    while ((read = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, read);
                    }
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                inputStream = null;
                outputStream.flush();
                outputStream.close();
                outputStream = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

And this is how I query ContentResolver after creating image, to immediately refresh my image gallery with the result of query which should contain info of newly created image.

cursorPhotos = MainActivity.this.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    projectionsImages,
                    null,
                    null,
                    MediaStore.Images.Media.DATE_TAKEN + " DESC"
            );

But immediate query couldn't find newly created image. And if I run query again after a moment, newly created image is there in the result.

It seems providing information for newly created image takes time for ContentResolver(if ContentResolver is in charge for it) as it would be running in background while I run immediate query.

Is there any method or listener to know when the newly created image is registered by ContentResolver?


回答1:


You could use this or this is how I've implemented a listener(observer) to ContentResolver changes, using ContentObserver to know when is the appropriate time to run query for getting newly created image from ContentResolver.

First create ContentObserver Class:

This class as its name tells us, observes any content changes in our desired Uri.

class MyObserver extends ContentObserver {
    public MyObserver(android.os.Handler handler) {
        super(handler);
    }

    @Override
    public void onChange(boolean selfChange) {
        this.onChange(selfChange, null);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        //(SDK>=16)
        // do s.th.
        // depending on the handler you might be on the UI
        // thread, so be cautious!

        // This is my AsyncTask that queries ContentResolver which now
        // is aware of newly created media file.
        // You implement your own query here in whatever way you like
        // This query will contain info for newly created image
        asyncTaskGetPhotosVideos = new AsyncTaskGetPhotosVideos();
        asyncTaskGetPhotosVideos.execute();
    }
}

and at the end of your copy method you could set ContentObserver to your ContentResolver on specific Uri.

 getContentResolver().registerContentObserver(
         MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
         true,
         myObserver);

and don't forget to unregister your observer otherwise you will face memory leak. I would prefer to to it at the end of my AsyncTask (onPostExecute).

getContentResolver().unregisterContentObserver(myObserver);

You could choose to have a ContentObserver on your desired Uri through your entire app lifecycle to get notify if medias got changed, deleted or inserted from outside or within inside your app.

For this approach you could register your observer in the onResume() lifecycle method and unregister it in the onPause() method.




回答2:


Sorry i posted wrong code

When you add files to Android’s filesystem these files are not picked up by the MedaScanner automatically. But often they should be.

So to add a file to content provider manually

So use this code :-

Intent intent =
      new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
sendBroadcast(intent);

For more methods of doing this and for reference visit this site:-

http://www.grokkingandroid.com/adding-files-to-androids-media-library-using-the-mediascanner/



来源:https://stackoverflow.com/questions/38554843/contentresolver-doesnt-contain-just-created-image-in-an-immediate-query-after-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!