I have a BroadcastReceiver which handles System Broadcasts like AC Connected and disconnected. The BroadcastReceiver receives POWER_CONNECTED and starts an Activity "MainActivity", which unlocks KeyGuard and acquires WakeLock. In the onCreate and in onResume I register dynamically a BroadcastReceiver to listen on POWER_DISCONNECTED.
The "MainActivity" starts a second "VideoPlayer Activity", which also register a BroadcastReceiver listening on POWER_DISCONNECTED.
When I send the ACTION_POWER_DISCONNECT over adb I see through LogCat that the "MainActivity" stops first. Why?
How can I handle that the "VideoPlayerActivity" finishes first?
Thanks
Look here (http://developer.android.com/reference/android/content/BroadcastReceiver.html):
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.
You can't guarantee that VideoPlayerActivity will receive.
I would recommend to create a separate BroadcastReceiver (which isn't part of activities). And in this broadcast receiver do something like this:
videoPlayerActivity.finish();
mainActivity.finish();
Sure, you need to initialize both of these variables in onCreate or onResume of your activities.
Actually you Registered the Broadcast Receiver in your main activity so its passing the context of main activity in the BroadcastReceiver so i will able to finish only that activity.
So lets screw up this what you need to do just write these lines of code in the onReceive() of Power Disconnected action receiver:
public void onReceive(Context context, Intent intent) {
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(startMain);
}
Enjoy
Related
I have an activity that starts a background service. Once it is started, it runs forever.
Lets say the background service needs the activity that started it to update something. Then how can I start the activity again "If it is not started" however if it is already started then send a broadcast?
Thanks
You would have to bind to the service in your activity. Then, in the service, implement the onBind and onUnbind methods to set a boolean "bound". Check the boolean to see whether the activity is active.
With activity you mean the service's process. If the service is started forever, then its process its started foerever (except when the system kill its for recovering memory purpose and recreates it later). That doesnt mean the rest of activities/fragments/services are not kill. A service is just an entry point for your application and it gives your process a position into the process priority ladder.
Its hard to say, since I don't know the details of your app, but I think that you may want to consider a bit of a redesign.
As you have noticed, Activities are ephemeral. Generally speaking, a service should not (cannot) depend on a particular Activity being active.
In fact, a well-designed service should not depend on any particular activity at all.
I'm not sure I completely follow your question. However, when communicating from a Service to an Activity I use a broadcast receiver in the Activity class.
This can be created as follows:
// register the BroadcastReceiver in your activity class
this.receiver = new NotificationReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.example.LISTENER");
registerReceiver(receiver, filter);
// insert in your activity class
class MyReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if(intent.hasExtra("command")) {
if(intent.getStringExtra("command").equals("userRegistered")) {
// insert code to do something when this intent is received
}
}
}
}
// insert in your service class to send message
Intent i = new Intent("com.example.LISTENER");
i.putExtra("command", "userRegistered");
sendBroadcast(i);
I define BroadcastReceiver in an application manifest and the receiver receives events in onReceive as expected. However I do not create the receiver class so I can't pass any information about my activity which the receiver is supposed to control. Context parameter gives me only application context and no any activity reference. So what is right way to make communication between application activities and broadcast receiver?
The answer is a little twisted but I found it here as well
Inform Activity from a BroadcastReceiver ONLY if it is in the foreground
It seems working. Please close the question then.
You can communicate broadcast to activity from this:-
Intent intent=new Intent(context,YourActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Hi I am developing android application in which I am defining one broadcast receiver.I am calling receiver from my activity. I am defining broadcast receiver like this :
public class MyScheduleReceiver extends BroadcastReceiver {
private static final long REPEAT_TIME = 100 * 5;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("RRRRRRRRRRRRRRRRRRRRRRRR", "on receive");
}
}
In android manifest file I am defining like this:
<receiver android:name="abc.xyz.MyScheduleReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
and in main activity I am calling my broadcast receiver like this :
//in activity oncreate
startService(new Intent(this, MyScheduleReceiver.class));
My problem is that when call start service it's not starting my service actually. But when i restart my device it start my service because I gave intent filter "BOOT_COMPLETED". what I wanted to do actually when i call start service my service must be start,
Am I doing something wrong. How to solve this problem?
Actual what happens here is that you can staring a broadcast receiver while starting the activity and this broadcast receiver starts listening BOOT_COMPLEATED is happening or not. When this happens it comes to onreceive . If you need to start a process doing in background you can use a a Service insted of BroadcastReciever. BroadcastRecievers are used to listen for some events to happen.Go through this, it will help you
Services
BroadcastReceiver
You're either confused, or you aren't wording your question well. What you have in your manifest (and how Android works generally) is that when BOOT_COMPLETED occurs, it will call that BroadcastReceiver you defined. It will not automatically start an activity or service. If you want to do that, you need to call startService or startActivity in your onReceive function of the receiver.
You do not start BroadcastReceivers. You start services, which are long term background processes. You register BroadcastReceivers to be informed of special events (like BOOT_COMPLETED). When one of the events you registered for occurs, it will create an instance of that class and call its onReceive.
Hopefully that clears things up. If not, I suggest you reread some tutorials on services and broadcast receivers, you seem to have the two confused.
startService call would only start a Service. MyScheduleReceiver here is a braodcast receiver. To trigger broadcast receivers, you generally have to send broadcasts and not call the startService.
to start broadcasts you need to send broadcasts not startService()
add this instead of startService(new Intent(this, MyScheduleReceiver.class));
Intent intent = new Intent();
intent.setAction("pakagename.MyScheduleReceiver");
sendBroadcast(intent);
I hope it helps.
So I understand (I think) about broadcast intents and receiving messages to them.
So now, my problem/what I can't work out is how to send a message from the onReceive method of a receiver to an activity. Lets say I have a receiver as such:
public class ReceiveMessages extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equalsIgnoreCase(TheService.DOWNLOADED)){
// send message to activity
}
}
}
How would I send a message to an activity?
Would I have to instantiate the receiver in the activity I want to send messages to and monitor it somehow? Or what? I understand the concept, but not really the application.
Any help would be absolutely amazing, thank you.
Tom
EDITED Corrected code examples for registering/unregistering the BroadcastReceiver and also removed manifest declaration.
Define ReceiveMessages as an inner class within the Activity which needs to listen for messages from the Service.
Then, declare class variables such as...
ReceiveMessages myReceiver = null;
Boolean myReceiverIsRegistered = false;
In onCreate() use myReceiver = new ReceiveMessages();
Then in onResume()...
if (!myReceiverIsRegistered) {
registerReceiver(myReceiver, new IntentFilter("com.mycompany.myapp.SOME_MESSAGE"));
myReceiverIsRegistered = true;
}
...and in onPause()...
if (myReceiverIsRegistered) {
unregisterReceiver(myReceiver);
myReceiverIsRegistered = false;
}
In the Service create and broadcast the Intent...
Intent i = new Intent("com.mycompany.myapp.SOME_MESSAGE");
sendBroadcast(i);
And that's about it. Make the 'action' unique to your package / app, i.e., com.mycompany... as in my example. This helps avoiding a situation where other apps or system components might attempt to process it.
No offense, but your question is still damn vague. So, I'm going to outline a whole mess of scenarios and hope that one of them actually hits whatever problem you think you have.
Scenario A: Only The Activity
If you only need to receive the broadcast when you have an activity in the foreground, have the activity register the BroadcastReceiver using registerReceiver(). As #MisterSquonk indicated, you would register the receiver in onResume() and unregister it in onPause().
Scenario B: Activity If In Foreground, Else Other; Ordered Broadcast
If you want the foreground activity to handle the broadcast, but you want something else to happen if that activity is not in the foreground (e.g., raise a Notification), and the broadcast is an ordered broadcast (e.g., incoming SMS), then you would still use the Scenario A solution, but with a higher-priority IntentFilter (see setPriority()). In addition, you would register a BroadcastReceiver via a <receiver> element in the manifest, with a lower-priority <intent-filter> for the same broadcast. In the activity's BroadcastReceiver, call abortBroadcast() to consume the event and prevent it from reaching your manifest-registered BroadcastReceiver.
Scenario C: Activity If In Foreground, Else Other; Regular Broadcast
If Scenario B almost fits, but the broadcast you are listening for is not an ordered broadcast, you will need to start with Scenario B. However, have the broadcast that both receivers have in their respective filters be one of your own, using a private action string as #MisterSquonk suggested. In addition, have another BroadcastReceiver registered in the manifest, whose <intent-filter> is for the real broadcast you're listening for. That receiver would simply call sendOrderedBroadcast() to send out the ordered broadcast that the other receivers are listening on.
Scenario D: Activity Regardless of Foreground
If some activity of yours needs to know about the broadcast, and it does not matter whether or not it is in the foreground, you need to rethink what you mean by that. Usually, this really means that the broadcast affects your data model in some way, in which case your concern should not be to let the activities know, but rather to update your data model, and use your already-existing "let the activities know about the data model change" logic handle the rest.
If, however, you are convinced that this is not part of your data model, you can implement Scenario B or Scenario C, plus stick some information in a static data member. Your activities can examine that static data member in onResume() to pick up the information about the broadcast when they return to the foreground.
If you're thinking "but, what if my process is terminated between the broadcast and the other activity coming to the foreground?", then your broadcast really is updating your data model, per the opening paragraph of this scenario.
If you're thinking "but, I want to update an activity that is doing work in the background", then the activity in question is broken. Activities should never be doing work in the background. That work should be delegated to some form of service, and there's a whole related set of scenarios for getting a broadcast to the service.
To broadcast an intent:
Intent intent = new Intent("com.yourcompany.testIntent");
intent.putExtra("value","test");
sendBroadcast(intent);
To receive the same intent use:
IntentFilter filter = new IntentFilter("com.yourcompany.testIntent");
BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String value = intent.getExtras().getString("value");
}
};
registerReceiver(receiver, filter);
Possibly not relevant at the time of the question being asked but there is now the LocalBroadcastManager in the Android Support Package.
Works pretty much the same way as normal broadcasts but all "chatter" is local to the app it is running in.
Advantages:
You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
It is more efficient than sending a global broadcast through the system.
Example:
Intent i = new Intent("my.local.intent");
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
and to receive
receiver = new MyBroadcastReceiverToHandleLocalBroadcast();
IntentFilter i = new IntentFilter();
i.addAction("my.local.intent");
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, i);
I am currently firing an Intent to a Broadcast Receiver which in turns starts an Activity.
Then from the same Service another Intent is fired to a Broadcast Receiver thats in the Activity.
The problem is that the Activity isn't getting the Intent meant for it because it is fired before it is alive and the Broadcast Reciever is registered.
I was wondering is there anyway to make sure an Activity is alive before sending an Intent?
Or any other solution to this?
Why not start the activity if it is not yet alive?
The general mechanism to start a new
activity if its not running— or to
bring the activity stack to the front
if is already running in the
background— is the to use the
NEW_TASK_LAUNCH flag in the
startActivity() call.
That or simply give the activity a chance to start before firing the Intent.
Alternatively you could try using sendOrderedBroadcast to retrieve data back from the broadcast and then possibly do a retry.
public abstract void sendOrderedBroadcast (Intent intent, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)