I'm using a BroadcastReceiver in my Android app which simply contains the following piece of code:
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
GcmIntentService.isHandled = true;
Toast.makeText(context, "broadcast receiver test", Toast.LENGTH_SHORT).show();
}
}
I'm using this receiver to determine if my activity is running and carry out some updates in a ListView without having any notifications produced by GcmIntentService.
With the code being simple so far, only creating a toast message, I'm unable to catch the boolean value from GcmIntentService.isHandled as soon as the sendBroadcast is invoked.
Is it possible in any way to determine if the code for my receiver has finished running. I understand that sendBroadcast is an asynchronous call, and I'm making use of Thread.sleep(1000) so far to wait for the isHandled value, but it would be nice if there is a more reliable method on achieving this.
Any thoughts?
Your question can be divided to two parts:
1.How to know that if there is a receiver actually received the broadcast.
2.How should the receiver notify the service that message is been handled.
It seems difficult to achieve the first goal through standard Intent api, instead I suggest you may try the "observer pattern".
You may create a global Observable object in your Application and make your Activity implements Observer, register itself in onCreate() and unRegister in onDestory().Inside the Service you can check if there is an Activity running through countObservers() and then simply notify it.
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 have a BroadcastReceiver, and the onReceive is called from two different postExecute methods in two different asyncTasks, in two different Activities.
I have a third activity that is running all the time called HomeActivity, and I want to publish some text to the HomeActivity's UI from the onReceive method.
Is it possible? I know that the context parameter is the context of the activity who raised the onReceive, but I want to access the HomeActivity's UI.
Here is the code
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// here I want to publish some text to the HomeActivity
}
}
any ideas? thanks in advance
You want to change text in your running activity based on what you receive in the onReceive of the BroadcastReceiver? Right? One way is that you can use LocalBroadcast. See LocalBroadcast Manager.
For how to implement is, there is a great example on how to use LocalBroadcastManager?.
LocalBroadcast Manager is a helper to register for and send broadcasts of Intents to local objects within your process. The data you are broadcasting won't leave your app, so don't need to worry about leaking private data.`
Your HomeActivity can registers for this local broadcast. From the MyBroadcastReceiver you send a LocalBroadcast from within the onReceive (saying that hey, I received a message. Do you want to do something now activity). Then inside your Activity you can listen to the broadcast. This way if the activity is in the forefront/is active, it will receive the broadcast otherwise it won't. So, whenever you receive that local broadcast, you may change the text etc, if activity is open.
In general i have a service that sends an intent to my activity which is ALWAYS on every 6 sec and a BroadcastReceiver everytime on receive updates a timer.
I found by accident that after a while ( this is random ) that the particular receiver stops working.
OnPause i unregister it and onResume i register it again.
Also this happens randomly in any devices and android versions.
I found by researching on the web , that after onReceive the receiver is ready to killed by Android but mine keeps getting intents.
"Receiver Lifecycle
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
"
FYI i have declare it like this inside my activity
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent intent) {
Log.i("Intent received", "+_ " + intent.getAction());
if (intent.getAction().equals(TEST)) {
//do sth
} else {
//do sth else
}
}
}
Thans a lot even for taking the time to read :).
I dont declare anythin to my manifest and as for my logcat i must be over my phone the moment it happens. The service is a simple send broadcast after one async task. The last test i made was ensuring that the code from the service was running by logging the beeing sent. And the service kept on.
I am away from my code write now but i think there will be no help because is very simple. Thnaks
Well i could still figure out but I find a solution to my problem
Timer now is in the activity and receiver is sending the event but after 10000 tries i want to trigger the END EVENT. Now the receiver since he didn't work i couldn't get it but now i Start an intent with extras for the same activity always with flags new_task and clear_top.
No matter if my receiver is working or not, since the service is ok i will start the specific Activity and pseudo-show the END EVENT.
PS:: This behavior isn't always trigger but sometimes. So now i am ok.
If i am not understood please comment and ask anything. Thanks
I have a dynamically registered BroadcastReceiver on a Service. It gets AudioManager.RINGER_MODE_CHANGED_ACTION as IntentFilter. Every time I start the service I get the log message in onReceive() method. It works normally after that. I do not want it to receive once when service is started each time. Could you please tell me what I am missing here?
receiver=new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
Log.d("zil", "degisti");
}
};
IntentFilter filter=new IntentFilter(
AudioManager.RINGER_MODE_CHANGED_ACTION);
registerReceiver(receiver,filter);
The intent you are interested in, AudioManager.RINGER_MODE_CHANGED_ACTION, is "sticky". That means that the system always keeps the last broadcast sent and whenever a BroadcastReceiver is registered that is interested in that Intent, it receives it right away. This is a very useful feature but sometimes it isn't what you want ;-)
I assume that you are only interested in actual "change" events. In this case you need to ignore the "current" event and listen only for any events that happen in the future. Lucky for you, there is a solution:
In 'onReceive()' do the following:
if (isInitialStickyBroadcast()) {
// Ignore this one as we aren't interested in the current state
} else {
Log.d("zil", "degisti");
// Do whatever you want to do with the event here
}
unregisterReceiver(receiver);
this probably wont work because you created an Anonymous inner class implementation of BroadcastReciever. instead create a nested/private class that extends BroacastReceiver in the activity where you want your service started. Then dynamically register and unregister your receivers in the Activity lifecycle callbacks
I have a widget that simply uses a service to update the looks of a widget's RemoteViews. The service is started based on filters supplied by a different registered BroadcastReceiver. When one of the criteria are met, the onReceive() of my BroadcastReceiver is called and I start my service. The service runs and then stops itself. This works great for a while. However, after a while it is as if the BroadcastReceiver is killed. I have seen in the logs where my process has died, and it restarts my service in 5000 ms. This is great, but the problem is that my BroadcastReceiver is what actually controls the starting of the service based on my subscribed events. Without it, my service is not started when those events occur, such as the user's screen on. Any idea why this would happen? Why would the BroadcastReceiver stop receiving events when the unRegister() has not been called? I don't want my service to be up and running at all times. I suspect the same behavior would occur if I used the service itself as the BroadcastReceiver. Thanks for any help.
#Override
public void onReceive(Context context, Intent intent)
{
try
{
Log.i(TAG, "Received Broadcast: " + intent.getAction());
Bundle bundle = intent.getExtras();
context.startService(new Intent(
com.mypkg.services.UpdateService.ACTION_UPDATE));
Log.i(TAG, "Service start complete.");
}
catch(Throwable t)
{
JLog.e(TAG, "An occurred during onReceive(): ", t);
}
}
Your application is crashing, you'll need to find the crash dump in the logs to understand more about it.
You can make the broadcast receiver immune by not needing to registerReceiver() in the first place -- instead of programatically declaring the receiver, declare it in your AndroidManifest, along with an appropriate intent filter to define the broadcast(s) you wish to receive.