I'm receiving intents in a broadcast receiver (declared in manifest), details of which I am 'logging' via b'cst intents received by my 'MainActivity', whose receiver updates the contents of a text view and is registered within the MainActivity code.
I'm wondering if there's a way to keep the contents of the MainActivity text view updated even if the MainActivity doesn't have 'focus' (i.e. another activity has been started). I appreciate that the b'cast receiver of the MainActivity will become unregistered upon pausing, but feel there ought to be a way to do this.
Any ideas?
You should do all of that on the "onResume" of the activity, just when it gets to the foreground.
One of solutions is to use a handler inside receiver, and in that you call a static method inside your activity...inside that method you can update or whatever you need to do with your text view...
Related
I have a BroadcastReceiver which listens to system intents such as Intent.ACTION_PACKAGE_ADDED. When it receives one, the Activity needs to refresh its the data it presents.
Of course, the Activity may not have focus, or may not even be running when this happens. What is the proper way to "leave a message" for the next time the Activity gains focus?
I thought of storing a boolean in the SharedPreferences, but something tells me this is not the right way to go.
What is the proper way to "leave a message" for the next time the Activity gains focus?
IMHO, you have four separate issues here:
Issue #1: How does the BroadcastReceiver tell a running Activity that an event occurred that may be of interest?
Solution: Use an event bus (LocalBroadcastManager, greenrobot's EventBus, Square's Otto), and post a package-added event from the receiver on the bus. Your activity can be registered for events from the bus while it is in the foreground, and it can update its view on the data when your event is received.
Issue #2: How does the BroadcastReceiver update the model data in the SQLite database when the broadcast occurs?
Solution: Delegate this, plus the receiver's side of the event bus logic, to an IntentService, as you need a background thread to do the database I/O. Post the event on the bus when the work is completed.
Issue #3: So, what happens if my activity is not in the foreground at the time the event goes out, but the activity exists (i.e., is in the background)?
Solution: Either reload your data in onResume() or use some sort of a "sticky" event with the bus. LocalBroadcastManager does not offer that, but greenrobot's EventBus has the notion of sticky events, and Square's Otto has a related #Producer construct.
Issue #4: What happens if I do not have an activity instance at all? For example, the package is added when my process is not running, so Android forks a process for me and invokes my receiver, but I have no UI code at all in my process right now?
Solution: Do nothing special. Your existing "load-the-data" logic will handle this case.
One simple solution can be a static variable flag in Broadcastreceiver. Once receiver receives intent, make flag=true.
Activity when gains focus can look at this static variable and can refresh data accordingly and turn this static flag to false.
It depends of what you are trying to do when the Intent is received. If you only want to refresh the content, the the proper way is to use the onResume and onStopto attach the broadcast receiver listener. This will only work while the activity is on the foreground, so every time the user enters the activity again you need to reload the list to avoid the case that this intent arrived while not in foreground.
Another way to proceed if you want to listen it while you are not showing your UI is to create a Service that listens to this Intent with the BroadcastReceiver. Again it depends of the moments you need to receive this event.
To sum up:
For foreground UI: onResume to attach and onPause to detach.
For background: use a Service
I implemented a broadcast receiver to update one of my UI activities but my problem is this: when the back button is pressed by the user, android kills the broadcast receiver but when the home button is clicked, the state is retained. What am trying to achieve is retaining the state even after the back buttton is clicked-- onBackPressed() until the user explicitly calls finish(). Any pointers?
You shouldn't rely on your Activity being always accessible to receive the broadcast. Instead, use LocalBroadcastManager to attempt to deliver the broadcast to the Activity, and if it fails - store the update locally and apply it when the Activity is displayed next time.
You need to register your receiver in your onCreate() method and call unregisterReceiver() on onDestroy().
Edit:
You can see #Shiki's answer in here.
It does what you need.
For example, I started an activity, there is a button in the activity
And then I start the background service, this service will check whether the target activity is on foreground, then trigger the click event of that button.
Is it possible to do this?
Why would you trigger a click event of an activity rather than notifying the activity about its results? Try to use local broadcasts which are sent from the service to the activity. The activity registers for that broadcast and in its onReceive of the BroadcastReceiver you'll trigger your onClick method or any other method of your choice. The Receiver is registered in onResume and unregistered in onPause to guarantee that the activity is actually visible.
I would not recommend to use a direct dependency on your activity as this might cause IllegalStateExceptions if in any circumstance your activity is not started or visible at all.
I can strongly recommend you to use eventbus concept like "otto by square" in this case.
you will subscribe to event from the activity this will keep to modularity and will let you do this function
I have an activity named MainActivity and a service named MainService.
In mainActivity i have a button to start the MainService and a textView(lets say- txt1).
And in OnCreate() method of the service i have taken an instance of MainActivity and using that instance i am trying to update the txt1(TextView) of the activity- using setText. Even tried with post() method.
But its showing error. If i am not wrong than i think UI cant be updated from service. Or, i need to bind the service with the activity. right?
So, my question is that why cant i update textView of activity from service?
you probably can just not directly, if you create a callBack reference you can call a method in your activity from the service, but essentially the textView updates are run on the UI thread, so the actual update has to happen in the activity..
This might be helpful: https://developer.android.com/training/multiple-threads/communicate-ui.html
You can do it this way:
sendBroadcast(intent) from service.
register receiver in your activity's onResume() and unregister the same in onPause().
Update textview in onReceive of BroadcastReceiver.
In my application there's a main activity which might be show on the top or in the background, and there's a broast receiver who receive the alarm event.
My main activity and the receiver seems to be two instances, and I can't call a static member in main activity (e.g.listview) to update itself from the receiver. It this correct?
So, how do i notify my current main activity to update itself?
p.s. I don't want to show my main activity if it's not currently on top.
Thanks a lot.
One mechanism I have seen used to provide a good solution is a Broadcast Receiver. You can read more about the solution in the Common Tasks area of the android documentation.
Edit: Although, rereading your question, I'm not positive I have enough information. If your receiver is already in your activity, then you just need to use the runOnUi(Runnable) call from the Activity to allow you to update the UI.