I want to clear my shared preferance field phonenumber exactly at 12 am in broadcast receiver. How will I do that ?
Here is my code ...
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences prefs = context .getSharedPreferences("connect", Context.MODE_PRIVATE);
String username = prefs.getString("phonenumber", null ) ;
}
}```
Alarm Manager
The Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing.
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
synchronized public void run() {
preferences.edit().putString(key, "").apply()
}
}, TimeUnit.MINUTES.toMillis(1), TimeUnit.MINUTES.toMillis(1));
ScheduledThreadPoolExecutor.
You can use java.util.Timer or ScheduledThreadPoolExecutor (preferred) to schedule an action to occur at regular intervals on a background thread.
ScheduledExecutorService scheduler =
Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate
(new Runnable() {
public void run() {
// call the preferences clear logic
}
}, 0, 10, TimeUnit.MINUTES);
EDit:
You can actually save the install time and then do a calculation to see if a week has elapsed. If it has clear the shared preference
//First time
long installed = context
.getPackageManager()
.getPackageInfo(context.getPackageName(), 0)
.firstInstallTime;
Ref:More on periodic event handling
Get install time and clear shared preference
Related
I have this Runnable method which send a notification once it is called and every minute sends a JSON Post on an HTTP Server. So i coded the method "sendNotification" to keep informed the user regards the "service" is running but when I close the app, the method to send the JSON stops and the notification stays active on the notification bar. I would like to close the notification as well.
//Runnable methods for frequency position
private final Runnable oneMinuteRunnable = new Runnable() {
#Override
public void run() {
sendNotification();
getTimestamp();
new Thread(new Runnable() {
#Override
public void run() {
getLocation();
doPostRequest();
}
}).start();
handler.postDelayed(this, 60 * 1000);
}
};
This is the notification method
//Make notification when the frequency service is running
public void sendNotification() {
Notification notification = new NotificationCompat.Builder(this, com.example.httptracker.Services.Notification.NOTIFICATION_ID)
.setSmallIcon(R.drawable.ic_baseline_run_circle_24)
.setContentTitle("AMP Tracker")
.setContentText("Tracker is running")
.build();
compat.notify(1, notification);
}
I looked up online and I saw only solutions with a Service class but I would need to develop a "stop service" button to cancel the notification. But it is not what I need. The notification should disappear once the app is closed or the method killed.
Thanks in advance
try to cancel your notification with:
compat.cancel(1); // assuming compat is NotificationManager instance, 1 is your id
in e.g. onDestroy of Activity or any place when your app is stopping oneMinuteRunnable looped execution
I have been trying to write a metronome in Android however I am finding really hard to sync the beats accurately using the Handler postdelayed method. I manage to achieve an accurate timing using a ScheduledThreadPoolExecutor, but the issue is that with the ScheduledThreadPoolExecutor I can't control the timing from within the run method and therefore I am forced to stop and start the scheduled job, which is not ideal. Is there a way to make the Handler postdelayed more accurate? or a way to reschedule the ScheduledThreadPoolExecutor without having to stop and start the thread?
My current code is as below:
public class Metronome extends Service implements Runnable
{
private Handler handler = new Handler();
private SoundPool soundPool;
private long interval;
private void initSoundPool()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
soundPool = new SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.build();
} else
{
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
soundId = soundPool.load(context, R.raw.secondary_clave, 1);
}
#Override
public void run()
{
handler.postDelayed(this, interval);
soundPool.play(soundId, 1, 1, 0, 0, 1);
}
public void start()
{
handler.post(this);
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
With the ScheduledThreadPoolExecutor it's super accurate, however, I don't have control via the "interval" flag inside the run loop, so if I change the interval I have to terminate the executor and start a new one everytime I need to rechedule which is horrible.
public class Metronome extends Service implements Runnable
{
private SoundPool soundPool;
private long interval;
private ScheduledThreadPoolExecutor beatsPerBarExec;
private ScheduledFuture<?> futureThread;
private void initSoundPool()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
soundPool = new SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.build())
.build();
} else
{
soundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
}
soundId = soundPool.load(context, R.raw.secondary_clave, 1);
}
#Override
public void run()
{
soundPool.play(soundId, 1, 1, 0, 0, 1);
}
public void start()
{
beatsPerBarExec = new ScheduledThreadPoolExecutor(1);
futureThread = beatsPerBarExec.scheduleAtFixedRate(this, 0, interval, TimeUnit.MILLISECONDS);
}
public void pause()
{
futureThread.cancel(false);
beatsPerBarExec.purge();
beatsPerBarExec = null;
}
#Override
public IBinder onBind(Intent intent)
{
return null;
}
}
You may be seeing the effects of drift.
Example: you want your Runnable to run every 200msec. You reschedule your Runnable in the run() method using postDelayed() and pass it 200msec as the delay. When the run() method is called the next time, it may not be exactly 200msec since the previous time. Perhaps it is 210msec. Now you reschedule your Runnable to run in another 200msec. This time the run() method may be called again after 210 msec, which means your sound plays 420msec since the first one, etc.
To eliminate drift, you need to determine the exact clock time you want the Runnable to run at, subtract the current time and use that in the call to postDelayed(). This will take into account any potential variance in the thread timing.
Be aware that when you call postDelayed() you are posting a Runnable to run on the main (UI) thread. This is the thread that handles all the UI updates and when your Runnable is ready to run it will just be queued to the main (UI) thread handler, and may not run immediately.
You can mitigate this problem by scheduling your Runnable to run on a background thread instead of the main (UI) thread. However this means your Runnable will be called on the background thread and I don't know if your other code (that plays the sound) needs to run on the main (UI) thread or not.
Hi i need to call a method every 4 seconds, even when the device is sleeping, i use alarm manager with service Start_stick, the service name is TransactionService. the code works well when the device is active and the method is called every exact 4 second, but when the screen is locked and device sleep the calling becomes inaccurate. so the method is now called every 2 seconds, sometimes every 1 sec,5 ....
this is how i run the thread to call method every 4 seconds
AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(
Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(getApplicationContext(),
TransactionService.class);
PendingIntent pendingIntent = PendingIntent.getService(
getApplicationContext(), 0, notificationIntent, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 4000, pendingIntent);
this is the log of calling the method when device is active and screen is on
12-30 13:23:00.565 17397-17479/com.ids.simcardrefill D/url: calling
12-30 13:23:04.565 17397-17537/com.ids.simcardrefill D/url:calling
12-30 13:23:08.565 17397-17411/com.ids.simcardrefill D/url:calling
12-30 13:23:12.565 17397-17655/com.ids.simcardrefill D/url:calling
and this is how the method is calling when device is sleeping
12-30 13:09:12.565 17397-17655/com.ids.simcardrefill D/url:calling
12-30 13:09:17.785 17397-17598/com.ids.simcardrefill D/url:calling
12-30 13:09:20.565 17397-17479/com.ids.simcardrefill D/url:calling
12-30 13:09:25.775 17397-17537/com.ids.simcardrefill D/url:calling
12-30 13:09:28.565 17397-17411/com.ids.simcardrefill D/url:calling
here the difference between calling is inaccurate: 2 seconds, 5 seconds, 3 seconds
this is how the service look like :
public int onStartCommand(Intent intent, int flags, int startId) {
mshared = PreferenceManager
.getDefaultSharedPreferences(getApplicationContext());
edit = mshared.edit();
hostname = mshared.getString(
getApplicationContext().getString(R.string.hostname), "0");
contin = true;
cost
= mshared.getString(getString(R.string.test), "0.09");
if (contin) {
getTransactions get = new getTransactions(getApplicationContext());
get.execute(hostname);
}
return START_STICKY;
}
`
any solution ??
You should crate a service for working in background: https://developer.android.com/guide/components/services.html
You should use Handler in order to implement every 4 second functionality.
Handler handler = new Handler();
Runnable test = new Runnable() {
#Override
public void run() {
//do work
handler.post(test, 4000); //wait 4 sec and run again
}
};
public void stopTest() {
handler.removeCallbacks(test);
}
public void startTest() {
handler.post(test,0); //wait 0 ms and run
}
EDIT: i have tried the code below and it works for me
MyService.java
public class MyService extends Service {
Handler handler;
Runnable test;
public MyService() {
handler = new Handler();
test = new Runnable() {
#Override
public void run() {
Log.d("foo", "bar");
handler.postDelayed(test, 100); //100 ms you should do it 4000
}
};
handler.postDelayed(test, 0);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
AndroidManifest.xml
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
MainActivity.java
#Override
protected void onCreate(Bundle savedInstanceState) {
//some code
startService(new Intent(this, MyService.class));
}
And remember if you want start-stop functionality take loot at my first example.
The correct way to do this is using a Handler (as already mentioned in the other answer), but I will take the liberty to add a few points to it.
The problem
I had a similar situation, where the AlarmManager was firing erratically. Digging deeper into the issue led to me to understand that since the AlarmManager operation wakes up the CPU by holding a CPU wake-lock and is intensive on the battery (given that the device is inactive), the OS tries to batch different alarms from different apps and fires all pending alarms when the device wakes up. This leads to the erratic behaviour of the AlarmManager. The documentation also specifies that we shouldn't be using this to trigger events at exact timestamps. There are Android APIs which are supposed to work for exact intervals, eg AlarmManager.setExact(), but the OS optimises itself to ignore the exactness if the interval duration is less than a minute. [not documented, but speaking from my personal experiences]
The fix
I fixed the issue using a Handler only, as shared in the other answer. But there is a small caveat. In the edge case that the Handler is killed (due to any reason), it won't trigger itself and your polling would stop.
The caveat
The fallback is to keep a AlarmManager as well, running every minute to trigger the Handler back again in case it was stopped prematurely by the OS. So, you have a Handler running every n seconds. Store the timestamp of the last time the Handler was called in SharedPreferences. Have a backup AlarmManager running every x minutes (ideally x = 5*n, so that you don't miss more than 5 polling calls). The AlarmManager checks when the Handler last ran. If it's within the margin, the AlarmManager does nothing and reschedules itself after x minutes. If it's been more than x minutes, the Handler must have been killed by the OS and the AlarmManager starts the Handler back again.
Adding some code to give you context as well.
public class PollingAlarmReceiver extends WakefulBroadcastReceiver {
final long POLLING_FREQUENCY_MARGIN = 5 * 1000; //margin kept in case the System delays any threads
Context mContext = ServicesApp.getContext();
/*
Splash/BootReceiver starts the Alarm and the Handler for polling.
The Handler starts the polling service and schedules the next run after an delay of the polling interval.
Before starting the service, the Handler also checks when the service was last run and whether it is time for the next call or not (with a margin of 5 seconds [POLLING_FREQUENCY_MARGIN]).
The Handler should cover all the cases and run smoothly. In case it fails, the Alarm acts as a failsafe.
The Alarm runs at an interval of 1 minute checking when the Handler was last called.
If it is past the time of the next scheduled call (with a margin of 5 seconds [POLLING_FREQUENCY_MARGIN]), the Alarm starts the runnable and makes the Handler queue the next run.
*/
#Override
public void onReceive(Context context, Intent intent) {
if (mContext == null)
mContext = ServicesApp.getContext();
if (mContext == null)
mContext = context.getApplicationContext();
if (mContext != null) {
if (getLastPolledTimestamp(mContext) > 0 && (System.currentTimeMillis() > (POLLING_FREQUENCY_MARGIN + getPollingInterval(mContext) + getLastPolledTimestamp(mContext)))) {
startPollingHandler();
}
}
}
Runnable mPoller = new Runnable() {
#Override
public void run() {
if (mContext == null)
mContext = ServicesApp.getContext();
if (mContext != null) {
try {
if ((System.currentTimeMillis() >= (getPollingInterval(mContext)) - POLLING_FREQUENCY_MARGIN + getLastPolledTimestamp(mContext))) {
if (!isServiceRunning(PollingService.class, mContext)) {
mContext.getSharedPreferences(CommonLib.APP_SETTINGS, 0).edit().putLong(LAST_POLLED_TIMESTAMP, System.currentTimeMillis()).commit();
Intent service = new Intent(mContext, PollingService.class);
startWakefulService(mContext, service);
}
}
} finally {
ServicesApp.getHandler().postDelayed(mPoller, getPollingInterval(mContext));
}
}
}
};
public void startAlarmToCheckForHandler() {
if (mContext == null)
mContext = ServicesApp.getContext();
if (mContext != null) {
AlarmManager alarmMgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext, PollingAlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
alarmMgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), 60 * 1000, alarmIntent);
}
}
public void startPollingHandler() {
mPoller.run();
}
public void cancelAlarm() {
if (mContext == null)
mContext = ServicesApp.getContext();
if (mContext != null) {
AlarmManager alarmMgr = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext, PollingAlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
alarmMgr.cancel(alarmIntent);
}
}
}
P.S. : I have this code running on production for thousand of devices whose main functionality rely on the exactness of the polling and it seems to be working great for me.
I want to run some task (fetching data from database) in background after 5 minutes interval. What should I use?
Please mind that Google ask you to run long operations on Service. Please read the articles below, to detech what service do you need (service, interservice)!
Intent Service going to shut down itself after the job is done.
To fire a service in every 5mins to do the job , you can combine with a timer, as suggested above.
Mind before continue: Service belongs to the same thread, where you create it. So when you are about to developer your service please use a new Thread to start it. If you forget to do it, your service going to belong to the UI thread, mean you are in a trouble....
read first:
http://developer.android.com/guide/components/services.html
developer guide:
http://developer.android.com/reference/android/app/Service.html
You can use TimerTask inside a service
Timer timer = new Timer();
timer.schedule( new YourTask(), 50000 );
Try this.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Do something
}
}, 0, 5000);
Use Async task:
pre Execute, do inBackground, Post Execute
With alarm Manager
Intent myIntent1 = new Intent(sign_in.this,MyNotificationService.class);
pendingintent2 = PendingIntent.getService(sign_in.this, 1,myIntent1, 1);
AlarmManager alarmManager1 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar1Notify = Calendar.getInstance();
calendar1Notify.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 20);
alarmManager1.set(AlarmManager.RTC_WAKEUP,calendar1Notify.getTimeInMillis(), pendingintent2);
long time = 300*1000;// 5 minutes repeat
alarmManager1.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar1Notify.getTimeInMillis(),time,pendingintent2);
Add Permission in manifest
<service android:name="com.example.MyNotificationService" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</service>
you can use a timer task:
TimerTask scanTask;
final Handler handler = new Handler();
Timer t = new Timer();
public void doTask(){
scanTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//your task(fetch data)
}
});
}};
t.schedule(scanTask, 300000, 300000);
}
You can use timer, it is not a problem but method within android do have some advantages
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle) {
...
mHandler = new Handler();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
updateStatus(); //this function can change value of mInterval.
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
I have activity which needs to be active all the time. I have thread which sleep 10 sec, and monitors values taken from database, compare them and start method. I'm wondering if user go back to other applications and activities, does my activity and thread still work, or they are handled by activity manager and go to pause-stop-destroy?? How to stay them a live??
Thank you.
here is code for that thread:
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.sleep(10000);
myHendler.post(new Runnable() {
public void run() {
// TODO Auto-generated method stub
final Calendar cal = Calendar.getInstance();
int godina2 = cal.get(Calendar.YEAR);
int mesec2 = cal.get(Calendar.MONTH);
int dan2 = cal.get(Calendar.DAY_OF_MONTH);
int sati2 = cal.get(Calendar.HOUR_OF_DAY);
int minuti2 = cal.get(Calendar.MINUTE);
trenutniDatum = new StringBuilder().append(dan2).append("-").append(mesec2 +1).append("-").append(godina2);
trenutnoVreme = prepraviVreme(sati2) + ":" + prepraviVreme(minuti2);
for(int i = 0; i < primljenoIzBazeDatum.length; i++){
String bazaBroj = "";
String bazaText = "";
if(primljenoIzBazeDatum[i].toString().equals(trenutniDatum.toString()) && primljenoIzBazeVreme[i].toString().equals(trenutnoVreme)){
int bazaId = Integer.parseInt(primljenoIzBazeId[i]);
bazaBroj = primljenoIzBazeBroj[i].toString();
bazaText = primljenoIzBazeText[i].toString();
String datumPromena = "*" + primljenoIzBazeDatum[i].toString() + "* SENT *";
datumVreme.open();
datumVreme.updateData(bazaId, datumPromena);
datumVreme.close();
sendPoruka(bazaBroj, bazaText);
}
} // end for
} // end run
});
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
Based on my understanding of what you want to do, here is what I would do :
First, create a BroadcastReceiver
public class Poller extends BroadcastReceiver {
private final String TAG = "Poller";
#Override
public void onReceive( Context context, Intent intent ) {
Log.i(TAG, "Poller broadcastintent received");
Intent myIntent = new Intent( context, PollerService.class );
context.startService( myIntent );
}
then , create the service that is called and then shuts itself down
public class PollerService extends Service {
final String TAG = "PollerService";
#Override
public void onStart(Intent intent, int startId) {
Log.i(TAG, "Service onStart()");
pollingTask.execute();
}
AsyncTask<Void, Void, Void> pollingTask = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... param) {
// Do what you want in the background
}
#Override
protected void onPostExecute(Void result) {
stopSelf();
}
};
}
then, set an AlarmManager to wake the service every minute
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent alarmIntent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast(context, 0 , alarmIntent, 0 );
int type = AlarmManager.ELAPSED_REALTIME_WAKEUP;
long interval = POLLING_INTERVAL_IN_MILLISECONDS;
long triggerTime = SystemClock.elapsedRealtime() + interval;
// For short intervals setInexact repeating is same as exactRepeating, use at least fifteen minutes to make it more efficient
am.setInexactRepeating( type, triggerTime, interval, pi );
Log.i(TAG, "Set inexact alarm through AlarmManager");
}
setup the receiver in Android manifest
<receiver android:name="Poller">
<intent-filter>
<action android:name="CHECK_DATABASE"/>
</intent-filter>
</receiver>
finally, unset the AlarmManager to stop polling once your required SMS is received
AlarmManager am = ( AlarmManager ) getSystemService( Context.ALARM_SERVICE );
Intent intent = new Intent( "CHECK_DATABASE" );
PendingIntent pi = PendingIntent.getBroadcast( context, 0 , intent, 0 );
am.cancel(pi);
I do think that Peter is right though and this will kill you battery unless you'll only be checking until you get the required info and then don't poll and that's a short time.
Also, if you can get the exact time when you want to send the SMS with a single call from the database you can just set up the AlarmManger to wake up the service at that time, perform the action and be done with it. That would be the best approach (I can't quite make out if that is the case from you code but it does seems to be from you comments).
No, no application code on Android is not guaranteed to run all the time. Android OS can kill off aplications and services any time it feels it needs to.
Your best bet to periodically execute code would be to use AlarmManager, which makes your code execute periodically. Also a proper flag must be set to execute your code when device is asleep.
Note, since your period is very short (10s), it would keep CPU running all the time, draining the batterry very quickly.
If it has to be active all the time you have to use a Service: http://developer.android.com/guide/topics/fundamentals/services.html
I'm wondering if user go back to other applications and activities,
does my activity and thread still work, or they are handled by
activity manager and go to pause-stop-destroy?? How to stay them a
live??
They won't be kept "alive". If the system needs the resources your activity is destroyed. If you want to keep things running in the background even after your app is finished you have to use a Service.
In Java language you can scheduling your programs by traditional way:
java.util.Timer
java.util.TimerTask
for more information you can see:
http://enos.itcollege.ee/~jpoial/docs/tutorial/essential/threads/timer.html
http://www.ibm.com/developerworks/java/library/j-schedule/index.html
but better practice is using a scheduling framework such as Quartz, you can see http://www.quartz-scheduler.org/.
Spring framework also integration with Quartz framework.