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?
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
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
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.
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>
The issue is that, you've put the constant name with package into apostrophes (as string). The actual string constant has different value.
Related
Can anybody help me please? My question is that how to to display popup message on camera image capture using broadcast receiver.
I have register Receiver but it is not working.
Receiver class:
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,Toast.LENGTH_LONG).show();
}
}
Manifest file:
<receiver
android:name="com.example.abdullahnawaz.mycamera.CameraReciver"
android:enabled="true" >
<intent-filter>
<action android:name="com.android.camera.NEW_PICTURE" />
<data android:mimeType="image/*" />
<action android:name="android.intent.action.CAMERA_BUTTON" />
</intent-filter>
</receiver>
Starting from Android 7.0, please use JobInfo.Builder.addTriggerContentUri().
For older devices, you can listen to the ACTION_NEW_PICTURE or ACTION_NEW_VIDEO broadcast. These broadcasts are no long sent on 7.0 and above.
I am writing a Gallery like app.
I want to be notified when an image is copied to device via MTP.
I tried to register a broadcast receiver to listen for media scanner finished action, but it never got called. I tried to both register in AndroidManifest.xml or register in Java code, neither works.
<receiver android:name="com.robin.huangwei.omnigif.content.MediaScannerReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.MEDIA_SCANNER_FINISHED" />
<data android:scheme="file" />
</intent-filter>
</receiver>
public class MediaScannerReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("-----", "Scan finished, new item: " + intent);
}
}
or using JAVA code as below
mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("-----", "Scan finished, new item: " + intent);
}
};
IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_FINISHED);
filter.addDataScheme("file");
registerReceiver(mReceiver, filter);
None of the above works.
Whats wrong with my code? I can see every time a new image is copied, it could show in Gallery App. It might be using content observer to watch the media store database, which I don't want to.
I just want to be notified when a new image is added into the device storage via MTP. Since it is added into media store, which must be done by media scanner, why cannot my app capture the broadcast intent? If this is not even correct, I want to know the answer I post as the title.
I am trying to "listen" when a user take picture using the default camera app. I used the broadcast receiver solution as below
Manifest:
<receiver
android:name=".CameraEventReceiver"
android:enabled="true" >
<intent-filter>
<action android:name="com.android.camera.NEW_PICTURE" />
<action android:name="android.hardware.action.NEW_PICTURE" />
<data android:mimeType="image/*" />
</intent-filter>
</receiver>
The receiver:
public class CameraEventReceiver 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, Toast.LENGTH_SHORT).show();
Intent i = new Intent(context, MyAct.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
The problem is that the event is fired multiple times (twice). My breakpoint at where context.startActivity(i) is called twice and both with the action android.hardware.action.NEW_PICTURE.
Any reason why this is happening or how to prevent it?
Thank you
The stock Camera app on KitKat send both android.hardware.action.NEW_PICTURE and com.android.camera.NEW_PICTURE broadcasts (don't know for older versions), that may be why your receiver is notified twice.
If your app is only for ICS+ you can remove com.android.camera.NEW_PICTURE from your intent filter as it is not documented.
If you still want to handle this, your receiver should implement some logic to know the intent has already been handled for the data it receives. This logic depends on your application and what you do with the received data.
I have two apps that I made, and am trying to send an intent from one to the other but the intent is never getting to the onReceive() however this problem is only one way. The first app can send to the second but the second cannot send back info. I am using a different intent action to send from the second to the first but otherwise they are identical. Any ideas on why this might not be working? I have tried everything I can think of and read most of the posts I could find on here and to no avail.
It's not crashing or giving me any indications as to what is happening in the logcat it's just doing nothing.
send function
private void sendFinishLog(String ID, String Cond)
{
Log.d("me", "send finish log");
Intent logIntent = new Intent();
logIntent.putExtra("ID", ID);
logIntent.putExtra("Cond", Cond);
logIntent.setAction("com.me.intent.finishlog");
Log.d("me","logIntent : " + logIntent.toString()
+logIntent.getExtras().toString());
sendBroadcast(logIntent);
}
receive class
public class LogReceiver extends BroadcastReceiver {
public static ArrayList<LogDataHolder> logData = new ArrayList<LogDataHolder>();
private boolean found;
static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
private static String lasttime;
private static String now = "Boot time";
#Override
public void onReceive(Context cont, Intent logIntent)
{
Log.d("me","On receive");
etc.....
}
Receiving app manifest
<!-- for receiving logs -->
<receiver
android:name = "LogReceiver"
android:enabled="true">
<intent_filter>
<action android:name="com.me.intent.finishlog" />
</intent_filter>
</receiver>
something like:
public void onResume() {
IntentFilter filter = new IntentFilter();
getActivity().registerReceiver(mLogReceiver,filter);
}
and for un-register:
public void onPause() {
getActivity().unregsiterReceiver(mLogreceiver);
}
edit:
i just figured that your LogReceiver-class has no constructor neither. you will need to write one aswell:
private LogReceiver mLogReceiver = new LogReceiver() {
and after that you can use the onReceive-method like you have it already in your code.
Try it again like this. The category may need to be added
<receiver
android:name = "LogReceiver"
android:enabled="true">
<intent-filter>
<action android:name="com.me.intent.finishlog" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
My problem was solved when I removed the receiver unregister from the OnPause(). method.
You declared the receiver in the manifest as:
android:name = "LogReceiver"
The documentation states that name should be:
The name of the class that implements the broadcast receiver, a
subclass of BroadcastReceiver. This should be a fully qualified class
name (such as, "com.example.project.ReportReceiver"). However, as a
shorthand, if the first character of the name is a period (for
example, ". ReportReceiver"), it is appended to the package name
specified in the element.
In other words, it needs to include the package. Try changing the name to:
android:name = ".LogReceiver"
or
android:name = "com.me.yourpackagename.LogReceiver"
I want to make an application in which once the application starts, it will show two button(start and stop button) and once the user clicks the start button the call function will be blocked for the time period till the user again start the application and click the stop button to stop this function. any help please its urgent
in short I Will tell I want to block the outgoing call from my phone by using this activity only
please is there any way to do so???
You can block the outgoing call using the setResultData(null) function in the onReceive method of the Broaadcast receiver.
public class BlockOutgoing extends BroadcastReceiver
{
String number;
#Override
public void onReceive(Context context, Intent intent)
{
Log.d("12280", "asdasNumber is-->> " + number);
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
setResultData(null);
Toast.makeText(context, "Outgoing Call Blocked" , 5000).show();
}
}
In the manifest file, you need to register the receiver like this,
<receiver
android:name=".BlockOutgoing"
android:label="#string/app_name" >
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
Also define the permission to intercept the outgoing call,
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
Edit-
To unregister a broadcast receiver, follow this link
public class BlockOutgoing extends BroadcastReceiver {
String number;
#SuppressLint("WrongConstant")
#Override
public void onReceive(Context context, Intent intent)
{
// Log.d("12280", "asdasNumber is-->> " + number);
number = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
setResultData(null);
Toast.makeText(context, "Outgoing Call Blocked" , 5000).show();
}
}
<receiver
android:name=".BlockOutgoing"
android:label="#string/app_name" >
<intent-filter android:priority="1">
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>