I am making an app where I receive XMPP packets. My app starts in foreground and starts a Sticky Service if not started and start receive messages in backgrounds and make notifications of them. The notifications works well and when clicked they show the data. Issue comes (that too sometimes in some mobile phones) when I make a sendBroadcast call from service so that I can asynchronously update the text of message in Activity when it is opened.
My app is made with a Activity and within that there are two Fragments(SherlockFragment)
So I made a private broadcastreceiver in one of fragment where I want to show the text (updated text).
Code is written below
public class newMessage extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.v("ONMESSAGE", "broadcast");
String action = intent.getAction();
if(action.equalsIgnoreCase("NewMessage")){
Bundle extra = intent.getExtras();
String username = extra.getString("from");
String message = extra.getString("message");
showMessage(username, message);
Log.v("ONMESSAGE", "in broadcast is " + username);
}
}
}
I then make a statement of below in Fragment class
private newMessage messageReceiver = new newMessage();
in onCreateView I wrote the below line
getActivity().registerReceiver(messageReceiver, new IntentFilter("NewMessage"));
I did not unregister the broadcast receiver now and I tried doing that too.
When I receive a message in my service, I made call to below code.
Intent i = new Intent("NewMessage");
i.putExtra("message", message);
i.putExtra("from", from);
context.sendBroadcast(i);
I did not add the broadcats to to manifest cause I dont know how to do it when written inside a class.
Sometimes, it calls the sendbroadcase and everything works well however sometimes it does not call and just generate the notification.
Related
I'm dealing with wearable, and my purpose is the next:
From my watch, I want to press a simple button, which send a simple message to the mobile. But I would like to handle all those behaviors :
when mobile app isn't yet launched, then launch the app and pass the message from wear, which can be handled in the launcher activity
when mobile app is launched but in the background, then just bring it to foreground and handle message from wear, which can be handled in the launcher activity
when mobile app is launched and in foreground, juste handle the message in the launcher activity
So far, I handle to launch the app when it isn't not yet launched, but I can't get the extra message in the launcher activity contained in the intent. Here the code.
the mobile service
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
Intent intent = new Intent( this, MainActivity.class );
intent.putExtra("Data", msg);
intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity( intent );
}
}
}
However, if I use a broadcast to send the message from service to the main activity, it works only if the app is launched and foreground
public class MobileWearService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
super.onMessageReceived(messageEvent);
String event = messageEvent.getPath();
String msg = new String(messageEvent.getData());
if (event.equals(START_ACTIVITY)) {
broadcastIntent.setAction("com.me.project.wear.to.app");
broadcastIntent.putExtra("Data", msg);
broadcastIntent.putExtras(intent);
sendBroadcast(broadcastIntent);
}
}
}
launcher activity
private IntentFilter mIntentFilter = new IntentFilter("com.me.project.wear.to.app");
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null && intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
}
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(mReceiver, mIntentFilter);
}
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mReceiver);
}
So I would to combine the fact to get the message from wear (I know how to) but pass this message to get it in the launcher activity regardless of the state of the app.
Just make the static BroadcastReceiver
public class WatchMessageReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if (intent != null &&
intent.getAction().equals("com.me.project.wear.to.app")) {
String msg = intent.getStringExtra("Data");
Intent launcherIntent = new Intent(context, LauncherActivity.class);
launcherIntent.putExtra("Data",msg);
startActivity(launcherIntent);
}
}
}
in your manifest file
<receiver android:name ="WatchMessageReceiver"
<intent-filter>
<action android:name="com.me.project.wear.to.app"/>
</intent-filter>
</receiver>
In the Sending and Syncing Data training, there is a Handling Data Layer Events:
When you make a call to the Data Layer API, you can receive the status of the call when it completes. You also can listen for data events, resulting from data changes that your application makes anywhere on the Android Wear network.
Listen for Data Layer Events
Because the data layer synchronizes and sends data across the handheld and wearable, it is usually necessary to listen for important events. Examples of such events include creation of data items and receipt of messages.
To listen for data layer events, you have two options:
Create a service that extends WearableListenerService.
Create an activity that implements DataApi.DataListener.
With both these options, you override the data event callback methods for the events you are interested in handling.
Some of the events you can listen for using WearableListenerService are as follows:
onDataChanged(): Whenever a data item object is created, deleted, or changed, the system triggers this callback on all connected nodes.
onMessageReceived(): A message sent from a node triggers this callback on the target node.
onCapabilityChanged(): When a capability that an instance of your app advertises becomes available on the network, that event triggers this callback. If you're looking for a nearby node you can query the isNearby() method of the nodes provided in the callback.
According to the related SO post:
WearableListenerService does not run constantly - it is only started when a new message/node connection/data layer change is sent and stopped when there are no more messages.
Hope this helps.
I am novice in android programming and I am trying to implement a simple app making use of push notification using firebase. I setup the android project (using Android Studio 2.2) folowing google documentation and I am able to get notification both with app in foreground than in background.
I have two class that extends FirebaseMessagingService (named MyFirebaseMessagingService) and FirebaseInstanceIdService (named MyFirebaseInstanceIDService).
In the first one I have the method onMessageReceived implemented that is triggered when the app is in foreground or when I receive a "data" tag as part of the notification. So I have this piece of code inside:
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
if (remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
String cappello;
cappello = remoteMessage.getNotification().getBody();
}
Now my problem is to update a textView in the main layout using the variable "cappello" mentioned above. How can I do that? I have found some example using different classes but all of them seems to be something different from that case.
Ho can I trigger an action to update some parts of the main layout ? A texView for example ?
Use a broadcast receiver and register it in your activity, Which gets triggered when new message comes
Short example, In your FirebaseMessagingService::onMessageReceived, you may have this:
cappello = remoteMessage.getNotification().getBody();
Intent intent = new Intent();
intent.putExtra("extra", cappello);
intent.setAction("com.my.app.onMessageReceived");
sendBroadcast(intent);
Then in your MainActivity, you implement a BroadcastReceiver :
private class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
String state = extras.getString("extra");
updateView(state);// update your textView in the main layout
}
}
and register for it in onResume() of MainActivity:
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.my.app.onMessageReceived");
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
registerReceiver(receiver, intentFilter);
I've followed a tutorial and implemented GCM push notification on my existing app. I've set Main activity to show notification. User receives a notification, clicks on it and notification display on Main activity. The problem is on app relaunch it shows notification every time.
Main Activity
public void registerGCM() {
....
protected Void doInBackground(Void... params) {
ServerUtilities.register(context, uname, uemail, regId);
}
}
Im calling this function on onCreate of Main activity to register app. This process is working fine.
Here's the BoradcaseReceiver code in Main activity outside of onCreate function.
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String newMessage = intent.getExtras().getString(EXTRA_MESSAGE);
WakeLocker.acquire(getApplicationContext());
Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show();
WakeLocker.release();
}
};
It should only show notification once when user clicks it (this works fine), but its also showing notification every time use launch the app. How do i prevent this?
Please let me know if im not clear enough.
Any help will be highly appreciated.
Thanks!
If i understood you correctly your missing this documentation
add this attrs into your manifest between activity tags for your result activity i.e MainActivity (for more information check link above)
android:excludeFromRecents="true"
android:launchMode="singleTask"
android:taskAffinity=""
i can't see your notification receiver class so make sure you are setting resultIntent flags like
resultIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
note: dont forget to give every notification an unique id
I have an activity for display new sms and SmsReceiver (extends BroadcastReceiver) to receive incoming sms. After receive sms, what is the best practice to update the UI?
Well if you have your own activity it is obious that you want you activity to be shown after the user receive a sms. Then in your receiver , onReceive method you can do this
startActivity(new Intent(context,MyActivity.class));
and the activity is presented to the user...
If you want to put additional info you can use putExtra("key","value") (it is method from the intent)
you can use like
Intent i=new Intent():
i.putExtra("key","value");
startActivity(context,i);
then in the activity onCreate method you can get this info by
String value = intent.getStringExtra("key");
and like this you can implement your business logic
Edit
when the activity is already running you can use
android:launchMode=["multiple" | "singleTop" |
"singleTask" | "singleInstance"]
I think singleInstance and singleTask will keep only one instance of your activity
Since you're using BroadcastReceiver there is no reason to use startActivity() as Lukap suggests. Simply use the receiver to actually receive messages.
When the SMS have arrived and you want to update the UI, do something like this:
Intent intent = new Intent(SOME_FANCY_NAME);
String msg = String.format("%d new SMS(s)!", numNewSMS);
intent.putExtra(SOME_FANCY_NAME_EXTRA, msg);
sendBroadcast(intent);
Then, in your activity:
class MyMessageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(SOME_FANCY_NAME)) {
// Here goes your UI-updates
String msg = intent.getStringExtra(SOME_FANCY_NAME_EXTRA);
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
}
}
I am trying to send a Broadcast from a service out to an Activity. I can verify the broadcast is sent from within the service, but the Activity doesn't pick up anything.
Here is the relevant service code:
Intent i = new Intent(NEW_MESSAGE);
i.putExtra(FriendInfo.USERNAME, StringUtils.parseBareAddress(message.getFrom()));
i.putExtra(FriendInfo.MESSAGE, message.getBody());
i.putExtra("who", "1");
sendBroadcast(i);
And the receiving end in the activity class:
public class newMessage extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equalsIgnoreCase(IMService.NEW_MESSAGE)){
Bundle extra = intent.getExtras();
String username = extra.getString(FriendInfo.USERNAME);
String message = extra.getString(FriendInfo.MESSAGE);
String who = extra.getString("who");
}
}
}
The BroadcastReceiver is defined within an Activity. I am registering the receiver in the onCreate method of the Activity, not in the Manifest file.
I'm stumped as to why it won't rec. anything.
Any insight?
EDIT
Registering takes place as follows:
registerReceiver(messageReceiver, new IntentFilter(IMService.NEW_MESSAGE));
Where "messageReceiver" is defined as
private newMessage messageReceiver = new newMessage();
IMService.NEW_MESSAGE is merely a string = "NewMessage"
I'm not sure if it is specific to the set up, or if it is a fix in general, but moving the register/unregister to the onResume/onPause _respectively_ and not registering in the onCreate solved the problem for me.
Try this two things:
Use manifest file to register receiver(but it barely helps)
Try make your Receiver a regular class, not inner one.
Inner class broadcast receiver will not be able to handle broadcast(means it unable to locate that class ).
So make it as a separate class
Definitely it will work.