There are two ways to make a broadcast receiver known to the system: One declares it in the manifest file with this element. The other is to create the receiver dynamically in java code.
Now, the receiver has been created dynamically in java code and it does work normally.But why the first way "Declare in the manifest file" failed?
Is there anyone to success?
Thanks.
AndroidManifest.xml
<receiver android:name="pj.batteryinfo.BatteryReceiver">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"></action>
</intent-filter>
</receiver>
For some actions, you could only declare the BroadcastReceiver in Java code. This happens to the BATTERY_CHANGED action and SCREEN_ON,SCREEN_OFF so far as I know.
When you declare a BroadcastReceiver in the Manifest.xml file, no matter whether your app is running or not, the BroadcastReceiver will be awaken and thus the onReceive method will be called.
Why?I think this is because the BATTERY_CHANGED action is very common to take place and if you can declare it in the Manifest, the system will often send a lot of broadcasts and thus consumes battery dramatically;however, when you declare it in the code, the broadcastReceiver will only be effective when the activity is running and thus avoid extreme battery consumption. To save battery, Android doesn't allow such actions to be registered in the file.
This is just my guess. I didn't see any official explanations on this. As a developer, I just memorize such actions, rather than the reasons behind them.
Related
There is a kiosk app called Mobilock. This app starts way faster (Almost 5 seconds before) than my own app which starts with BOOT_COMPLETED broadcast.
My own app has the highest priority which is max value of integer. So this is not about the priority.
These guys have found a way to start their application 5 second sooner than BOOT_COMPLETED broadcast.
Has anyone got an idea about what they are doing?
Oh my god! I've luckily found it. :)
This Page Says : Apps must register their components with the system before they can run during Direct Boot mode or access device encrypted storage. Apps register with the system by marking components as encryption aware. To mark your component as encryption aware, set the android:directBootAware attribute to true in your manifest.
Encryption aware components can register to receive a ACTION_LOCKED_BOOT_COMPLETED broadcast message from the system when the device has been restarted. At this point device encrypted storage is available, and your component can execute tasks that need to be run during Direct Boot mode, such as triggering a scheduled alarm.
You just need to put
android:directBootAware="true"
So the code in manifest is;
<receiver
android:directBootAware="true" >
...
<intent-filter>
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
Listen also to android.intent.action.QUICKBOOT_POWERON and android.intent.action.LOCKED_BOOT_COMPLETED.
It seems to be device-dependant, which broadcast is sent first.
can anybody tell me the difference between intent-filter in activity and broadcastreceiver? Thank you very much!
<activity>
<intent-filter></intent-filter>
</activity>
and
<receiver>
<intent-filter></intent-filter>
</receiver>
I register a BroadcastReceiver to listen event of SMS arrives. Now, I want to use intent-filter in activity. Can I do it?
You can certainly have an <intent-filter> for an <activity>. Some do, such as your launcher activity.
However, if you try using the same <intent-filter> on an <activity> that you are using on a <receiver> to "listen event of SMS arrives", that will not work. The reason it will not work has nothing to do with the <intent-filter>, but rather with the Intent.
For inter-process communication (IPC) in Android, we usually use an Intent for one of three things:
starting an activity
starting or binding to a service
sending a broadcast
These are completely independent. You can think of them as three separate channels on a TV, or three separate train tracks.
When an SMS arrives, the system will send out one (or more) broadcasts related to that event. Since they are broadcasts, you can listen for them with a <receiver>. Since they are broadcasts, you cannot listen for them using an <activity> or a <service>.
You are welcome to have a <receiver> call startActivity() to start up an activity, which is almost like having an <activity> directly respond to the broadcast. However, while this is technically possible, it is rarely the right answer, as users usually will not appreciate being interrupted in whatever they are doing by your activity popping up without warning.
When an app starts an activity using an intent, it only starts one activity (possibly showing the "Complete action using..." dialog to let you choose which app you want to open it with), and the same goes for services, but broadcasting an intent may start several broadcast receivers, possibly from different apps.
You can get a more detailed idea here.
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.