Android schedule PeriodicWorkRequest only for n times - android

Android Periodic work will run periodically but i need to schedule a task within specific time. Suppose i want to run a task every day for 20 days only. I didn't find any way to do that.
How can i do that?

The offered API allows to cancel a work unconditionally:
If you no longer need your previously enqueued work to run, you can ask for it to be cancelled. Work can be cancelled by its name, id or by a tag associated with it.
But you can use your favorite storage to tack the number of days until they reach to 20 days. And every time the work is performed; i.e. when the doWork() callback gets called; you can increment the no. of days.
Here's an example of SharedPreference:
public static final String WORK_TAG = "WORK_TAG";
public static final String DAY_NO = "DAY_NO";
#androidx.annotation.NonNull
#Override
public Result doWork() {
SharedPreferences prefs = getApplicationContext().getSharedPreferences("prefs", MODE_PRIVATE);
int dayNo = prefs.getInt(DAY_NO, 1);
if (dayNo == 23) {
// cancel the work
WorkManager.getInstance(getApplicationContext()).cancelAllWorkByTag(WORK_TAG);
Log.d(TAG, "The periodic work has been stopped");
} else {
// Increment the number of days
dayNo++;
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("DAY_NO", dayNo);
editor.apply();
// Do your work here
}
return Result.success();
}
Make sure that you tag the work with the same tag when you initialize the workRequest:
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
MyWorkerclass.class, // Worker class
.......
.addTag(WORK_TAG)
.build();
Also notice that any other work with the same tag will be cancelled as well, so make sure it's a unique tag.

Related

Writing Firebase database after app is swiped from recent list

I need to write three items of data in Firebase Realtime Database in case the user kill the app
from recent list while it's still running; I implemented a service in order to
update the database when onTaskRemoved is called.
In the manifest the service is declared with the option android:stopWithTask="false"
Here is the service
public class ServiceAppMonitoring extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
FirebaseDatabase mDatabase = FirebaseDatabase.getInstance();
SharedPreferences mSettings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
//Get some datas from Shared Preferences...
String path1 = "first/node/path";
mDatabase.getReference(path1).setValue(false);
if (condition) {
// Compose array of datas
List<Object> data2 = Arrays.asList(new Object[]{ ... });
String path2 = "second/node/path";
mDatabase.getReference(path2).setValue(data2);
// Compose array of datas
List<Object> data3 = Arrays.asList(new Object[]{ ... });
String path3 = "third/node/path";
mDatabase.getReference(path3).setValue(data3);
stopSelf();
} else {
stopSelf();
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) { return null; }
}
Strangely only the first instruction is successful, the other two seem to be ignored... at least no data is written into database.
Further I've noticed another "unusual" behaviour, if I arrange all the DatabaseReferences in the
following way:
mDatabase.getReference("first").child("node").child("path").setValue(false);
no one of the instructions end up writing into database, to get (at least) the first one working I've to arrange this way:
mDatabase.getReference("first/node/path").setValue(false);
Can anybody kindly help me to understand why this happens?
Thanks
This is almost certainly because Firebase operations are asynchronous, and return immediately before the writes are complete. onTaskRemved is going to return before either of the database writes fully finish.
I'm guessing that your app process is going to die very soon, if not immediately, after onTaskRemved returns. This means that your database writes might not finish. Android doesn't know that these writes are pending, and it's not going to wait for them.
Since you don't have way from your service to tell Android to wait for these writes, you will have to schedule them for later. I suggest looking into using WorkManager to schedule the writes to happen in the background, whenever Android allows it. It might not be immediate, but WorkManager will make sure that any scheduled tasks will eventually complete.
Hey based on your answer I updated a small thing on database from onTaskRemoved like this
I already initialized the DatabaseReference in the onCreate method
DatabaseReference temp = FirebaseDatabase.getInstance.getReference().child("temp");
and in onTaskRemoved
temp.setValue(true);
this is getting executed and I added a onchange listener in onCreate method to listen for this values change and it worked like a charm. If you don't understand anything feel free to ask and let me know how you got over this problem:)
EDIT:
This is not working in all devices...
EDIT AGAIN: I simply used on Destroy method in my service and killed the service after completing the task and is working for now...
EDIT AGAIN AND AGAIN: OnDestroy is not working in android 6 or below I guess. I tested in Android 6 and it didnt work.

i need to schedule 2 tasks at diffrent times

i try to schedule 2 tasks, the first need to done everyday - to check birthdays,
the second task need to be only if today is the first day of the month..
i tried to make 1 schedule that will done everyday at 8:00 am , and when its done to check if its the first day of month.
if its true make the method of the second task.
my problem is that the method starts every time that onCreate() done & its the first day t the month, so if i open the app 10 times at the 1/10/16 , the method will happen 10 times, instead of 1 time.
my code:
onCreate()
startTimers();
startTimers method:
private void startTimers() {
d = new Date();
d.setTime(System.currentTimeMillis());
d.setHours(8);
d.setMinutes(0);
d.setSeconds(0);
timer = new Timer();
timerTask = new TimerTask() {
#Override
public void run() {
if(d.getDate() == 1){
// TODO: 19/10/2016 find good if that will make it work only 1 time per month..
saveSalariesBeforeStartNewMonth();
resetSumOfMinutes();
Log.d("TAG","Started new Month good luck!##!#");
}
checkBirthdays();
}
};
timer.schedule(timerTask,d.getTime(),1000*60*60*24);//every day at 8:00 at morining..
}
Thank for helpers.
Try to store a simple boolean to the SharedPreferences after successfully scheduling so that before you call startTimers() just check with the stored value. Sth like:
public void onCreate(){
if (!isScheduledAlready()) {
startTimers();
}
}
public boolean isScheduledAlready(){
SharedPreferences prefs = getPrefs().getPreferences();
return prefs.getBoolean("schedule_keys", false);
}
public void setSchedule(boolean scheduled) {
SharedPreferences prefs = getPrefs().getPreferences();
prefs.edit().putBoolean("schedule_keys", scheduled).apply();
}
Also I'm not sure if in your situation you might want to tweak the value when the month change? If then you can just need add more a bit more conditions I guess.

Make a POST call every 10 seconds for an infinite time?

How can I make a certain function execute after every 10 seconds for an infinite time?
What I have done till now: I am getting the location values of the user from the App and storing them on the server. I am using a service, so that, the code keeps running for an infinite time, I am using a Broadcast receiver, so that, if the phone is booted, the service should start again and starts sending me the location.
The issue Everything works perfectly fine for about first 10-15 minutes, but, after this, the service gets stopped by itself. Also, when the user signs up for the App, authorized tokens are generated. These tokens are also sent in the POST call as one of the parameters, for security purposes. Even these tokens are lost, despite working perfectly fine for the initial 10 minutes. I am storing these tokens in SharedPreferences. Any help in this regard would be highly appreciated.
Code for SharedPreferences
Log.i("onCreate", "onCreate");
Log.i("atoken value", ConfirmToken.avalue);
Log.i("utoken value", ConfirmToken.uvalue);
atoken = ConfirmToken.avalue;
utoken = ConfirmToken.uvalue;
Log.i("atoken value", atoken);
Log.i("utoken value", utoken);
Log.i("Starting SharedPref", "Starting SharedPref");
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
SharedPreferences.Editor editor = settings.edit();
editor.putString("atoken", atoken);
editor.putString("utoken", utoken);
editor.commit();
if (settings.contains("atoken")) {
atoken = settings.getString("atoken", "nulll");
Log.i("Inside SharedPref", atoken);
}
if(settings.contains("utoken")) {
utoken = settings.getString("utoken", "nulll");
Log.i("Inside Sharedprefs", utoken);
}
//Calling UpdateData here so that values of lat, lng get updated, before they are used by MyService.java
UpdateData();
startService(new Intent(this, MyService.class));
Now, the update data function simple makes a POST call, using these tokens and Location values as parameters.
This is how I run a task every few seconds. Note that it runs in another thread, so accessing UI elements needs runOnUiThread call, but since you are in a service, you will not have any issues with that.
private ScheduledThreadPoolExecutor taskExecutor;
private void stopTimerTask() {
if (taskExecutor != null)
taskExecutor.shutdownNow();
// keep one task at any given time
taskExecutor = new ScheduledThreadPoolExecutor(1);
}
private void startTimerTask() {
stopTimerTask();
taskExecutor.scheduleWithFixedDelay(Timer_Tick, TIMER_INITIAL_DELAY, TIMER_PERIOD, TimeUnit.MILLISECONDS);
Log.d("Pool", "Timer Task Running");
}
private Runnable Timer_Tick = new Runnable() {
#Override
public void run() {
// Do something
}
};
You should however be aware that Android OS may terminate your service at any time when running low on resources or it feels like the service is doing too much work. You should start focusing on how to restore it's state, just like every one else does.
I think the following is the easiest way.
Also remember if you are making a network call, make an asynchronous request so that your app doesn't stop working while your app waits for the response.
for(long startTime = new Date().getTime();new Date().getTime() - startTime ==10000; startTime++)
{ /*your code goes here*/ };
No matter what you do, if the system is low on resources, it will terminate your app.Please let me know weather this works for you or not :)

How do I get an Android app to run a method daily?

I need an ad screen(revmob) to show once daily when called from the onCreate method. I grabbed the idea from How do I get an Android application's method to run a method daily with Eclipse? but it is not working since the ad is loading every time the onCreate is called.
The code I have is:
if(runOnceDaily()){
revmob = RevMob.start(this, REVMOB_APP_ID);
revmob.showFullscreen(this);
}
private boolean runOnceDaily(){
boolean result = false;
SharedPreferences prefs = this.getSharedPreferences(
"com.blogspot.blog.myapp", Context.MODE_PRIVATE);
long minStartTime = System.currentTimeMillis() - 1000*60*60*24;
long lastTimeRan = prefs.getLong("lastTimeRan", -1);
if (lastTimeRan >= minStartTime) {
// a day passed.
//also save the new 'lastTimeRan' in prefs
result = true;
prefs.edit().putLong("lastTimeRan", System.currentTimeMillis()).commit();
}
return result;
}
You can use AlarmManager to run a Method daily
Use Alarmmanager with BroadcastReceiver class.
Call your method which needs to be run everyday in the OnReceive method of receiver.
This method would be very easy.

android show an activity for every 24 hrs

in my app next to the splash screen i need to show an activity called Tips Page. This activity to be shown once in a day. When the user opens the app again within 24 hrs it should not be shown.
First i tried to show based on the current date, when the first the activity shown i will store the current date in shared preference and next time when the app gets opened i will check whether the current date and date in shared preference are equal or not. If equal i will not show the activity if not i will show the activity.
But here there is a logic mistake, if the user opens the app first in midnight of 11 PM in a date, and again opens the app after t hour the Tips activity will be shown, but i need to show it after 24 hrs, how can it be done. pls help me in this ligic
I think you need such a flow, see this the implementation of Jason Hessley's Answer
SharedPreferences settings = getSharedPreferences("Preferences",
MODE_PRIVATE);
long timeFromPrefs = settings.getLong("time", System.currentTimeMillis());
final long TIME_DIFF = 24*60*60*1000;
if ((System.currentTimeMillis()-timeFromPrefs)>TIME_DIFF) {
// show Activity...........
Editor editor = settings.edit();
editor.putLong("time", System.currentTimeMillis());
editor.commit();
}
Android applications can run periodic timers using android.os.Handler & java.lang.Runnable classes. As simple example is shown below.
Key Points
1. Service classes extending android.app.Service should implement onBind, onCreate & onDestroy, life cycle methods.
2. periodicTask is an instance of Runnable implementation, that runs a Thread. Execution of run() will print the message "Awake".
3. mHandler is an instance of Handler, that is attached the periodicTask thread.
4. The Handler is informed to execute the thread every minute, by postDelayed.
5. When the service is destroyed, the periodicTask instance is removed from the Handler, by invoking removeCallbacks.
Sample Code
public class PeriodicTimerService extends Service {
private Handler mHandler = new Handler();
public static final int ONE_DAY = 86400000;
private Runnable periodicTask = new Runnable() {
public void run() {
Log.v("PeriodicTimerService","Awake");
mHandler.postDelayed(periodicTask, ONE_DAY );
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
mHandler.postDelayed(periodicTask, ONE_DAY );
}
#Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(periodicTask);
Toast.makeText(this, "Service onDestroy() ", Toast.LENGTH_LONG).show();
}
}
Save the last time the activity was started in a shared pref as you stated in your question. Then subtract the last time from the current time. If it is greater then 24 hours, show your tips.

Categories

Resources