I am trying to create an Android app that increments a counter after every 24 hours. I am just making use of SharedPreferences and when it is time it increments the value in shared preferences. Right now I made use of FirebaseJobDispatcher but the problem with this was that it is inconsistent in incrementing. I read through some documents and my understanding is that it is better to use FirebaseJobDispatcher when it involves some network calls as well. My question is that how can I schedule a simple job in android to run every 24 hours? Please any help and suggestions would be very helpful. Below is my FirebaseJobDispatcher code. Right now I am just using using 2 minutes just for checking purposes.
public class ScheduleIncrementJob {
private static final int UPDATE_INTERVAL_MINUTES = 2;
private static final int UPDATE_INTERVAL_SECONDS = (int)(TimeUnit.MINUTES.toSeconds(UPDATE_INTERVAL_MINUTES));
private static final int SYNC_FLEX_SECONDS = UPDATE_INTERVAL_SECONDS;
private static final String UPDATE_JOB_TAG = "update_counter_tag";
private static boolean sInitialized;
synchronized public static void scheduleUpdateCounter(final Context context){
if(sInitialized)return;
Driver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);
Job constraintUpdateJob = dispatcher.newJobBuilder()
.setService(IncrementJobService.class)
.setTag(UPDATE_JOB_TAG)
.setLifetime(Lifetime.FOREVER)
.setRecurring(true)
.setTrigger(Trigger.executionWindow(UPDATE_INTERVAL_SECONDS,
UPDATE_INTERVAL_SECONDS + SYNC_FLEX_SECONDS))
.setReplaceCurrent(true)
.build();
dispatcher.schedule(constraintUpdateJob);
sInitialized = true;
}
}
You can use AlarmManager class to schedule a repeating alarm with PendingIntent that will do your job when scheduled.
https://developer.android.com/training/scheduling/alarms
I'll give you sample of dailyAlarm doing some job when fired:
public void setDailyAlarmOn(Context context, long alarmTime, Uri reminderTask, long repeatTime) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent operation =
yourJobHere.getReminderPendingIntent(context, reminderTask);
if (Build.VERSION.SDK_INT >= 23) {
manager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, repeatTime, operation);
} else {
manager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime, repeatTime, operation);
}
}
alarmTime - first time in miliseconds when alarm is supposed to be fired
repeatTime - time in mili seconds - 86400000 for 24h (1000*60*60*24)
Uri reminderTask - uri that I created to not to cancel previous alarms, in short, it's a code for alarm application and it's uri from row in database.
operation - PendingIntent which you'll need to create
I did it by extending IntentService and handling job in onHandleIntent:
YourJobHere.class:
public class YourJobHere extends IntentService {
private static final String TAG = YourJobHere.class.getSimpleName();
public static PendingIntent getReminderPendingIntent(Context context, Uri uri) {
Intent action = new Intent(context, YourJobHere.class);
action.setData(uri);
return PendingIntent.getService(context, 0, action, PendingIntent.FLAG_UPDATE_CURRENT);
}
public YourJobHere() {
super(TAG);
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
//TODO: make your job here
}
}
If you want you can refer to my full project on GitLab:
https://gitlab.com/Domin_PL/SlothProfileScheduler
Hope it'll help you
Related
I am trying to set an alarm to call a method in MainActivity. I have used the method described here; the alarm fires but once it does it repeats about once a second.
I am using setExactAndAllowWhileIdle since the alarm is needed only every hour or so (actually it doesn't need to be exact, I could use setAndAllowWhileIdle instead but that gives the same problem).
My Alarm class is pretty simple:
public class Alarm extends BroadcastReceiver
{
static MainActivity main = null;
public Alarm()
{
}
public Alarm(MainActivity ctx)
{
main = ctx;
}
#Override
public void onReceive(Context context, Intent intent)
{
if (main != null)
main.alarmAction();
}
}
In OnCreate() for MainActivity I have
alarmReceiver = new Alarm(this);
IntentFilter alarmFilter = new IntentFilter("Alarm");
registerReceiver(alarmReceiver,alarmFilter);
and then I have methods:
public void SetAlarm() {
alarmStarted = true;
Intent i = new Intent(this, Alarm.class);
i.setAction("Alarm");
PendingIntent pi = PendingIntent.getBroadcast(this, 1001, i, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.cancel(pi); // tried this to solve the problem but probably not needed
am.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, 1000 * 60 * 10, pi);
}
public void alarmAction() {
if (!alarmStarted)
return;
SetAlarm();
// will be more stuff here but this is minimum required to show problem
}
The flag alarmStarted is set from a button press.
Android Studio is giving me a memory-leak warning about the use of static in static MainActivity main = null, but without this main is always null in onReceive. I don't know if the repeating alarm issue is connected with this or not.
I'm developing an app that synchronize your local date with the cloud. So I need to check automatically, each 10 minutes, my local data to get the new camera files to upload to the cloud.
So I have used an IntentService that works only when the app is running in foreground. If I close it, my service doesn't upload anything.And I WANT MY INTENTSERVICE WORKS IN BACKGROUND with the AlarmManager.
My IntentService is declared in Manifest.xml:
<!-- Uploader and Deleter Files Service -->
<service android:name=".receiver.UploadDeleteService" android:exported="false" />
<receiver
android:name=".receiver.AlarmReceiver"
android:process=":remote" >
</receiver>
My AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
public static final String ACTION = "com.codepath.example.servicesdemo.alarm";
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, UploadDeleteService.class);
context.startService(i);
}
}
My ServiceInteractor where I instance my AlarmReceiver inside AlarmManager:
public class ServiceInteractorImpl implements ServiceInteractor {
private Context context;
public ServiceInteractorImpl(Context context){
this.context = context;
}
#Override
public void launchService() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(context, AlarmReceiver.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(context, AlarmReceiver.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 5 seconds
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
// Interval can be INTERVAL_FIFTEEN_MINUTES, INTERVAL_HALF_HOUR, INTERVAL_HOUR, INTERVAL_DAY
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, 10);
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis,
cal.getTimeInMillis(), pIntent);
}
}
My UploadDeleteService where I call to the retrofit implementation module:
public class UploadDeleteService extends IntentService implements ApiConnector.GetObjectListener {
private RemoteInteractor remoteInteractor;
public UploadDeleteService(String name) {
super(name);
}
public UploadDeleteService() {
super("UpdateDeleteService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i("SERVICE", "Service running");
remoteInteractor = new RemoteInteractorImpl(getApplicationContext());
remoteInteractor.checkNews(this);
}
#Override
public void onImageUploaded(String type, JSONObject response) {
Log.d("SERVICE", " onImageUploaded ");
//REST OF THE STUFF....
}
}
Please I need a helping hand to solve that problem. I need it works each 10 minutes although the app is closed. Thanks!
For stopped Service:
change "cal.getTimeInMillis()" to "10*60*1000"
cal.add(Calendar.MINUTE, 10); //this will add 10 minute to current time
For Stopped open app when service start:
normally it will not open your app, you need to check what happened in RemoteInteractorImpl.class
you create new instance at onHandleIntent
remoteInteractor = new RemoteInteractorImpl(getApplicationContext());
remoteInteractor.checkNews(this);
I want to make a background running service (independent of an app) which would download weather data from server periodically every day. I already have code to download data from the server and store it in the database.
What I would like to know is, what is the best way to run the service periodically.
You can Create a Android Intent Service :-
public class BackendService extends IntentService {
public BackendService() {
super("BackendService");
}
#Override
protected void onHandleIntent(Intent intent) {
// Your Download code
}
}
Then set a Alarm Receiver to set the interval in which service will be called.
public void backendscheduleAlarm() {
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), BackendAlarm.class);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(this, BackendAlarm.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every 1 hour
long firstMillis = System.currentTimeMillis(); // first run of alarm is immediate
int intervalMillis = 3000; //3600000; // 60 min
AlarmManager backendalarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
backendalarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, intervalMillis, pIntent);
}
And Create a Broadcast Receiver class to call that service:
public class BackendAlarm extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, BackendService.class);
i.putExtra("foo", "bar");
context.startService(i);
} }
read about Android Services which are mainly made for such background work:
http://developer.android.com/guide/components/services.html
all you need is to start the service on a certain time you set.
My app needs to do some background task after boot completed and also in sleep mode.
So I'm using WakefulIntentService to avoid flow problem in sleep mode and it works well.
But when I'm trying to use the boot receiver for continuing data flow after boot completed it gives some strange error and also not working sometimes.
Here is my Boot Receiver class where I am trying to do multiple task.
public class OnBootReceiver extends BroadcastReceiver {
private static final int SERVICE_PERIOD = 300000; // 5 minutes currently
// private static final int HANDLER_PERIOD = 300000 * 12; // 1 hour
// currently
private static final String TAG = "OnBoot";
private Context mContext;
private int mInterval = 1000 * 60 * 60 * 2; // 2 hours by default, can be
// changed later
private Handler mHandler;
#Override
public void onReceive(Context context, Intent intent) {
mContext = context;
AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OnServiceReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60000, SERVICE_PERIOD, pi);
mHandler = new Handler();
startRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#SuppressWarnings("unchecked")
#Override
public void run() {
SharedPreferences mSharedPreferences = mContext
.getSharedPreferences(KEY_USER_ID, 0);
String UserId = mSharedPreferences.getString(KEY_USER_ID, "0");
new SyncValidater(mContext, UserId).execute();
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}
In this class I have written two tasks. the first one is starting another broadcast receiver which starts the wakeful service(same as github example). And the second one starts one handler which starts one AsyncTask class to do some server transaction in every two hours. But sometimes the handler starts in random time and sometimes stop.
So here I'm confusing that is my app requires two boot receivers ?
is there any other option to do these multiple tasks in the current receiver ?
please help. Thanks
And the second one starts one handler which starts one AsyncTask class to do some server transaction in every two hours
No, your second task will run once and probably never again, because your process is terminated in the meantime.
So here I'm confusing that is my app requires two boot receivers ?
No.
is there any other option to do these multiple tasks in the current receiver ?
Use two AlarmManager events, each with their own period. One is your current AlarmManager event. The other is one you create in support of your every-two-hour work to be done.
I want to call a specific patch of code regularly after 60 seconds to get the updated data in the application. I am wondering where i should put the code in the Main Android activity. Any help will be appreciated
thanks
You can use Timer Class of Java's util package. It will allow you to execute a specific code again & again on a regular interval. Have a look at the example which executes on every 5 seconds.
use services and broadcast receivers in android.
// Restart service every 30 seconds
private static final long REPEAT_TIME = 1000 * 30;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyStartServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
// Start 30 seconds after boot completed
cal.add(Calendar.SECOND, 30);
//
// Fetch every 30 seconds
// InexactRepeating allows Android to optimize the energy consumption
service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), REPEAT_TIME, pending);
refer this site for more information.
http://www.vogella.com/articles/AndroidServices/article.html
import android.os.Handler;
public class ExecuteEveryMinuteExample {
private static final int DELAY_IN_MILLIS = 60000;
private final Handler handler;
private final Runnable task;
public ExecuteEveryMinuteExample(Handler handler, Runnable runnable) {
this.handler = handler;
this.task = new Task(runnable);
}
public void start() {
handler.postDelayed(task, DELAY_IN_MILLIS);
}
public void stop() {
handler.removeCallbacks(task);
}
private class Task implements Runnable {
private Runnable task;
private Task(Runnable runnable) {
this.task = runnable;
}
#Override
public void run() {
task.run();
start();
}
}
}
This "timer" is associated with Activity lifecycle, remember to stop it in Activity#onDestroy or better in Activity#onPause. Also checkout Timer, ScheduledThreadPoolExecutor and TimerTask they may suit your needs better.