broadcast receiver won't receive camera event

22,163

Solution 1

I solved this but by using a different method. Instead of using a broadcast receiver I set up a fileobserver on separate folders that the camera saved to. It's not as practical as the other way, but it still works fine. Here's how I set it up:

FileObserver observer = new FileObserver(android.os.Environment.getExternalStorageDirectory().toString() + "/DCIM/100MEDIA") { // set up a file observer to watch this directory on sd card
            @Override
        public void onEvent(int event, String file) {
            if(event == FileObserver.CREATE && !file.equals(".probe")){ // check if its a "create" and not equal to .probe because thats created every time camera is launched
                Log.d(TAG, "File created [" + android.os.Environment.getExternalStorageDirectory().toString() + "/DCIM/100MEDIA/" + file + "]");
                fileSaved = "New photo Saved: " + file;
            }
        }
    };
    observer.startWatching(); // start the observer

Solution 2

I sure this way works 100% . I tested carefully.

Register your broadcast receiver in AndroidManifest. Most of answers above miss "category android:name="android.intent.category.DEFAULT" . BroadcastReceiver can't start without this

  <receiver
    android:name=".CameraReciver"
    android:enabled="true" >
        <intent-filter>
            <action android:name="com.android.camera.NEW_PICTURE" />
            <action android:name="android.hardware.action.NEW_PICTURE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />

        </intent-filter>
    </receiver>

And finally, you create a class named "CameraReciver.java" extend from BroadcastReceiver and this my code :

public class CameraReciver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub
    Log.i("INFO", "Enter BroadcastReceiver");



Cursor cursor = context.getContentResolver().query(intent.getData(),
                null, null, null, null);
        cursor.moveToFirst();
        String image_path = cursor.getString(cursor.getColumnIndex("_data"));
        Toast.makeText(context, "New Photo is Saved as : " + image_path, 1000)
                .show();



}

After that, deploy your project to Emulator ( I use genymotion),of course nothing happened because your BroadCastReceiver works without GUI. Let you open camera app, and click capture button. If everything OK, you'll get a toast with content like "New Photo is Saved as : storage/emulated/0/DCIM/Camera/IMG_20140308.jpg". Let enjoy ^_^

Thanks "tanay khandelwal" (answered above) for how to get the path of new Photo captured by camera ^_^

Hope to help everyone

Solution 3

you should check out here: ImageTableObserver and here PicasaPhotoUploader how they do it.

Basically, they have an observer for Media.EXTERNAL_CONTENT_URI that will notify of whatever happens on the SD card, then in the Observer, they check if the data returned is a photo.

camera = new ImageTableObserver(new Handler(), this, queue);
getContentResolver().registerContentObserver(Media.EXTERNAL_CONTENT_URI, true, camera);

At least this way you don't have to hardcode the directory.

Solution 4

Hello friends I was also trying to implement some task on capture event and after studying and working on it I prepared this code which is working fine so it may help you

first create a receiver for your event say CameraEventReciver and in that you can implement your code I m also giving you the path of the new image so it will be more useful to you for your code

    public class CameraEventReciver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    Cursor cursor = context.getContentResolver().query(intent.getData(),      null,null, null, null);
    cursor.moveToFirst();
    String image_path = cursor.getString(cursor.getColumnIndex("_data"));
    Toast.makeText(context, "New Photo is Saved as : -" + image_path, 1000).show();
      }
    }

And in Android Manifest you just have to take some permissions and register your reciever with intent filter and appropriate action for image capture also make your receiver android enabled

  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.CAMERA" />

   <receiver
        android:name="com.android.application.CameraEventReciver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="com.android.camera.NEW_PICTURE" />
            <data android:mimeType="image/*" />
        </intent-filter>
    </receiver>
Share:
22,163
Admin
Author by

Admin

Updated on July 09, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to make an app that detects when a user takes a photo. I set up a broadcast receiver class and registered it in the manifest file by:

    <receiver android:name="photoReceiver" >
      <intent-filter>
        <action android:name="com.android.camera.NEW_PICTURE"/>
          <data android:mimeType="image/*"/>
     </intent-filter>
    </receiver>
    

    No matter what I try to do the program won't receive the broadcast. Here is my receiver class:

    public class photoReceiver extends BroadcastReceiver {
      private static final String TAG = "photoReceiver";
    
    @Override
    public void onReceive(Context context, Intent intent) {
        CharSequence text = "caught it";
        int duration = Toast.LENGTH_LONG;
        Log.d(TAG, "Received new photo");
    
        Toast toast = Toast.makeText(context, text, duration);
        toast.show();
     }
    }
    

    If I remove the mimeType line in the manifest and in my activity I send my own broadcast using

    Intent intent = new Intent("com.android.camera.NEW_PICTURE");
    sendBroadcast(intent);
    

    then I successfully receive the broadcast and can see the log and toast window. Am I approaching this the right way? Is there any thing that I need to add?

  • techi.services
    techi.services over 13 years
    nice! good to see someone who can think for themselves ;D. I was looking at the camera source and a method storeImage in the ImageCapture class is responsible for firing of that intent. That method only fires the intent if !mIsImageCaptureIntent. I didn't look further but I would have thought that means, do the following if the image capture did not occur due to an intent. Not sure how you are taking a picture and whether the camera app uses an intent to take a picture but food for thought.
  • AlikElzin-kilaka
    AlikElzin-kilaka almost 12 years
    The problem with this solution is that the app must be running in the background all the time in order to observe the filesystem. Major problem and not playing nice.
  • gonzobrains
    gonzobrains about 11 years
    Can you use this solution to monitor multiple folders or must you create a separate FileObserver for each folder you wish to observe?
  • Ruzard
    Ruzard almost 11 years
    You have to create an observer for every folder you want to monitor.
  • Snake
    Snake over 10 years
    2 years late to the party, but I tried the solution given by Tanay below and it actually works on image capture! Any objections to why I shouldn't use it?
  • Amit Jayaswal
    Amit Jayaswal almost 10 years
    I tried it, but it didn't helped me. I also asked the question about this. Here is my work. stackoverflow.com/questions/24989221/…
  • Amit Jayaswal
    Amit Jayaswal almost 10 years
    I tried it, but not working for me ... Here is my question which I asked, please help me. stackoverflow.com/questions/24989221/…
  • Shrikant
    Shrikant over 8 years
    Above code works perfect for photos captured, any idea how we can get receiver for videos captured?
  • Harshit Gupta
    Harshit Gupta about 8 years
    I am using camera in my app. will I get toast if the user has taken the picture( and has been taken to Save/Discard screen)?
  • Ujjwal
    Ujjwal about 7 years
    From android 7.0, this has stopped working :( . Is there any workaround??