I want to create a traffic widget, and store the used traffic at each device shutdown. The problem is that I can't get the shutdown receiver to trigger.
I used the following code:
IntentFilter actionShutdown = new IntentFilter("android.intent.action.ACTION_SHUTDOWN");
IntentFilter quickPOFF = new IntentFilter("android.intent.action.QUICKBOOT_POWEROFF");
TrafficDataUpdate trafficDataUpdate = new TrafficDataUpdate();
getContext().registerReceiver(trafficDataUpdate, actionShutdown);
getContext().registerReceiver(trafficDataUpdate, quickPOFF);
I also tried with the receiver declared in manifest, but no success:
<receiver android:name=".receivers.TrafficDataUpdate">
<intent-filter>
<action android:name="android.intent.action.ACTION_SHUTDOWN"/>
<action android:name="android.intent.action.QUICKBOOT_POWEROFF"/>
</intent-filter>
</receiver>
Do you have suggestions?
Can someone recommend me another way of counting the data traffic, without the shutdown receiver?
Use one IntentFilter, not two, teaching it to listen for both actions. Your second registerReceiver() is implicitly unregistering the first receiver.
Also note that this will only work so long as your process is still in memory. Usually, your process is not in memory, and it is in the user's best interests for your process to not be in memory. Please replace this implementation with one where the receiver is registered in the manifest, as is shown in the following StackOverflow threads:
Android ACTION_SHUTDOWN Broadcast not working
BroadcastReceiver's behaviour for ACTION_SHUTDOWN
handling phone shutdown event in android
Related
I created a broadcast receiver and registered in in manifest using following approach it is working fine
static way registering broadcast receiver (working fine)
<receiver
android:name="DeviceRestartListener"
android:enabled="true"
android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</category> -->
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
But when i tried to register the broadcast receiver programmatic (instead of static way) using following way it doesnt work
Programmetic registering (not working)
DeviceRestartListener dataBroadcastReceiver = new DeviceRestartListener();
IntentFilter filter = new IntentFilter();
filter.addAction(
"android.intent.action.BOOT_COMPLETED")
//registerReceiver(dataBroadcastReceiver, filter); //DOESNT WORK
registerReceiver(dataBroadcastReceiver, filter, "android.permission.RECEIVE_BOOT_COMPLETED", null); //DOESNT WORK
No compilation and run time error. But the receiver is not receiving broadcast after device restarts
Thanks
All the Broadcast receivers will not work even when they are statically declared in manifest or registered dynamically using Application context. for example Intent actions like
Intent.ACTION_SCREEN_OFF
and
Intent.ACTION_SCREEN_ON
have to be registered dynamically. These actions will not be fired when they are declared in manifest. some Intent actions like
Intent.ACTION_TIME_CHANGED;
Intent.ACTION_TIME_TICK;
Intent.ACTION_TIMEZONE_CHANGED;
will be fired when are registered dynamically through context whose window token is not null.(like Activity or Dialog).
similar to this, some of the Intent actions like
Intent.ACTION_BOOT_COMPLETED
will work only when they are registered statically using manifest
Register receiver in code
When we register a receiver in code, we must unregister it when the app gets destroy (actually, when the Activity or Service that register it, gets destroy).
Register receiver in manifest
When we declare it in the manifest, you make it available even if you app is not running.
When to use which method to register
Which method to use for registering your BroadcastReceiver depends on what your app does with the system event. I think there are basically two reasons why your app wants to know about system-wide events:
Your app offers some kind of service around these events
Your app wants to react graciously to state changes
Examples for the first category are apps that need to work as soon as the device is booted or that must start some kind of work whenever an app is installed. Battery Widget Pro or App2SD are good examples for these kinds of apps. For this type you must register the BroadcastReceiver in the Manifest file.
Examples for the second category are events that signal a change to circumstances your app might rely on. Say your app depends on an established Bluetooth connection. You have to react to a state change – but only when your app is active. In this case there is no need for a statically registered broadcast receiver. A dynamically registered one would be more reasonable.
There are also a few events that you are not even allowed to statically register for. An example for this is the Intent.ACTION_TIME_TICK event which is broadcast every minute. Which is a wise decision because a static receiver would unnecessarily drain the battery.
I'd like to know if it's possible to start service using intents sent from another app? I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated. I did something similar for external intents from tasker but it doesn't work.
<receiver android:name="BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
I'd like to know if it's possible to start service using intents sent from another app?
Sure.
I've a Broadcast Receiver for android.intent.action.BOOT_COMPLETEDand it works even though at the time when the intent is received BrodcastReceiver class for it is not instancionated.
That is because manifest-registered BroadcastReceiver objects are not instantiated ahead of time. They are only created when a matching broadcast is sent.
I did something similar for external intents from tasker but it doesn't work.
"it doesn't work" is insufficient information for anyone to help you.
But, if you have a <service> with an <intent-filter>, other apps can create an Intent matching your <intent-filter> and use that to start (or bind to) your service. There are two exceptions:
If you add android:exported="false" to the <service>, third party apps cannot invoke it at all, though you would be better served simply getting rid of the <intent-filter> in that case
If you use android:permission on the <service> element, the other app needs to hold your stated permission in order to start or bind to your service
I have the following question:
Is it possible to completely override a phone-function when receiving a BroadcastReceiver? For example, is it possible to receive sms and do not let the sms to appear in the notification area?
thanks
Yes it is possible just define your BR like below code. make sure you call abortBroadcast(); method from receiver so it wont allow to further call onReceives of other BRs.
<receiver android:name=".SMSReceiver"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
Permission
<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission>
but it wont guaranteed to work all the time as there may be other apps doing same and could have abortedBroadcast, so there may be chances even your onReceive wont be tringger.
Sometimes. It depends on what type of broadcast it is. Take a look through the docs for BroadcastReceiver:
There are two major classes of broadcasts that can be received:
Normal broadcasts (sent with Context.sendBroadcast) are completely asynchronous. All receivers of the broadcast are run in an undefined order, often at the same time. This is more efficient, but means that receivers cannot use the result or abort APIs included here.
Ordered broadcasts (sent with Context.sendOrderedBroadcast) are delivered to one receiver at a time. As each receiver executes in turn, it can propagate a result to the next receiver, or it can completely abort the broadcast so that it won't be passed to other receivers. The order receivers run in can be controlled with the android:priority attribute of the matching intent-filter; receivers with the same priority will be run in an arbitrary order.
SMS happens to be an ordered broadcast, so in this case if you call abortBroadcast, other receivers with a lower priority will not be called. This will only work if your priority is the highest though, which is not really possible to guarantee, but you can do a reasonable job by just setting a very high priority, perhaps over 9000 might be appropriate. Although the docs do say to not use anything 1000 or over, this is to ensure that the system always gets to handle the broadcasts. In your case though, you really do want to stop the system from handling the broadcast.
I have two apps that I have complete control over. Both are signed with the same cert and both use the exact same intent filter. One sends the broadcast from a fragment, the other is suppose to receive it and do something. This however is not working:
Strings.FILTER_INIT_REGISTER = "com.app.FILTER_INIT_REGISTER"
Intent intent = new Intent(Strings.FILTER_INIT_REGISTER);
getActivity().sendBroadcast(intent);
I have registered the receiver in the Manifest app tag for the app containing the ReportingReceiver class:
<receiver
android:name=".receivers.ReportingReceiver"
android:exported="true"
>
<intent-filter>
<action android:name="com.app.FILTER_INIT_REGISTER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Curious why the ReportingReceiver class is not getting the intent call?
If your application only has a service and receivers then this won't work in Android 3.1 and later. The reason is that the system will not send broadcast Intents to application that are in the STOPPED STATE. An application is in the STOPPED STATE when it is first installed. It is removed from the STOPPED STATE when the user manually starts the application for the first time. It is returned to the STOPPED STATE if the user forces the application to stop using the application manager tool.
Since your application has no Activities, there is no way for the user to "start" it. Therefore it will never come out of the stopped state.
See http://developer.android.com/about/versions/android-3.1.html#launchcontrols
As Android Addict says in his comment to David Wasser's answer ... there is a way around this behaviour.
Just add the following flag to the calling Intent. This will ensure that you also reach broadcast receivers from "stopped" applications.
http://developer.android.com/reference/android/content/Intent.html#FLAG_INCLUDE_STOPPED_PACKAGES
You can read more about this Android 3.1 change here
http://developer.android.com/about/versions/android-3.1.html#launchcontrols
and here
http://code.google.com/p/android/issues/detail?id=18225
I need some help to understand when I can expect my broadcast receiver will work when just registered in the manifest versus having to be registered from a running activity or service.
So for example if I register a stand alone receiver with the following intent filter it works without having a service/activity reference to it:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.blk_burn.standalonereceiver"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<receiver android:name="TestReceiver">
<intent-filter>
<action android:name="android.media.AUDIO_BECOMING_NOISY"/>
</intent-filter>
</receiver>
</application>
</manifest>
However if I replace android.media.AUDIO_BECOMING_NOISY with android.intent.action.HEADSET_PLUG the receiver is not triggered (Android Documentation)
From what I found on this site you have to register this receiver from an activity or service that is already running for it to work (Post).
Can anyone tell me why this does not work when just adjusting your intent filter in the manifest and why you need to have a service running in the background that references/registers the receiver?
Is there a work around so that I can just register my receiver in my app's manifest using an intent filter with android.intent.action.HEADSET_PLUG?
How can do I identify which Broadcast actions from the android documentation need to have a service or activity register them versus just having the right filter in the manifest?
If your receiver is registered in the manifest, and your app is not running, a new process will be created to handle the broadcast. If you register it in code, it's tied to the life of the activity/service you registered it in. For some broadcasts, it doesn't really make sense to create a new app process if it doesn't exist, or there are some security, performance, etc. implications, and thus you can only register the receiver in code.
As for the HEADSET_PLUG broadcast, it seems the idea is that your already running app can get this to do app-specific adjustments to UI, volume, etc. If your app is not running, you shouldn't really care about the headphones being unplugged.
AFAIK, there is no single place this info is summarized for all broadcasts, but each Intent should have a comment in the JavaDoc about how to register and use it, but apparently it's lacking in places. You should be able to compile a list if you grep the Android source tree for Intent.FLAG_RECEIVER_REGISTERED_ONLY.
As usual broadcast receivers can be configured in the manifest fileAndroidManifest.xml. A BroadcastReceiver that is configured in this way is called statically registered.
You can register your receiver in the manifest file by using the element:
<receiver
android:name=".ConnectivityChangeReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
The nested element is used to specify the event the receiver should react to.
Dyanmic Broadcast Recievers
As an alternative you can register your BroadcastReceiver implementation dynamically in your code. You just need to call the registerReceiver() method on your Context object.
The registerReceiver() method takes two parameters:
The arguments of the registerReceiver() method
receiver : The BroadcastReceiver you want to register
filter : The IntentFilter object that specifies which event your receiver should listen to.
When you register your receiver in this way, it lives for as long as the component livesand Android sends events to this receiver until the creating component itself gets destroyed.
It’s your task to handle the lifecycle correctly. Thus when you add a receiver dynamically, take care to unregister the same receiver in the onPause() method of your Activity!
I suggest to register the receiver in the onResume() method of your Activity and to unregister it in your onPause() method:
#Override
protected void onPause() {
unregisterReceiver(mReceiver);
super.onPause();
}
#Override
protected void onResume() {
this.mReceiver = new ConnectivityChangeReceiver();
registerReceiver(
this.mReceiver,
new IntentFilter(
ConnectivityManager.CONNECTIVITY_ACTION));
super.onResume();
}
When to use which method to register
Which method to use for registering your BroadcastReceiver depends on what your app does with the system event. I think there are basically two reasons why your app wants to know about system-wide events:
Your app offers some kind of service around these events
Your app wants to react graciously to state changes
Examples for the first category are apps that need to work as soon as the device is booted or that must start some kind of work whenever an app is installed. Battery Widget Pro or App2SD are good examples for these kinds of apps. For this type you must register the BroadcastReceiver in the Manifest file.
Examples for the second category are events that signal a change to circumstances your app might rely on. Say your app depends on an established Bluetooth connection. You have to react to a state change – but only when your app is active. In this case there is no need for a statically registered broadcast receiver. A dynamically registered one would be more reasonable.
There are also a few events that you are not even allowed to statically register for. An example for this is the Intent.ACTION_TIME_TICK event which is broadcast every minute. Which is a wise decision because a static receiver would unnecessarily drain the battery.