I have listview where i view a list of objects. This list is saved in the internal memory, and will be refreshed when you start your app with a service. But when you open the listviewactivity, i want the listviewactivity to restart if the service is finished loading.
I tried to implement it like this:
in my service class, after it is ready:
sendBroadcast(new Intent("REFRESH_RECEIPT_LISTVIEW"));
and then at the bottom of my ListViewActivity.class:
class DataUpdateReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("REFRESH_RECEIPT_LISTVIEW")) {
//restart code
}
}
}
So this should work, but i don't get how to restart my listviewactivity with the broadcast receiver. To restart an activity you can do something
start new activity, same as old one, finish this one
but how can i do this within the broadcastreceiver context?
And do i need to initialize/start my receiver within my listviewactivity oncreate or so?
thanks!
Related
I had to implement a feature to this app which consists of an Activity and a Service working on the background (it implements Service, not IntentService).
I went through a few tutorials on the Internet that are supposed to work, and they all use LocalBroadcastManager, which by the way is the recommended by Android:
If you don't need to send broadcasts across applications, consider
using this class with LocalBroadcastManager instead of the more
general facilities described below.
I literally lost a day to find out the problem why it wouldn't work for me: it only works if I use Context.sendBroadcast(). and Context.registerReceiver() instead of the LocalBroadcastManager methods.
Now my app is working, but I feel I am going against the best practices, and I don't know why.
Any ideas why it could be happening?
EDIT:
After I wrote this question I went further on the problem. LocalBroadcastManager works through a Singleton, as we should call LocalBroadcastManager.getInstance(this).method(). I logged both instances (in the Activity and in the Service) and they have different memory addresses.
Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be
the same.
Any thoughts on that? (sorry for the long post)
Code samples:
MyService
public class MyService extends Service {
...
// When an event is triggered, sends a broadcast
Intent myIntent = new Intent(MainActivity.MY_INTENT);
myIntent.putExtra("myMsg","msg");
sendBroadcast(myIntent);
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(myIntent);
}
MyActivity
public class MainActivity {
...
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("onReceive", "received!");
// TODO something
}
};
#Override
protected void onResume() {
super.onResume();
registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
// Previously I was trying:
// LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(messageReceiver, new IntentFilter(MY_INTENT));
}
}
I've never used LocalBroadcastManager, but it sounds like you have to register your receiver on there (i.e. lbm.registerReceiver(...), not mycontext.registerReceiver(...)). Are you doing that?
Now I came to another question, shouldn't a Service have the same Context as the Activity that called it? From this article a Service runs on the Main Thread, hence I'd think the Context would be the same.
The Context class is not related to threads. In fact, both Service and Activity are (indirect) subclasses of Context -- so they're their own Contexts! That's why you can use "this" as a Context.
But regardless of which context you send into LocalBroadcastManager.getInstance(), you should be getting the exact same LBM instance out. I can't think of any reason that you wouldn't -- except if you're running the Activity and Service in different processes?
Declaration:
private BroadcastReceiver receiver;
Initialization:
receiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
//todo
}
};
Registration:
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, new IntentFilter("RECEIVER_FILTER"));
context can be any type of Context, you can use the application context.
Unregister:
LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver);
Broadcast:
Intent intent = new Intent("RECEIVER_FILTER");
intent.putExtra("EXTRA", someExtra);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
check out if your Service and Activity are run in different process, LocalBroadcastManager can't apply in different process.(you should see it in AndroidManifest.xml file)
I want to call the activity method from broadcast receiver onReceive method which will be called once the alarm gets triggered.
Below is my Home Activity code snippet
public class HomeActivity extends Activity{
public static HomeActivity mHomeActivity = null;
protected void onCreate(Bundle savedInstanceState) {
}
public void startLocationReporting(){
...........//Logic to start the location reporting
}
public void stopLocationReporting(){
...........//Logic to stopthe location reporting
}
}
Below Broadcast receiver will be triggered based on the alarm we configured
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// Here context is application context not an HomeActivity instance
//Below code works fine when the app is in foreground
if (HomeActivity.mHomeActivity != null) {
HomeActivity.mHomeActivity.startLocationReporting();
}
//Static references are cleared once the app quits.
//How to start location reporting when the app is quitted
}
}
Please help me on this.
How to the call the methods of an Activity from broadcast receiver
once the app is quited?
Calling methods from class by creating object of class which extends Activity class will cause following major issues:
1. token android.os.BinderProxy#43756de8 is not valid; is your activity running? when trying to accessing any service using Activity context with is not running
2. NullPointerException when accessing views in calling methods.
or may other issues are also possible...
Try to implement logic using IntentService :
A. Create separate class with startLocationReporting and stopLocationReporting by passing all required parameters.
By doing this you will access both methods from Activity or from any other components
B. Create a IntentService for doing task and start it when onReceive method called. By this application will do long running task in background so call startLocationReporting and stopLocationReporting by passing all required parameters in IntentService
On receiving a certain event in my Android service, I want to terminate the app from within the service. I know I can call finish in an activity to end it.
Also I understand that service will call stopSelf() on itself to end itself. But I need to terminate the entire app including any particular activity of the app that was visible at that time.
Any ideas?
Try this:
Process.killProcess(Process.myPid());
You can create an BaseActivity with BroadcastReceiver to close all Activities by registering it in onCreate() of BaseActivity and extending all your Activities with BaseActivity.
public static final String EXIT_APP_ACTION = "EXIT_APP_ACTION";
BroadcastReceiver ExitAppBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
Register it in onCreate() for the BaseActivity in your Application using,
registerReceiver(ExitAppBroadcastReceiver, new IntentFilter(EXIT_APP_ACTION));
Then you can fire this BroadcastReceiver from your Service using the Context to close all Activites including Service by calling stofSelf(),
stopSelf()
context.sendBroadcast(new Intent(BaseActivity.EXIT_APP_ACTION));
This is the scenario: i have a BroadcastReceiver that listen to the ACTION_PHONE_STATE_CHANGED, and when it changes it starts a Service. This service make a query con the CallLog, and when something increases i want to show it on several ProgressBar on the MainActivity, but how can i do that?
I was thinking on creating an Application class thats subclasses the MainActivity and the Service, and then i could have the corresponding references, or am i wrong?
Thanks in advance
There are some possibilites:
Your Service can send a brodcast(sendBroadcast) and your activity just need register a broacastReceiver according your implemented on your service. Something like that:
Your service:
Intent intent=new Intent(getApplicationContext(),WebResults.class);
intent.setAction("com.toxy.LOAD_URL");
intent.putExtra("url",uri.toString());
sendBroadcast(intent);
Your Activity:
private class Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context arg0, Intent arg1) {
String url = arg1.getExtras().getString("url");
WebView webview =(WebView)findViewById(R.id.webView);
webview.loadUrl(url);
}
This link can helo you : http://www.vogella.com/articles/AndroidBroadcastReceiver/article.html
The second way is register a listener on your service and notify that listener on your service.
In your service:
void onSomethingHappened()
{
activityListener.notifyProgressBar();
}
void subscribe(YourInterface listener)
{
actibityListener = listener;
}
In you activity, after start you service:
service.subscribe(this);
However, to take the better solution you should take into account your service implementation(type).
This link about AndroidService can be useful.
I have a main Activity A, in which I create a background thread to load data from db. After the loading is done, I want to update the list which might have been already shown in a child activity B (If user has navigated to B in the meanwhile). If user hasnt yet navigated to B, its not an issue.
But how to update B's list once thread in A has finished?
B is a child of A.
Thanks,
Set the list as empty at first .You can take the user to activity B . Store the content of list dataand fill the list using a static list which is empty when the background thread is incomplete. Once loading from db is done called the notifydatasetchanged() method of the list's adapter .
An easy way to implement the background thread would be an asynchronous task . You can define different phases of the asynchronous tasks by overriding the corresponding methods.
Thanks Imran,
I handled it by creating an IntentService in a separate class (inner class was not working), and start it from A. After work is done I fire a BroadCast from the IntentService which B's broadcastreceiver is listening. It updates the list eventually.
Here is the code:
In class A, just start the IntentService in for ex OnCreate():
Intent contactIntent = new Intent(this, ContactLoaderService.class);
startService(contactIntent);
Create IntentService like (in a separate class):
public class ContactLoaderService extends IntentService {
public ContactLoaderService() {
super("ContactLoaderService");
}
#Override
protected void onHandleIntent(Intent arg0)
{
populateContacts();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction(ContactsResponseReceiver.ACTION_RESP);
broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(broadcastIntent);
}
}
In class B I create an inner class which just updates the list like:
public class ContactsResponseReceiver extends BroadcastReceiver {
public static final String ACTION_RESP = "com.a.b.c.ContactsLoaded";
#Override
public void onReceive(Context context, Intent intent) {
mCurrentAdapter.notifyDataSetChanged();
}
}
In B, dont forget to register the receiver. In B's onCreate() method:
IntentFilter filter = new IntentFilter(ContactsResponseReceiver.ACTION_RESP);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new ContactsResponseReceiver();
registerReceiver(receiver, filter);
And the usual service tag in AndroidManifest.xml
<service android:name="com.a.b.c.ContactLoaderService"> </service>