In my app, I need to update the database with some data from the server. The data need not be shown to the user immediately. It is also fine if the new data is shown to the user the next time he uses the app. There is no UI component that needs to be updated now because of this operation. So, I just need to fetch some data from the server in the background, when the app is running.
currently I am using an Asynctask in an activity. But it does not handle configuration changes well. So, I was reading up a bit and came across a few options:
Using Loaders
Using Fragments
Using Asynctask in a fragment
Using static Asynctask
I am a bit new to this and am quite confused what would be the best implementation method for my requirement. Kindly suggest
Just in case it might help someone. What I have done to fix this is:
Use an alarmmanager to setrepeating alarm that would invoke a service at specific intervals to fetch the data. Something like the code below is called the first time the app runs.
Intent i = new Intent(WordListActivity.this, NewData.class);
PendingIntent pint = PendingIntent.getService(
WordListActivity.this, 0, i, 0);
alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarm.setRepeating(AlarmManager.RTC, cal.getTimeInMillis() + 10000,
gap, pint);
Related
I'm making an alarm clock app using PendingIntent and AlarmManager. I know in order to cancel a PendingIntent, you need to recreate it exactly. In my app, much like many other alarm clock apps, there is a list of alarms with a switch to toggle each alarm on/off. When toggled off, I currently recreate the PendingIntent and cancel it using the following:
Intent intent = new Intent(context, MyBroadcastReceiver.class);
String id = this.getId().replaceAll("[^0-9]+", "");
PendingIntent alarmIntent = PendingIntent.getBroadcast(context, id, intent, 0);
alarmIntent.cancel();
The first 3 lines of the code above I believe are unnecessary. When I toggle the alarm, I have access to the custom alarm object which contains the id along with many other details of the alarm. When I'm creating a new alarm, if I store the newly created PendingIntent in the alarm object, I can have access to the PendingIntent used to create the alarm, and just retrieve it and cancel it in 1 line, like this:
this.getPendingIntent().cancel();
I wouldn't have to recreate the intent, get the id, or recreate the PendingIntent from the code shown earlier. This would ultimately save time and resources (not much but it's good practice), so I have a couple questions:
1) Is there anything wrong with storing the PendingIntent in an object and use it later instead of recreating it? It seems like a straightforward answer but I haven't seen anyone do this before.
2) Is there an advantage to recreating the PendingIntent that I'm not aware of?
Thanks!
Is there anything wrong with storing the PendingIntent in an object and use it later instead of recreating it?
Assuming that the underlying Intent doesn't have some massive payload (e.g., Bitmap in an extra), you should be OK.
It seems like a straightforward answer but I haven't seen anyone do this before.
https://github.com/commonsguy/cw-omnibus/tree/v8.7/AlarmManager/Simple, though it's a trivial example.
Is there an advantage to recreating the PendingIntent that I'm not aware of?
It works for cases where you do not have the PendingIntent. Your process does not live forever. If you want to use a cached PendingIntent as an optimization, that's fine, but you need to be in position to create the PendingIntent if it is needed.
I have to develop a simple application that every 5 seconds fetch a json from a server. I know that this will drain the battery but since I don't have control on the server, this is the only solution I have at the moment, so stay with me. (It's a demo app, the final release will be totally different)
What I did:
I created an IntentService and in his onHandleIntent I do the http request and manage the response asynchronously. Reading the docs, the IntentService is preferred to the Service. At the end, as seen in other topics, I use the AlarmManager class to recreate the intentService. That's the method:
private void repeat() {
lastTrigger = System.currentTimeMillis();
alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent serviceIntent = new Intent(this, StatusPollingService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, lastTrigger + UPDATE_INTERVAL, pendingIntent);
}
In my onCreate in my first Activity, I simply start the service:
serviceIntent = new Intent(BaseActivity.this, StatusPollingService.class);
startService(serviceIntent);
My issues:
When I close my application (using back button), the intentService continues to do the requests and recreates itself (as expected), so I have to kill it manually
I'd like to stop to do polling every time my app goes in background and restart when goes in foreground, to limit the battery drain
My other issues:
I implemented a class that triggers a listener when the app goes in background/foreground. I implemented the interface in my BaseActivity and in my IntentService. When the app goes in background, a boolean became false and I don't execute the repeat() method. When I go in foreground, in my method onBecameForeground I simply create the service:
serviceIntent = new Intent(BaseActivity.this, StatusPollingService.class);
#Override
public void onBecameForeground() {
startService(serviceIntent);
}
Going in background there's no problem, but going in foreground multiple intentService are created, one intentService per every Activity I have in that moment (I see it in the log).
My questions:
Is this the best way to do this job? How could I resolve these problems?
If this is the best (or the less bad) way, how can I create a single instance of the IntentService?
Thank you so much for your help
If you only need it in the foreground, then I'd not bother with the alarms. Just post intents every 5 seconds to your intent service using Handler.
Supposedly there should be only one instance of the intent service, so if you post multiple intents for processing, they will get queued and handleIntent will be called in your intent service for each intent. Note that, however, that if your service is processing intents fast enough, then it may finish (and destroyed) before you post another intent - so you'll see multiple instances of the service being created. But there will only be one instance at a time.
Edit: to expand a bit, you will need the alarms when (and if) you'll be polling the server in background, so don't through that code away ;) Handler will keep "freezing up" in background as the OS doesn't count the time while the device was sleeping for the Handler postponed execution.
I need a background service for my android app that every 5 minutes calls a webservice and stores the received data in a database . The webservice is already fully functional and every 5 minutes has new data available. And also how can I make this service make the webcalls at precise times, I need it to make the calls at certain minutes and seconds.
For example it has to make the calls at 12:05:05 and then at 12:10:05 and after that at 12:15:05 and so on. The reason for this is because the webservice has new data at precise times and I want to get it as soon as it is available. What couldbe the best solution for this problem?
You could use the AlarmManager to start an IntentService which calls the webservice.
Here is a good explanation of this technique.
you have to used below code for calling method every 5 minutes.
// some time when u want to run
Date when = new Date(System.currentTimeMillis());
try{
Intent someIntent = new Intent(someContext,MyReceiver.class); // intent to be launched
// note this could be getActivity if you want to launch an activity
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0, // id, optional
someIntent, // intent to launch
PendingIntent.FLAG_CANCEL_CURRENT); // PendintIntent flag
AlarmManager alarms = (AlarmManager) context.getSystemService(
Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP,
when.getTime(),
AlarmManager.INTERVAL_FIFTEEN_MINUTES,
pendingIntent);
}catch(Exception e){
e.printStackTrace();
}
You can learn the fundamentals of services from here. And then learn about REST web services from here.
Also learn about Databases in Android from here.
I am running into a weird situation where I previous has created a pending intent for activity recognition updates
PendingIntent pendingIntent = PendingIntent.getService(mContext, getIntentID(), intent,
PendingIntent.FLAG_UPDATE_CURRENT);
my getIntentID code is
private static int getIntentID(){
if(intentID == 0)
return intentID = (int)(System.currentTimeMillis());
return intentID;
}
I did this because I wanted to be sure the id was unique everytime I stop and start my service.
However now when I am in my intentService reading the activities that are being sent I am pretty sure it is not my most recent pendingintent calling making the request. I believe it is from a previous one. However I don't know how to cancel it since I don't know the id from the previous one.
1. Why don't I know the previous id? well when I cancelled the updates via the remove updates I did use my getIntentID which I thought was working correctly however when I stopped my app, started it again but didnt launch the update() code for the activity recognition, I noticed I was still getting activities, when I used the debugger.
Here is my update request
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(getActivityRecognitionClient(),
Utility.DETECTION_INTERVAL_TIME, pendingIntent())
Here is my remove code
ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(getActivityRecognitionClient(),
pendingIntent())
So my question is, is there a way to cancel all calls period to the activity recog. even if I dont know the pendingintent info?
So my question is, is there a way to cancel all calls period to the
activity recog.
If you refer the API of ActivityRecognitionApi it contains only two methods
https://developers.google.com/android/reference/com/google/android/gms/location/ActivityRecognitionApi
one for requesting updates
requestActivityUpdates(GoogleApiClient client, long detectionIntervalMillis, PendingIntent callbackIntent)
and
second one to remove updates
removeActivityUpdates(GoogleApiClient client, PendingIntent callbackIntent)
both methods need PendingIntent.
So obviously answer is NO.
Hope this will helps you.
Okay there seems to be no way to cancel the pending intents to the activity recog. LIke Nag stated however what I ended up doing was changing the name of my intentservice class and using it instead and keeping track of the pending Id info. Now I don't have any request coming in from previous calls
I'm implementing an app on Android. I've just added a new service that is called on boot-completed. This service creates a new thread that is simply a loop, making something minute after minute. To wait the next minute I used Thread.sleep(60000) but it doesn't work: after the waiting period no other action is performed. It seems that the app is closed or waiting permanentely.
Is there another way to make a loop-service avoiding Thread.sleep? I don't think it is a problem of code because if I call the main method of the service on the app starting it works (it is a problem related to the service)
Thank you in advance
I think the problem is related to the "scan media" of my LG L9 II.. when the "scan media" (I think is about my sd card) is completed all my service are killed (or something like it). Any suggestion?
Consider using AlarmManager to invoke your service. Below example illustrates how to establish repeating events every minute from AlarmManager.
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(getBaseContext(), 0, intent, 0);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), ONE_MINUTE, pending);
Services don't have their own thread, the share the main (UI) thread. If you want to do something every minute, create a new thread and have it do something once a minute.
There is almost never a good reason to use Thread.sleep(...) or explicitly create threads in Android. If you need something to happen every 60 seconds, create a Handler and use its postDelayed(...) methods. You can post a task that will re-post itself each time it runs. Just make sure you cancel it when your app is shutting down.