I build an AsyncTask that create a service and now I want to sent from service to AsyncTask message.
my code on the AsyncTask is:
class ResponseHandler extends Handler {
public void handleMessage(Message message) {
// Toast.makeText(this, "message from service",Toast.LENGTH_SHORT).show();
}
hope that it will handle the message from service correct my if I wrong.
and from service tried to do this
Message message = Message.obtain(null, MyService.ADD_RESPONSE_HANDLER);
message.replyTo = messenger;
try {
myService.send(message);
catch (RemoteException e) {
e.printStackTrace();
}
but my errors are cannot find symbol in lines:
MyService.ADD_RESPONSE_HANDLER
message.replyTo = messenger;
try {
myService.send(message);
What do I need to add? Please give me a code that will do the work. thanks a lot.
One way is using ResultReceiver. Here is my complete blog post which I had recently posted with an Example.
How to update Activity from Service using ResultReceiver
For sending a message or any data from service to Activity you will need to Register an Custom Broadcast receiver.see these tutorials for sending data from service to Activity:
Communication between service and activity – Part 1
Custom Intents and Broadcasting with Receivers
Related
I have an android activity that has BroadcastReceiver as below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, intentFilter);
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TAG", intent.getAction());
}
};
The problem is I am receiving message from network and depending on message type I create the activity or send Broadcast message to activity, since I receive message very fast the message type to create activity arrives right before(in few milliseconds) the message type to send Broadcast message to the same activity and I get an error handleWindowVisibility: no activity for token android.os.BinderProxy researching a bit I found that the activity might not be created correctly before I send the broadcast intent.
So I made the thread sleep for 3 seconds.
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Now everything works as expected but the above looks ugly and a bit hackish, is there a better way to send broadcast intent right before the activity creation?
Instead of creating the Activity and sending a broadcast Intent to it, just put the contents of the broadcast Intent in the Intent you use to start the Activity (as an "extra"). Then you don't need the 3 second delay, you just only send the broadcast Intent if the Activity is already running.
I have successfully implemented Firebase messaging in my app. Works great in the background and onMessageReceived() gets called when the app is in the foreground (yippee!).
The issue I have is that I need to update the UI dynamically and I am stuck on the best way to achieve this. I don't want to send the user an in-app notification (as the sample code shows), I'm not sure I want to send a broadcast, all I want to do is to access the MainActivity in order to call a method already there, however I have no reference to the MainActivity in the service.
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification().getBody() != null) {
Log.d(LOG_TAG, "Message received: " + remoteMessage.getNotification().getBody());
} else {
Log.d(LOG_TAG, "Message received: " + remoteMessage.getData().get("message"));
}
// Call method in MainActivity
// <<< What goes Here?>>>>
}
This seems a simple use case but I can't find anything online to help.
Thanks in advance
Yes, you can update UI and pass value to your activity by using Local Broadcast
In your onMessageReceived() Firebase Service.
broadcaster = LocalBroadcastManager.getInstance(getBaseContext());
Intent intent = new Intent(REQUEST_ACCEPT);
intent.putExtra("Key", value);
intent.putExtra("key", value);
broadcaster.sendBroadcast(intent);
and register local Broadcast in your Activity or fragment method
#Override
public void onStart() {
super.onStart();
LocalBroadcastManager.getInstance(getActivity()).registerReceiver((receiver),
new IntentFilter(PushNotificationService.REQUEST_ACCEPT)
);
}
#Override
public void onStop() {
super.onStop();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
}
and Handle Your update event like this, do your update UI work Here, it will call automatically when notification received and onMessageReceived() send a broadcast.
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
try {
String value= intent.getStringExtra("key");
String value= intent.getStringExtra("key");
} catch (Exception e) {
e.printStackTrace();
}
}
};
I believe you should send a Local Broadcast with the data and register a receiver wherever you want that data to be utilised. This is a very good design pattern(Observer) as it decouples your Activity from the Service.
If the activity wants to do something with the data it will, else it won't. They are both separate entities and it would be much easier to maintain this code in the future, as far as I know.
Hope this helped.
I have a BroadCastRecevier that works in an asnyc task and it works when server sent a message then broadcast sends this server messages to activities. When activity get the message I am doing some process using a Handler However sometimes handler is not triggered. I mean broadcast sends three messages but handler works two times.
g.broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
srvrMessage = intent.getStringExtra("message");
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
myHandler.sendEmptyMessage(1);
}
};
To avoid this issue I decide to use a Service. I have created a service class and want that handler work inside of it but I could not send myHandler as a parameter while starting the service. How can I make this handler works in the service?
I think these links will help you:-
http://techblogon.com/android-service-example-code-description-complete-tutorial/
http://blog.denevell.org/android-service-handler-tutorial.html
I have a application which starts service on the first launch.
After that it pulls data from the server periodically.
I have opened my activity and if there is refresh button, I already have service which is already fetching data in the background that moment I want to disable the button and as soon as new data is loaded I have to show it in activity and enable refresh button.
If activity is not running then it should show notification.
So second point was the easiest and done. I'm stuck on the point 1. How to send periodically data to activity from service? I'm using database to store the data.
Any help on this ?
You can have your service send 'Messages' to your Activity Messenger to make it react as soon as service detects new content (see this android developers help section on Activity/Service Messenging).
Here are samples for Two-Way messaging (from Service to Activity and from Activity to Service). Quoting the doc:
You can see an example of how to provide two-way messaging in the
MessengerService.java (service) and
MessengerServiceActivities.java (client) samples.
Here's the relevant parts.
Incoming Handler in Activity:
/**
* Activity Handler of incoming messages from service.
*/
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MessengerService.MSG_SET_VALUE:
mCallbackText.setText("Received from service: " + msg.arg1);
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Activity target published for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
In the service, showing only the relevant parts:
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
//obtain Activity address from Message
Messenger mClient=msg.replyTo;
try {
// try to send it some mValue
mClient.send(Message.obtain(null,MSG_SET_VALUE, mValue, 0));
} catch (RemoteException e) {
// The client is dead. Remove it
mClient=null;
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
Also you can bind to your service from your activity and periodically call one of your service method to check for new content. For this, if your service is another application, you must use aidl (this is harder). If it's in the same package, I advise you to use the much easier 'local service binding'
I created a service which syncs data from the web on a background thread and want to notify a list activity when the service has completed so it can update it's cursor? What would be the best way to do this? I'm thinking of sending a broadcast when the service is done but not sure if that's the best way to do it. I need to requery the cursor when the service has finished so I'm not sure if that will work well with broadcast receivers? I haven't done alot of android in awhile so thanks in advance.
Use a Handler in your service that registers a client when your ListActivity connects to the service; that is, in your onServiceConnected method in your ListActivity, send a Message to your service that enables you to keep track of connected clients. Then you can simply loop through these clients in your Service and send them a Message when something takes place in your Service that you want to notify your ListActivity about. For more information you can look at code in an on-going project of mine: my ListActivity and my Service stub.
In short, in your MainActivity, start and bind to your service with:
Intent i = new Intent(this, NetworkService.class);
startService(i);
bindService(i, networkServiceConnection, Context.BIND_AUTO_CREATE);
Define a messenger to respond to messages from the service like:
Messenger messenger = new Messenger(new IncomingHandler());
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case NetworkService.MSG_SOMETHING:
// do something here
break;
default:
super.handleMessage(msg);
}
}
}
And then write your service connection code like:
private ServiceConnection networkServiceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
networkService = new Messenger(service);
try {
Message msg = Message.obtain(null, NetworkService.MSG_REGISTER_CLIENT);
msg.replyTo = messenger;
networkService.send(msg);
log.debug("Connected to service");
} catch (RemoteException e) {
// Here, the service has crashed even before we were able to connect
}
}
Note that the replyTo is the messenger we just created.
In your NetworkService, keep track of connected clients with:
ArrayList<Messenger> clients = new ArrayList<Messenger>();
and create your handler like:
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_CLIENT:
log.debug("Adding client: " + msg.replyTo);
clients.add(msg.replyTo);
break;
default:
super.handleMessage(msg);
break;
}
}
}
Then, when you want to send a message back to your MainActivity, just do something like the following:
for (int i = 0; i < clients.size(); i++) {
try {
clients.get(i).send(Message.obtain(null, MSG_SOMETHING));
} catch (RemoteException e) {
// If we get here, the client is dead, and we should remove it from the list
log.debug("Removing client: " + clients.get(i));
clients.remove(i);
}
}
If you're already using the support library, you could just as easily fire a broadcast from the service using the LocalBroadcastManager back to your activity that would listen for the broadcast being sent.
Using LocalBroadcastManager ensures only your own application would ever receive the broadcast so you don't have to worry about leaking private data or opening up potential security holes.
Also see: how to use LocalBroadcastManager?
EDIT (09/2014):
A better way to do this would be to use an event bus framework like Otto (my favourite) or GreenRobot/EventBus to avoid coupling your components too tightly.
As per The Busy Coder's Guide to Advanced Android Development
An Event Bus is a great way for the service to let other pieces
of the app know that certain work was done. It provides a standard
communications channel (or “bus”) that event producers and event
consumers can hook into. Event producers merely need to hand the event
to the bus; the bus will handle directing those events to relevant
consumers. This reduces the coupling between the producers and
consumers, sometimes even reducing the amount of code needed to source
and sink these events.