Best practice to update UI from BroadcastReceiver (for receive new sms) - android

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();
}
}
}

Related

Android: How to pass data from service to broadcast reciever

In my laboratory work I have to create a service, which sends notifications when speed of battery discharging is greater then set.
I created an Activity with EditText for this value and 2 button for starting and stopping the service. Also I created a BatteryService class, inherited form Service class and BatteryReciever.
Now reciver registers with action BATTERY_CHANGED in service in onStartCommand. And problem is how to pass data to reciever or how to know about events in service.
What is the best way to solve this task?
To trigger a BroadcastReceiver, you need to use
sendBroadcast(intent);
Put the data you want to send from the Service in the intent as follows:
Intent intent = new Intent("my.custom.action");
Bundle b = new Bundle();
b.putSerializable("name", name);
b.putShort("count", count);
intent.putExtra("bundle", b);
sendBroadcast(intent);
And retrieve the data in the onReceive() method of the BroadcastReceiver:
#Override
public void onReceive (Context context, Intent intent){
Bundle b = intent.getExtras();
// do awesome things ...
}
Try this. This will work.

sendBroadcast does not get called in Activity when Activity is opened

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.

Information from BroadcastReceiver to specific Activity via external class

I have "ComposeActivity" which calls the "SendSMS" method after onClick, which than calls metod in SMS class. I had also registered two BroadcastReceiver: SmsDeliveredReceiver and SmsSentReceiver, similar to: https://stackoverflow.com/a/17164931/1888738. How can I inform ComposeActivity, that sms was succesfullly sent, and that activity can clean some EditText's, and maybe show crouton with information that sms was sent or not(and why)? My codes: http://pastebin.com/LNRuSeBu
If you have receivers to handle when the SMS messages are sent or not sent. You could modify the onReceive of both of the receivers to send and intent to the ComposeActivity by creating an intent and calling intent.setComponent to specify where the intent should go. with some data that tells the ComposeActivity the result of trying to send the message.
Update:
public void onReceive(Context context, Intent arg1) {
Intent i = new Intent(action);
i.setComponent(new ComponentName("com.mypackage.compose","ComposeActivity"));
switch (getResultCode()) {
case Activity.RESULT_OK:
Log.d(getClass().getSimpleName(), "SMS delivered");
intent.setAction("com.mypackage.compose.SMS_SENT"); // String you define to match the intent-filter of ComposeActivity.
break;
case Activity.RESULT_CANCELED:
Log.d(getClass().getSimpleName(), "SMS not delivered");
intent.setAction("com.mypackage.compose.SMS_FAILED"); // String you define to match the intent-filter of ComposeActivity.
break;
}
startActivity(intent); // you may not necessarily have to call startActivity but call whatever method you need to to deliver the intent.
}
At that point it should just be matter of addind an intent-filter and a receiver to your compose activity either via the manifest or programatically. Your call. The strings I used were made up but you could pick an exiting intent action string or declare strings that you use in the intent filter. Again up to you. May also be helpful to look at questions about sending explicit intents to components like Android explicit intent with target component
or looking at the android docs.
Ok, after 5 hours of trying, I've already solved this:
in BroadcastReceiver in onReceive:
Intent intent = new Intent();
intent.setAction("SOMEACTION");
context.sendBroadcast(intent);
in Activity:
public BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals("SOMEACTION")) {
Log.d(TAG, "Sent");
}
}
};
and in onCreate Activity I registered BroadcastReceiver:
registerReceiver(receiver, new IntentFilter("SOMEACTION"));
Thats all...

Passing Data from Broadcast Receiver to another Activity

Hi I've been having an issue with Broadcast Receivers and passing information to another activity. I'm trying to create an application that will capture incoming SMS messages, look for a website in the text, then pop up an Alert Dialog box asking if the user wants to go to the website.
public class TextReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent)
{
// .. other code that
// sets received SMS into message
Toast toast = Toast.makeText(context,
"Received Text: " + message.getMessageBody(), Toast.LENGTH_LONG);
toast.show();
}
So that code works fine, receive a text it pops up a toast with the message. The toast is useless but it shows the receiver works. But I want to communicate with an activity to show an Alert Dialog and start up a webView. I already programmed the code that will take a string search for the website and open the webView. Is it possible to get the string from the broadcast receiver and do something like this?:
public class ReceiveText extends Activity{
public void onCreate(Bundle savedInstanceState) {
// Somehow pass the string from the receiver into this activity,
//stored in variable messages
findOpen(messages);
// is that possible?
}
public class findOpen(string messages){
// do stuff ... open alert...open site if OK
}
So basically I just want to pass a string from a Broadcast Receiver to another activity that will use that string. The rest of the code is basically in place all I need is that string... I'm new to this and Java and any help would be much appreciated. Thanks
Instantiate a BroadcastReceiver in the activity you want to get your data to, for example:
private BroadcastReceiver mServiceReceiver = new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent)
{
//Extract your data - better to use constants...
String IncomingSms=intent.getStringExtra("incomingSms");//
String phoneNumber=intent.getStringExtra("incomingPhoneNumber");
}
};
Unregister your receiver on onPause():
#Override
protected void onPause() {
super.onPause();
try {
if(mServiceReceiver != null){
unregisterReceiver(mServiceReceiver);
}
} catch (Exception e) {
e.printStackTrace();
}
}
Register it on onResume():
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.SmsReceiver");
registerReceiver(mServiceReceiver , filter);
}
Broadcast your data from the service via an Intent, for Example:
Intent i = new Intent("android.intent.action.SmsReceiver").putExtra("incomingSms", message);
i.putExtra("incomingPhoneNumber", phoneNumber);
context.sendBroadcast(i);
and that's it! goodLuck!
If you have your activity named ReceiveText, then in your BroadcastReceiver, you should do the following:
Intent i = new Intent(context, ReceiveText.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("message", message.getMessageBody());
context.startActivity(i);
Then, in your activity, you will need to getExtra as so:
Intent intent = getIntent();
String message = intent.getStringExtra("message");
And then you will use message as you need.
If you simply want the ReceiveText activity to show the message as a dialog, declare <activity android:theme="#android:style/Theme.Dialog" /> in your manifest for ReceiveText and then set the message to a textview in the activity.
EDIT: This restarts your activity. this answer is likely a better solution for most people.
We can send the data from onReceive to another activity using LocalBroadcastManager.
It means you are again broadcasting the data using the context
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Broadcast", "wifi ConnectivityReceiver");
Bundle extras = intent.getExtras();
Intent intent = new Intent("broadCastName");
// Data you need to pass to another activity
intent .putExtra("message", extras.getString(Config.MESSAGE_KEY));
context.sendBroadcast(intent );
}

Android Broadcast from Service To Activity

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.

Categories

Resources