Im creating a news-like app and I want to know is is possible to start app (ex : 1 time per 1h) to check if new data is available. You know what im talking about, I think. App should start from nowhere, check and finish().
Is this possible? I know that widgets can do it but normal activity or something like this?
Please, help.
Damian.
Yes, It is possible to use an "Alarm Service" in android, and use it to perform some work, at specific intervals.
Here is the link to Alarm Service documentation:
http://developer.android.com/reference/android/app/AlarmManager.html
Here is a sample code which uses Alarm Service
/**
* Method to start background service for server refresh and other tasks.
*/
public void startMyService()
{
//Start Service service to handle data refresh
Intent serviceIntent = new Intent(this, MyCommunicationService.class);
//Schedule additional service calls using alarm manager.
AlarmManager alarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(this, 0, serviceIntent, 0);
//Retrieve time interval from settings (a good practice to let users set the interval).
MyPreferenceManager prefManager = new MyPreferenceManager(this);
alarmManager.cancel(pi);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), prefManager.getDataRefreshTime()*1000 , pi);
}
Note that we are multiplying with 1000, because the parameter for setRepeating() method is in milliseconds.
Related
Following code works perfectly for Activity:
Intent intent = new Intent(context, MyActivity.class);
PendingIntent operation = PendingIntent.getActivity(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
However, when I do the same thing for IntentService, It works only if startTime and time I set alarm are on the same day. e.g. If I set the alarm today for 5 PM, it will be executed but when I set the alarm today for 5 PM tomorrow, it will not be executed. If this was Activity then it works for both cases.
Intent intent = new Intent(context, MyService.class);
PendingIntent operation = PendingIntent.getService(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
How to solve this?
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
Google has made this progressively harder from release to release. See Android AlarmManager setExact() is not exact. There could be two ways to solve this for your case:
you start an activity, which starts the service (as starting an Activity seems to work for you)
you use either setExactAnd... or setAlarmClock. setAlarmClock also triggers in the new "doze" mode, see https://stackoverflow.com/a/47049705/1587329.
Another way would be to re-think why and if you really need this... or if a JobScheduler could not fit your purpose more easily.
add replace your line with this line :
alarmmanager.setRepeating(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
it will repeat on specific interval you set in alarm manager
Replace the AlarmManager with this code:
alarmManager.setRepeating(AlarmManager.RTC,
timeMills,
AlarmManager.INTERVAL_DAY,
pendingIntent);
Worked for me.
HERE IS a DETAILED ANSWER check link in the bottom for more details.
Hope this will help. Your issue can be probably related to android versions too so do check the link for more details
app gets an instance of the AlarmManager and sets an alarm using a PendingIntent. More on usage and setting alarms is coming in the next section. The AlarmManager is the app side interface to the backing AlarmManagerService. It abstracts the details of the Binder interface, used to communicate with the system process (system_server) hosting the AlarmManagerService. These two components manage the alarm(s) the app has set and will send the PendingIntent correctly. This manager/service architecture is used throughout Android framework and is done for security and isolation purposes. The system_server process is running with privileges which normal apps do not have. If you are unfamiliar with Android’s use of permissions, see this article for more details on app processes and user IDs. These extra permissions are what allows system_server to access the underlying kernel alarm driver. The alarm driver is what manages setting alarms to wake up the device regardless of the sleep state of the SoC.
When the alarm is triggered the device is awakened (if asleep) and the AlarmManagerService is notified of an alarm expiring. It will then send the PendingIntent accordingly. This will cause the appropriate component within MyApp to be activated. If MyApp has not been started or its process is not cached, it will be started so the component can be activated.
basic usage will be as
public class MyActivity extends Activity {
...
private AlarmManager mAlarmMgr;
...
public void onCreate(Bundle savedInstance) {
...
mAlarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
...
}
...
}
let’s create a PendingIntent for our MyActivity using the component name.
Intent alarmIntent = new Intent(context, MyActivity.class);
PendingIntent pend = PendingIntent.getActivity(context,
0,
alarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Now that we have our PendingIntent and the AlarmManager, we can set our alarm so our Activity is triggered when the alarm has expired. To do this, we need to figure out when we want our alarm to go off and whether it should wake up the device or just be delivered the next time the device is awakened. Remember, we have two different ways of specifying time for our alarms: elapsed time or calendar (RTC) time. So our options are ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or RTC_WAKEUP. The _WAKEUP variants are our “aggressive” alarms where we want the device to come out of low power to call our app back. For our sample app, let’s set this up in a custom BroadcastReceiver and have it trigger our Activity about 30 seconds after the device is booted
public class MyBootReceiver extends BroadcastReceiver {
public void onReceive(Context, context, Intent intent) {
...
AlarmManager alarmMgr =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long wakeTime = SystemClock.elapsedRealtime() + 30000;
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeTime, pend);
}
}
Now when our device boots and the BOOT_COMPLETED broadcast is sent, our app’s process will be started and our receiver will set an alarm to trigger our Activity to be launched about 30 seconds later. Note that on Android 3.1 devices or newer, you must first manually launch your app before the BOOT_COMPLETED.
CREDIT GOES to writer of this BLOG
if you want to set the repeated alarm using SetExact you are bound to stop all other pending intents on the same time check this link for that here are many examples of how to do it! again credit goes to this writer
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 want to open my application automatically with some intervals if user destroy my application.How can i create this.I don't know how to create this Please anybody help me..
Use AlarmManager:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Replace MyActivity.class with the activity class you want to run periodically
Intent i = new Intent(context, MyActivity.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
long now = System.currentTimeMillis();
long interval = 60 * 60 * 1000; // one hour
am.setRepeating(AlarmManager.RTC_WAKEUP, now, interval, pi);
Also, add this permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
What you can do is, Use background service.
from service you can start your application as required.
use this from service
Intent intent = new Intent(getBaseContext(), myActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplication().startActivity(intent);
for service reference
http://www.vogella.com/articles/AndroidServices/article.html
Use alarm manager (AM) or GCM. With AM you can set timer and start your app in some interval. Via GCM you can send notifications from your server and run some actions.
Using service isnt a good idea. AM and GCM is more reliable way. I think AM is what you need.
P.S. Dont do it. Users will curse you )
I'm usign an Alarm Manager to update a widget with a Service. I've two different questions.
First question: I'm calling the service with Alarm Manager's intent. Like this:
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
context.startService(new Intent(context, MyService.class));
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
Is it wrong?
It looks and works right. But when I have looked at working services, I can't see my service name in the list. Perhaps it's not running as a single/seperate service. Just saw application name (not as a service). I'm not sure how to seperate or does it matter?
Another question: Over long time, running application, which controls widgets update, is closed somehow (manually or by a task killer). Of course Alarm Manager gonna stop and widget's functions gonna stop too. For example button clicking.
But, Twitter solved this problem. While the widget is active, if I close the main application (Twitter) -which controls widget- than click the widget, somehow widget triggering application and it starts again well. So buttons work properly. How is that possible?
Any help would be appreciated.
You dont need to do context.startservice that what the pending intent is for, if you want the service to run right away the first time just set it to run at the current time then set the interval from the current time.
You are also setting 2 different types of repeating when you don't need to setRepeating is strict where setInexact is not and can be adjusted by the OS when it gets fired hence the inexact in it. You want one or the other not both.
Also those intervals are very small and its going to kill the battery significantly.
It should just be this
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
It's good that your application/service isn't running all the time.
In fact it doesn't need/has to run all the time for updating a widget. If you schedule an Intent with AlarmManager the application will be started when the intent is fired if it has been closed.
When setting a service to go off at particular time, I use the AlarmManager system service.
Everything goes off without a problem, service is called and actions take place.
When the alarm time is reached, the service starts, and at this point I get the system time (System.currentTimeMillis()). I'm guessing this wont be the actual time the service start. Is there a way to get the time that was set for this PendingIntent?
ie
Set alarm for 9am.
DoStuffService starts at 9am.
DoStuffService knows it was supposed to start at 9am, and uses this value for future functions.
When you create an intent for your alarm, you could put extra data, including time of the alarm, into it like this:
Intent intent = new Intent("action name");
//put extra data into the intent:
intent.putExtra("alarm_time_hours", hours);
intent.putExtra("alarm_time_minutes", minutes);
PendingIntent sender = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
Then in your receiver or service you need to get this extra data from received intent. Use something like this:
Bundle bundle = intent.getExtras();
if(bundle.containsKey("alarm_time_hours")) {
int hours = bundle.getInt("alarm_time_hours");
}
if(bundle.containsKey("alarm_time_minutes")) {
int minutes = bundle.getInt("alarm_time_minutes");
}
Is there a way to get the time that was set for this PendingIntent?
No, sorry.
However, it should not be terribly difficult for you to determine it yourself. Following your example, if your service reports that it is now 09:00:02.36, you should be able to round down to determine that this is the 9am alarm.