broadcast receiver won't receive camera event
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?
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>