I have a widget and I would like to check if the screen is off or on.
I can't use PowerMananger.isScreenOn because I want to support Android 1.5/1.6 .
So I tried to register SCREEN_ON/SCREEN_OFF actions in the manifest but that doesn't work. Seems like only registerReceiver works for those intents. (Android - how to receive broadcast intents ACTION_SCREEN_ON/OFF?)
The question is, where should I register my widget?
I can't register the screen intents receiver from my widget because you can't call registerReceiver from another BroadcastReceiver that is stated in the manifest.
I thought about calling it in the onCreate of my configuration activity.
The problem is that I don't call unregisterReceiver, so I get an exception for a leak.
Is there any other solution to this?
Thanks.
My solution is to start a service in the public void onReceive(Context context, Intent intent) method in the AppwidgetProvider subclass. Like:
if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_ENABLED)) {
Intent listenerService=new Intent(context,ScreenMoniterService.class);
startService(listenerService);
return;
}
Then in the public void onCreate() method of this service, register the BroadcastReceiver and in the public void onDestroy() method, unregister it.
Of course, you should stop that service when all of the appwidget are deleted.
if (intent.getAction().equals(AppWidgetManager.ACTION_APPWIDGET_DISABLED)) {
Intent listenerService=new Intent(context,ScreenMoniterService.class);
stopService(listenerService);
return;
}
registerReceiver:
final IntentFilter bcFilter = new IntentFilter();
bcFilter.addAction(Intent.ACTION_SCREEN_ON);
bcFilter.addAction(Intent.ACTION_SCREEN_OFF);
context.getApplicationContext().registerReceiver(this, bcFilter);
unregisterReceiver:
context.getApplicationContext().unregisterReceiver(this);
(Just at AppWidgetProvider!)
Related
Hi i am trying to understand Broadcast Receiver , i went through many sample codes , but still have some doubts. I wanted to know when we have to extend the Broadcast Receiver class and when should we use registerReceiver() method and when should we create object for BroadcastReceiver. In some programs i came across registerReceiver methods being used but without extending the Broadcast Receiver class. I also wanted to know how the onReceive method gets called.
Which approach should be used when?
here is the registerReceiver method:
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
switch (getResultCode()) {
........
}
}
}, new IntentFilter(SENT));
Object being created for BroadcastReceiver:
private BroadcastReceiver intentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
.................
}
};
Android has intent action for broadcast receiver. BroadCast receiver will be trigger when it listen any action which registered within it.
Now we will take one example :
That we need to listen the action of "whenever any bluetooth device connect to our device". For that android has it fix action android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED
So you can get it via manifest & registration also
BY Manifest Registration:
Put this in your manifest
<receiver android:name="MyBTReceiver">
<intent-filter>
<action android:name="android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED" />
</intent-filter>
</receiver>
Create MyBTReceiver.class
public class MyBTReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED")){
Log.d(TAG,"Bluetooth connect");
}
}
}
That was the simplest broadcast Receiver.
Now,
if you are only interested in receiving a broadcast while you are running, it is better to use registerReceiver(). You can also register it within your existing class file. you also need to unregister it onDestroy().
here, you dont need any broadcast registration in manifest except activity registration
For example
public class MainActivity extends Activity {
IntentFilter filter1;
#Override
public void onCreate() {
filter1 = new IntentFilter("android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED");
registerReceiver(myReceiver, filter1);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("android.bluetooth.BluetoothDevice.ACTION_ACL_CONNECTED")) {
Log.d(TAG,"Bluetooth connect");
}
}
};
#Override
public void onDestroy() {
unregisterReceiver(myReceiver);
}
}
In both cases BroadcastReceiver will be extended. In your second example you create so called anonymous class. New class has no specific name, that is why it's called so. Anyway this new class extends BroadcastReceiver and overrides onReceive() method.
Now back to your question. There are two kinds of receivers - statically and dynamically defined ones.
If you declare your receiver in AndroidManifest file, then it is statically defined. In this case you need to refer to a class implementing BroadcastReceiver by name. As you can see, you cannot use an anonymous class, because the last has no name. You have to explicitly implement a receiver. It's worth to mention, that in this case you do not use registerReceiver() method. Android does it for you automatically.
If you declare receivers dynamically (for instance in activity's onResume() method), then you can use anonymous class for that. To register a receiver you call registerReceiver() method. You can also use a named class too. Both options are valid in this case.
Hope this explains the difference.
In both case you are creating object.But in first case there is not any reference for
the receiver object so it can not be unregistered later but second one has so it can be
unregistered after registering object using below methods:
registerReceiver(intentReceiver );
unregisterReceiver(intentReceiver );
I want to use BroadcastReceiver in my application as AsyncTask result indicator in different Activities and therefore AsyncTasks too. I think my approach is little wrong or I missed something.
Here what I'm doing: Firstly, during onCreate I registered my receiver as a BroadcastReceiver using the registerReceiver method. My receiver looks like:
protected BroadcastReceiver myReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String msg_for_me = intent.getStringExtra("some_msg");
Log.i("Tutorial", msg_for_me);
}
}
In my application, I've A and B activities. Each have different receivers which getting messages from different tasks. By the way, I must clarify that, A activity starting B activity.
I'm using receiver which in activity A, then activity A starting B using the startActivity. In activity B, I'm executing an AsyncTask and on onPostExecute I'm sending a broadcast with B activity's context. But somehow still A activity's receiver getting message. Both receivers have the same content but have different names.
So here are my issues:
Should I unregisterReceiver when I started new activity on onPause method?
Is BroadcastReceiver that how I'm using, only for one call? Should I register again and again whenever I send any message?
I'm pretty sure I didn't define any receiver to Manifest. I suppose this is what I'm doing wrong. If this is well, how can I use IntentFilter while sending broadcast?
Please let me know if there is uncertain question. Any clues about BroadcastReceiver would be great and appriciated.
Yes, you should unregister broadcast receiver on activity pause. It
is the potential leak.
No broadcast receivers are not for one call.
They are called everytime the broadcast is done for the registered
intents.
You can register the receiver for particular intent on
OnResume like this,
mContext.registerReceiver(iReceiver, new android.content.IntentFilter("android.intent.action.BATTERY_CHANGED"));
Where iReceiver is ,
iReceiver = new IntentReceiver();
private class IntentReceiver extends BroadcastReceiver {
private final String LOG_TAG="IntentReceiver";
#Override
public void onReceive(Context arg0, Intent intent) {
}
}
and unregister the same on OnPause
mContext.unregisterReceiver(iReceiver);
I have an issue with BroadcastReceiver which I'm using in my activities. I'm actually doing this :
In onCreate() :
receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("finish")) {
// some code
}
}
};
registerReceiver(receiver, intentFilter);
and in onResume() and onPause() I'm doing this :
#Override
public void onResume(){
super.onResume();
MyCollectionList.this.registerReceiver(receiver, intentFilter);
}
#Override
public void onPause(){
super.onPause();
MyCollectionList.this.unregisterReceiver(receiver);
}
where intentFilter is :
IntentFilter intentFilter = new IntentFilter("finish");
and when I do this in 6 activities where I need to add this broadcast receiver my application start lagging and getting slow than before.
So is there any other better way to watch for intent filters without slowing the app/or best way in my situation.
Thanks in advance!
Instead of registering your receiver with Activity's context, register it with your application's context in your 1st activity as below:
getApplication().registerReceiver(receiver, intentFilter);
This way even if your activities goes into 'pause' state, your receiver will remain active as your application will keep on running in the background.
Hope this helps.
dont register your broadcast receiver in onCreate. Registering it in onResume and unregistering in onPause is safe and enough in your case
you must be doing some heavy load processing in your receiver method. Android offers a 10sec window to perform what ever you want in your receiver otherwise it will declare it as ANR
To avoid lag, load your processing on a new worker thread
I am writing an alarm code and using a broadcast receiver. I am able to receive the broadcast receiver. but now I want to come back to the calling activity and update the UI of my activity. I am not able to this.
I used the following code in my activity but it is never executing that code.
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "I am back!!", Toast.LENGTH_LONG).show();
}
};
#Override
protected void onPause()
{
super.onPause();
unregisterReceiver(myBroadcastReceiver);
}
#Override
protected void onResume()
{
super.onResume();
IntentFilter intentFilter = new IntentFilter("com.test.Main");
registerReceiver(myBroadcastReceiver, intentFilter);
}
in the manifest file I have included the following, here gotAlarm is the broadcast receiver file
<receiver android:name=".gotAlarm"
android:enabled="true">
</receiver>
gotAlarm file is one which gets called from the pending intent of the alarm set
public class gotAlarm extends BroadcastReceiver {
public void onReceive(Context context, Intent intent){
Toast.makeText(context, "Wake Up!!", Toast.LENGTH_LONG).show();
}
}
May be I am missing something very basic.
please help.
Two things:
If you dynamically register the receiver via Context.registerReceiver() then you won't receive broadcasts when Activity is paused (or stopped or not-running). If you need to receive broadcasts even when Activity is paused then create a top-level BroadcastReceiver class (as opposed to your inner class) and use <receiver> to register it.
BroadcastReceiver lifecycle docs state that BroadcastReceiver object is alive only during processing of onReceive(). You can not do any async tasks like showing dialogs, etc.. In your case (Activities might not be running and you receive a broadcast) you should use NotificationManager to notify user something happened.
I have dropped this way and I am starting a new activity on receiving broadcast. And I am sending information data from calling activity to broadcast and from broadcast to next activity. This has served the purpose.
Did you register your BroadcastReceiver (you can do this in the 'onResume'-method of your Activity)? Also, you should unregister your BroadcastReceiver in the 'onPause'-method.
Maybe it's easy, but I couldn't really figure this out right so far... I got a BroadcastReceiver waiting to get triggered by the AlarmMangager - this works fine.
Now: because the event, if it occurs, needs to refresh some elements on screen of the main Activity, I would like to send an Intent from that background BroadcastReceiver to my Activity - but only if it is currently in the foreground, aka active.
If it is not running or not visible, I don't care - and the last thing I want to do is start the Activity by my intent! I handle repainting of the views in my onResume() method, so I don't care at all.
Any hints on how to do that?
Thanks!
EDIT: my BroadcastReceiver is waiting for alarms that must be notified to the user. So, it must be there and declared in the manifest. The problem is: it will have to decide whether the mentioned Activity is currently up in front or not.
I believe that you're familiar with AlarmManager now (creating a new Alarm, register a receiver...) so I will not talk about that. Just give you a solution for your question.
Instead of registering a BroadcastReceiver in a class file and in manifest, you only create a new BroadcastReceiver in your activity, and then, register it in onResume method, and unregister it in onPause method, sth like this in your activity:
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//do something
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mIntentFilter = new IntentFilter();
mIntentFilter.addAction("your alarm action");
...
}
#Override
protected void onResume() {
registerReceiver(mIntentReceiver, mIntentFilter);
...
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(mIntentReceiver);
...
super.onPause();
}
The receiver will only receive the alarm intent when your activity is in foreground :)
(Sorry if my English is not clear)
So this is almost Bino's answer, but: instead of moving the receiver into the activity, use two receivers, with different Intents. The first one is your original alarm Intent, with a receiver registered in the manifest as you already have, and then that receiver sends a second broadcast intent, which is handled by a receiver registered by the activity as Bino says.
I've done this in my own timer project, on github. Here are the alarm receiver and the requery receiver. Hope that helps.