13

Background

When the user downloads a new image or captures one using the camera, the gallery app will get updated to show the new images.

I need to be notified of each new image as soon as it was created, no matter how it was created (camera, browser,...) , just as the gallery app shows.

The problem

As it turns out there is a mediaScanner Android component that is responsible for scanning all types of media files, and when it finishes, it's supposed to send an intent "MEDIA_SCANNER_FINISHED" (as shown on this example) .

So I've added the next code , hoping it will show a toast each time the user takes a photo from the camera app:

manifest:

    ...
    <receiver android:name="com.example.newgalleryimagereceivertest.MediaScannerBroadcastReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" />
            <data android:scheme="file" />
        </intent-filter>
    </receiver>
    ...

java file:

package com.example.newgalleryimagereceivertest;
...
public class MediaScannerBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {
        android.util.Log.d("AppLog", "gallery has new images");
    }

For some reason , this code doesn't work ...

The question

What's wrong with the code?

Will the broadcastReceiver ever be called after taking a photo?

What is the correct way to do it?

Do I really need to use a contentObserver and monitor its changes (using something like this), and keep the app running just for this? I really hope not...

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • I know Toast have some limitations for it to work. UI thread and activity context. So, before saying the code doesn't work. Could you make a log instead and double check `Log.d("toast", "gallery have new images");` – Budius Jan 23 '14 at 14:41
  • yes, using logs also shown it doesn't work. will now update the code here too. also found a weird thing on the manifest here that i've fixed. – android developer Jan 23 '14 at 14:49
  • It's just a guess, perhaps [`"android.hardware.action.NEW_PICTURE"`](http://developer.android.com/reference/android/hardware/Camera.html#ACTION_NEW_PICTURE) or `"com.android.camera.NEW_PICTURE"` is called instead – a.ch. Jan 28 '14 at 15:41
  • @a.ch. this will be called only by the native camera app and only from a certain API . I wish to be notified of any image that the gallery can show, and not being restricted by a specific app. third party cameras don't use this intent when a new picture is taken. – android developer Jan 28 '14 at 17:10
  • Hello,have you got the solution?. I was stuck at same point. – Amol Sawant Mar 15 '14 at 11:07
  • @AmolSawant96Kuli I found 2 possible solutions, each has its own disadvantages: contentObserver, which will require constant listening, and a polling mechanism, which will check for new content once every X minutes. all other solutions I've found will affect performance and/or memory usage too much to be used. – android developer Mar 15 '14 at 11:49
  • Thank you for replying dear, still i am finding the solution. If you will get any solution then let me know. – Amol Sawant Mar 15 '14 at 12:26
  • @AmolSawant96Kuli i've stopped searching, but if i find about it, i will post an answer here. – android developer Mar 15 '14 at 18:34
  • @AmolSawant96Kuli did you found any solution for the same ? I am stuck in similar problem https://stackoverflow.com/q/45813687/4732786 – Adarsh Sharma Aug 22 '17 at 09:41
  • @AdarshSharma I stopped handling this issue. Maybe one of the below answers can help you. – android developer Aug 23 '17 at 05:15

3 Answers3

5

ACTION_MEDIA_SCANNER_FINISHED is used for adding new directories to the gallery:

Broadcast Action: The media scanner has finished scanning a directory. The path to the scanned directory is contained in the Intent.mData field.

Constant Value: "android.intent.action.MEDIA_SCANNER_FINISHED"

You should use ACTION_MEDIA_SCANNER_SCAN_FILE, which is used to add new files - not just directories:

Broadcast Action: Request the media scanner to scan a file and add it to the media database. The path to the file is contained in the Intent.mData field.

Constant Value: "android.intent.action.MEDIA_SCANNER_SCAN_FILE"

You can test this Intent using the code discussed here.

Additionally, some have reportedly needed to include mime type and file extensions, such as:

<data android:mimeType="*/*"/>
<data android:pathPattern=".*\\.png" />
Community
  • 1
  • 1
Phil
  • 35,852
  • 23
  • 123
  • 164
  • sadly, i still get nothing. did it work for you? did you run your app, and when you take a picture using the camera, did you get an intent? – android developer Jan 29 '14 at 19:51
  • @androiddeveloper I added more to the answer regarding mime types and file extensions. Does this do the trick? – Phil Jan 29 '14 at 19:59
  • still nothing. i've also tried android:pathPattern=".*\\.jpg" and android:pathPattern=".*\\.jpeg" . i wonder if it's a regular expression or just wildcards. – android developer Jan 29 '14 at 20:07
  • I don't think these two options are as analogous as stated in the answer. As stated in the docs, _SCAN_FILE is to *request* a scan, while _SCANNER_FINISHED is to notify that the media scanner *has* finished. The _SCANNER_FINISHED broadcast notifies you that there is new data, but then you'd need to query the media store to find the new data, AFAIK. – parkerfath Mar 13 '15 at 21:56
3

You may want to look into adding these to your filter as well:

com.android.camera.NEW_PICTURE
com.android.camera.NEW_VIDEO
android.hardware.action.NEW_PICTURE
android.hardware.action.NEW_VIDEO

The android.hardware.x actions are the "official" current broadcasts, but the com.android.x ones are sent by Samsung devices and older versions of Android.

parkerfath
  • 1,648
  • 1
  • 12
  • 18
1

i think you can acheive this using the FileObserver .

as mentioned in the documentation :

Monitors files to fire an event after files are accessed or changed by by any process on the device . Each FileObserver instance monitors a single file or directory. If a directory is monitored, events will be triggered for all files and subdirectories inside the monitored directory.

but you have to keep in mind :

If a FileObserver is garbage collected, it will stop sending events. To ensure you keep receiving events, you must keep a reference to the FileObserver instance from some other live object.

Please give me some feedback . Hope That helps .

  • 1
    how would I know to which files to listen to? only files that are stored for the mediaStore should be monitored ... did you try it out? how do you monitor a specific process, and which one should it be for the mediaStore? how would you make the fileObserver observe all files from all directories, instead of a single one (it doesn't seem to be recursive) ? you would have to create an instance for every folder on the device, and also for each new one... – android developer Jan 30 '14 at 07:21
  • for example : you can listen to your pictures directory like the following : Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES); and so on for your directories . and no i havent tried it . you dont want to monitor which process created the file , you will monitor any file created by any process in the device . –  Jan 30 '14 at 07:28
  • but i don't want to monitor every single file created, as some won't get into the mediaStore (and maybe most of them). i also don't want to monitor just this single folder that you've written, since users can install apps that put image files (like third party cameras) on other folder , that still make the gallery app aware of those files... – android developer Jan 30 '14 at 07:33
  • cant you monitor the SD card for instance ? i dont know if what i am saying is correct or not . –  Jan 30 '14 at 07:36
  • i've read about it now. it doesn't seem to be able to work recursively - you would have to create a lot of FileObservers yourself - one for each directory , and even for new ones... for each file you would have to check if it got into the mediaStore... i think it can be an overkill... – android developer Jan 30 '14 at 07:41
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46410/discussion-between-amrola-and-android-developer) –  Jan 30 '14 at 07:51
  • sorry i don't have time to chat. this question is written while i work at the office... – android developer Jan 30 '14 at 09:10
  • I think the problem with this approach is that you'd need to have your app running at all times. One of the benefits of a broadcast is that it would wake up your app if necessary. – parkerfath Mar 13 '15 at 21:54
  • in case you need monitor the sub directories, you can use this RecursiveFileObserver class https://collimator.googlecode.com/svn-history/r22/trunk/src/com/toraleap/collimator/util/RecursiveFileObserver.java – HendraWD Mar 03 '16 at 08:54
  • @parkerfath indeed, but can live in the background with service too. I can achieve it with create a background service to store reference to the FileObserver, so the FileObserver will not garbage collected. And on the background service, i use START_STICKY flag onStartCommand, so it will be recreated if killed by the android system, like when device on low memory – HendraWD Mar 03 '16 at 08:58