Android Binding get the name of the service that sent a message - android

I have 2 service (Service A and B) that exchange data using binding. One of the 2 services (Service A) can bind to multiple services (now there is only Service B, but I'll have to add also other 2 services, C and D). All the services exchanges data in the same way and use the same messages.
I would like to know if it is possible to retrieve the name of the service that sent the message.
In particular my Service A when receives a message from B needs to store this information so when it receives the same message from C or D behaves differently. Is it possible without adding a String in a bundle attached to the Message?
This is the code where I would like to get this info in Service A
class myHandler extends Handler {
#Override
public void handleMessage(Message msg) {
String senderName;
switch (msg.what) {
case REGISTER:
senderName = ???
addToRecord(senderName);
sendConfirm(msg.replyTo, SUCCESS);
break;
case UNREGISTER:
senderName = ???
removeFromRecord(senderName);
sendConfirm(msg.replyTo, SUCCESS);
break;
default:
super.handleMessage(msg);
}
}
}

Message's structure like :
Message{
what,arg1,arg2,obj,when,data,replyTo.
}
and Bind of Messenger :
oneway interface IMessenger {
void send(in Message msg);
}
So your background service can not obtain the name of original service.
As you said, putting a String in a bundle to the message can resolve this.
In some circumstances for avoid fake name, you can assign the particular String to the original service when binding. And let them resend to your service when call the remote method.

Related

FirebaseMessagingService 11.6.0 HandleIntent

The FirebaseMessagingService has the method onMessageReceived() which we should override to handle notifications, but this only works when the app is in Foreground.
To handle notifications even when the app is in background, I used to override the handleIntent, to just call the onMessageReceived().
In FirebaseMessagingService 11.6.0, the method handleIntent became final, with that said, I can't override it as I was doing.
How should I handle notifications when my app is in background in the 11.6.0?
public class NotificationsListenerService extends FirebaseMessagingService {
private static final String TAG = "NotificationsListenerService";
#Override
public void onMessageReceived(RemoteMessage remoteMessage)
String notifyData = remoteMessage.getData().get("notifData");
if(notifyData.contains("|")){
String[] itens = notifyData.split("\\|");
notifyData = itens[0];
}
String notifyType = remoteMessage.getData().get("notifType");
String title = remoteMessage.getData().get("title");
String message = remoteMessage.getData().get("body");
if(!isAppInForeground(App.getContext())){
sendNotification(title, message, notifyData, notifyType);
}
}
#Override
public final void handleIntent(Intent intent) {
...
this.onMessageReceived(builder.build());
...
}
private void sendNotification(String messageTitle, String messageBody, String notifyData, String notifyType) {
...
}
//Detect if app is in foreground
private boolean isAppInForeground(Context context) {
...
}
}
It's not intended for anyone to override handleIntent(). That's why it was made final. Also, you'll notice that it's completely missing from the javadocs - that's intentional.
If you want to handle a message in any circumstance (both foreground and background), use onMessageReceived(). The javadoc for that method says:
Called when a message is received.
This is also called when a notification message is received while the
app is in the foreground. The notification parameters can be retrieved
with getNotification().
This should work for data messages, but not notification messages sent from the console. Notification messages have different delivery behavior. See the documentation about message types and how to handle them.
I'd add that in FirebaseMessagingService 11.8.0 docs, it is stated in https://firebase.google.com/docs/cloud-messaging/android/receive that if a notification has a data payload it will call onMessageRecieved() when the app is in the foreground, and if the app is in the background the notification and data payload are delivered in the extras of the intent of your launcher Activity.
So, this means you need to decide how to handle the notification in two places, depending on whether the user is actively using the app or if it is in the background.
As you have seen yourself, if you receive the notification while the app is in the foreground, onMessageReceived() is called and you handle the notification there.
When the app is launched from the background, you have 2 options:
1: By default, the notification is sent to your system tray, and when it is clicked it opens your main activity, passing the data (what would have been remoteMessage.getData() in onMessageReceived()) to your activity as intent extras. You can handle the extras in your main activity like so and decide what to do with them, for instance check for a key value and launch a related intent.
// [START handle_data_extras]
if (getIntent().getExtras() != null) {
for (String key : getIntent().getExtras().keySet()) {
Object value = getIntent().getExtras().get(key);
Log.d(TAG, "Key: " + key + " Value: " + value);
}
}
You can decide what intent to open on-click if you add an intent-filter in your app manifest and a designated "click_action" value in your notification, and then handle the intent extras in the designated activity. See https://stackoverflow.com/a/39665485/3746204
I'd also suggest checking the firebase messaging sample app for ideas: https://github.com/firebase/quickstart-android/tree/master/messaging
i have the same problem after update firebase library version.
i think the easiest way is downgrade firebase library again (i use 11.4.2) and handleIntent() still works !

GCM Push message to update UI when foreground and post notification when background. How to implement this?

I have received the GCM push Message.
How to decide whether I have to update the UI or post a notification.
If our app is in foreground then we can update the UI. If our app is not running then I need to post a notification. Whether this is the right way. Or else any other way to handle it. And how can I find that my app is in foreground or background.
Thanks in advance.
If you followed that guide at Android Dev (specifically, this section), your app should be posting the notification regardless of whether it is in the foreground or not.
However, if you want to change the UI of the Activity which is in the foreground, modify the PendingIntent inside the sendNotification() method to launch your Activity. You may attach extras in the associated Intent. If your Activity is in the background, it will be started and the extras will be available via getIntent() inside the Activity's lifecycle methods. If it is in the foreground, the Activity's onNewIntent() method will be called, from where you can get your extras again (that you sent from the notification).
Yes I found the answer by myself.
There are 3 different your current activity status.
Resumed - Static reference is available
Stopped - Static reference is available
Destroyed - Static references are garbaged
//Define static variable of your activity instance
public static FleetLocActivity mFleetLocActivity = null;
And write the below code in your GCMIntentService. This class is called whenever there is a new push message.
if (FleetLocActivity.mFleetLocActivity != null) {
**//Activity is in Stopped or Resumed State**
handlePushMessage(pushMessage);
// Start Service and Update UI with the help of Handler
} else {
**//Activity is in Destroyed State**
// Post notification of received message. And Add the action of opening your home activity. When the user clicks the notification it will open the home activity and start the respective service by using activity instance.
mAppUtilInstance.postGcmCommandNotification(
"Command Received : " + pushMessage, mContext);
}
//Class variable updated with the received push message
private String pushMessage = "";
private void handlePushMessage(String pushMsg){
Message msgObj = gcmCommandHandler.obtainMessage();
Bundle bundle = new Bundle();
bundle.putString(Constants.getInstance().GCM_SERVER_MESSAGE,pushMessage);
msgObj.setData(bundle);
gcmCommandHandler.sendMessage(msgObj);
}
/**
* to handle the GCM push message (or) commands using Handler
*/
private Handler gcmCommandHandler = new Handler() {
// Create handleMessage function
public void handleMessage(Message message) {
String pushMessage = message.getData().getString(
Constants.getInstance().GCM_SERVER_MESSAGE);
if (pushMessage != null && pushMessage.length() > 0) {
//Start Service and update UI HERE
}
}
};

Android sending periodically data from service to Activity

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'

Activity or Service?

I'm building a Bluetooth application. I want to periodically scan for nearby Bluetooth devices. This program should start when the device starts and continue discovering devices based on a schedule (every 10 mins for example). I've been looking over the Android example of "BlueTooth Chat" in the API documentation, and I don't kow why it never uses the "Service" class. Should I use Service or Activity?
Furthermore, I understand that Services are supposed to be used for "long running tasks," but I also at some point want to provide some kind of GUI notification to the users via this class that discovers Bluetooth devices.
So, can someone please explain which one to use? What is the advantage?
You should use service if you want your scheduling running.Because android will eventually destroy your activity.
Definitely use a Service. In your MainActivity bind to the Service using bindService providing a ServiceConnection object. In this ServiceConnection object send a Message to the service with a reference to a local Messenger object (as part of a replyTo) that the Service can then use to later on send a Message back to your MainActivity. This will enable you to update your MainActivity GUI based on the results of your bluetooth scan.
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);
}
}

android service notify activity completed best way?

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.

Categories

Resources