I have an Activity with R.id.eventDistance and R.id.eventTime to display the distance & travel time based on current location. I calculate these values every 30 seconds using my Location Service class.
My question is: how do I update the TextView in Activity? I've tried looking up the question and found some possible solutions such as using a BroadcastReceiver and call TextView.setText() in the onReceive() method. I'm not sure how this is done. Am I supposed to pass in the Activity class like this:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, HomeActivity.class);
}
}
I'm not sure what to do after that. Any help is appreciated.
please see this flow.
1.in your LocationService class when you want to update UI. in your case it should be called every 30 seconds.
Intent i = new Intent("LOCATION_UPDATED");
i.putExtra("<Key>","text");
sendBroadcast(i);
2.in your UI (HomeActivity) class
in onCreate()
registerReceiver(uiUpdated, new IntentFilter("LOCATION_UPDATED"));
in class
private BroadcastReceiver uiUpdated= new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
TextView.setText(intent.getExtras().getString("<KEY>"))
}
};
in onDestroy()
unregisterReceiver(uiUpdated);
You should bind your Activity to your service so that they can directly communicate and message pass.
Ref
http://developer.android.com/guide/components/bound-services.html
Related
I'm trying to get push notification working in my Android app, using parse.com's push notification service. They implement a Broadcast receiver, which I am extending in my own class:
public class MyPushBroadcastReceiver extends ParsePushBroadcastReceiver
{
#Override
protected void onPushReceive(Context context, Intent intent)
{
JSONObject data = getDataFromIntent(intent);
[...]
super.onPushReceive(context, intent);
}
#Override
protected void onPushOpen(Context context, Intent intent)
{
ParseAnalytics.trackAppOpenedInBackground(intent);
Intent i = new Intent(context, MyActivity.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
I'm over-riding two methods:
onPushReceive - this is called when a notification arrives
onPushOpen - this is called when the user clicks on a notification in the notification area
There are three things I need to do:
When a notification arrives, I need to save it
When the user clicks on a notification, I need to open the app to an activity that displays the notifications I've saved
If a notification arrives while I have the app open to the display notifications activity, I need to update the UI to include the new activity.
The first part was easy. I'm just writing some JSON to a file.
The second I've had no trouble with. I create an intent, and that opens my activity. It reads the JSON from the file, and Bob's your uncle.
I've not been able to find a clean way of handling the third part.
I think where I'm stuck is that I haven't a clear understanding of the lifecycle of Activities or BroadcastServices. I'm not creating either, in my app, they're declared in the manifest, and constructed whenever.
Does the Android framework create one of each, as it processes the manifest? Is it possible for an activity to find the instance of the BroadcastReceiver? If I could, it'd be easy enough for me to wire up a callback between them.
Or do I need to define my own BroadcastService, that the ParsePushBroadcastReceiver would use to publish events, and that the activity would consume? The examples I've seen on doing that seem excessively complicated for what should be a fairly simple thing.
Help would be appreciated.
The suggestion on using a static variable got me thinking, and I think I've found a workable solution.
There may be multiple instances of an Activity, but only one can be active at any time.
I spent some time playing around with setting various flags on the Intent I'd pass to startActivity(), and didn't like any of the behaviors I'd see. (Some combinations would crash, some would create multiple entries in the stack so that the back button returned you to an older instance of the activity, all of them created visual effects as the old activity was replaced by the new.)
So, why not create a static field that points to the currently active Activity?
public class MyActivity extends Activity implements ReceiveNotifications
{
public static ReceiveNotifications notificationReceiver = null;
#Override
protected void onResume()
{
super.onResume();
NotificationsActivity.notificationReceiver = this;
updateMessages();
}
#Override
protected void onPause()
{
NotificationsActivity.notificationReceiver = null;
super.onPause();
}
#Override
public void notificationReceived()
{
updateMessages();
}
private void updateMessages()
{
[...]
}
}
Whenever an instance of MyActivity is active, the static variable notificationReceiver will point to it. Of course, I'm using an interface to control how much of MyActivity is visible through that variable:
public interface ReceiveNotifications
{
void notificationReceived();
}
Then, when we receive a notification, if notificationReceiver is not null, we call notificationReceived():
public class MyPushBroadcastReceiver extends ParsePushBroadcastReceiver
{
#Override
protected void onPushReceive(Context context, Intent intent)
{
JSONObject data = getDataFromIntent(intent);
[...]
super.onPushReceive(context, intent);
if (MyActivity.notificationReceiver != null)
MyActivity.notificationReceiver.notificationReceived();
}
#Override
protected void onPushOpen(Context context, Intent intent)
{
ParseAnalytics.trackAppOpenedInBackground(intent);
Intent i = new Intent(context, MyActivity.class);
i.putExtras(intent.getExtras());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
You can use the onNewIntent() (docs) method of the Activity to send the new info about something happened and then display some prompt.
the title says all, I need to change the variable of my service from a activity in my other app , what to finalize the service or not, this is possible?
I found the Message object , but I do not quite understand
The simplest solution would be to implement a BroadcastReceiver. Your Service listens for the Broadcast and the other App sends the Broadcast.
Example Reciever:
public class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Get bundle from intent and use it to set your Variable in your Service
}
}
Example Broadcaster (courtesy of Vogella):
Intent intent = new Intent();
intent.setAction("de.vogella.android.mybroadcast");
sendBroadcast(intent);
I am using broadcast receiver in my app to detect incomming call and it works fine. But problem is I can not send action to activity. I mean.. I want do something in activity not in receiver. I read many tutorial but they all are performing action in receiver. Any idea ?
You can declare a BroadcastReceiver as inner class of the Activity. In this case you can directly call activity's methods:
public class MyActivity extends Activity {
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
activityMethod();
}
};
private final IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
#Override
protected void onStart() {
super.onResume();
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onPause();
unregisterReceiver(receiver);
}
private void activityMethod() {
}
}
You can start the Activity using an Intent and put a command code in the Intent extra fields. In your Activity you can then decide the behaviour based on the command code or resort to a default behaviour if none is present.
You can start an activity from your receiver via the normal means:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, YourActivity.class);
startActivity(i);
}
Note though that the user is going to expect that the phone application starts up since they are receiving a phone call. It is very likely a bad idea to hijack the phone call by dumping your own activity on top of the stock dialer app.
I've a simple Main Activity which has to stop till an SMS is received... How can I launch a method from the MainActivity within the BroadcastReceiver's onReceive() Method?
Is there away with Signal and Wait? Can I pass something with a pending Intent, or how can I implement this communication?
Communication from BroadcastReceiver to Activity is touchy; what if the activity is already gone?
If I were you I'd set up a new BroadcastReceiver inside the Activity, which would receive a CLOSE message:
private BroadcastReceiver closeReceiver;
// ...
closeReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//EDIT: receiving parameters
String value = getIntent().getStringExtra("name");
//... do something with value
finish();
}
};
registerReceiver(closeReceiver, new IntentFilter(CLOSE_ACTION));
Then from the SMS BroadcastReceiver you can send out this action:
Intent i = new Intent(CLOSE_ACTION);
i.putExtra("name", "value"); //EDIT: this passes a parameter to the receiver
context.sendBroadcast(i);
I hope this helps?
I had the exact same problem, I tried using intent but i was unsuccessful
The easiest way to use it would be using static methods and static variables
MainActivity.java
public static void stopsms()
{
/*
some code to stop the activity
*/
}
SMSReceiver.java
at the end call this function
MainActivity.stopsms();
It works amazing if your code does not affect when you use static methods and variables. Let me know if you need any help.
The problem with registering a second receiver within the activity, however, is that it will not be persistent like registering in the manifest... thus, although, this solution may work, will only work if the activity is running in background.
it's easy, use interface like that:
1) in your broadcast receiver create an interface.
public interface ChangeListener{
public void functionWhoSendData(String type);
public void etc();
}
and instantiate that interface in your broadcast receiver, use it:
public void onReceive(....
String data=functionWhereYouReceiveYouData();
ChangeListener.functionWhoSendData(data);
}
And in your activity, make it implements your interface
i have a android service running in the background which receives the coordinates from the server every few seconds. i am not sure how do i display the coordinates on a map every time the service receives a response from the server. kindly help or give an idea.
thanks
I don't know any tutorials on this, but here's a version of mine:
To send a broadcast, you use the 'sendBroadcast(Intent i)' method of the Context class. The Service class extends Context, so you can access it from your implementation.
So in your Service goes:
public static final String BROADCAST_ACTION="com.yourservice.update";
public void onStart( Intent intent, int startId ) {
...
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
sendBroadcast(broadcastIntent);
...
}
You have to register a receiver for this broadcast in you Activity (possibly before you start boradcasting them), like this:
private BroadcastReceiver receiver=new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
//Here goes handling the stuff you got from the service
Bundle extras = intent.getExtras();
if(extras != null)processUIUpdate(extras);
}
};
public void onResume() {
...
//Register for the update broadcasts from the torrent service
registerReceiver(receiver, new IntentFilter(YourService.BROADCAST_ACTION));
...
}
Don't forget to deregister when the Activity goes background:
public void onPause() {
...
//Deregister for the update broadcast from the torrent service
unregisterReceiver(receiver);
...
}
This should work.
Your service could broadcast intents whenever it wants to update the displayed location on the map. The Activity displaying the map should register a receiver for that boradcast, and the boradcast's intent can hold the values for lat. and long.