Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
132 views
in Technique[技术] by (71.8m points)

android - how to schedule a task every night at 12 AM

I want to start ScheduledExecutorService exactly on 12 AM daily, but in my code schedule is not started. Can any one tell me Whether my code is Correct or not? If any other way available that would also helpful

public class MainActivity extends AppCompatActivity{  
ScheduledExecutorService scheduler;

@Override

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
scheduler = Executors.newScheduledThreadPool(1);

scheduleTask();

}

 public void scheduleTask() {

        final Runnable beeper = new Runnable() {
            public void run() {
                MainActivity.this.runOnUiThread(new Runnable() {
                    public void run() {


Toast.makeText(getApplicationContext(),"SCHEDULE STARTED",Toast.LENGTH_LONG).show();

                                    }
                                }
                            }
                        }, 1500);
                    }
                    });
            }
            };

        Calendar midnight = Calendar.getInstance();
        midnight.set(Calendar.HOUR_OF_DAY, 0);
        midnight.set(Calendar.MINUTE, 0);
        midnight.set(Calendar.SECOND, 0);
        midnight.set(Calendar.MILLISECOND, 1);
        midnight.set(Calendar.DAY_OF_YEAR, midnight.get(Calendar.DAY_OF_YEAR) + 1);
        long tillMidnight = midnight.getTimeInMillis() - System.currentTimeMillis() - 1;
        long ticksTillMidnight = tillMidnight / 50;

        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, ticksTillMidnight,20*60*60*24, TimeUnit.MILLISECONDS
        );
        scheduler.schedule(new Runnable() {
            public void run() {
                beeperHandle.cancel(true);
            }
        }, 6*6,     TimeUnit.MILLISECONDS
        );
    }}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The answer is quite simple. In your case, a ScheduledExecutorService is bound to the lifetime of your process. If your process gets killed, then the ScheduledExecutorService will get killed along with it. Instead use an AlarmManager

Here are 3 steps

  1. Create the Alarm
  2. Create the BroadcastReceiver
  3. Register the Receiver in the App Manifest

1. Create the Alarm

public void createAlarm() {
    //System request code
    int DATA_FETCHER_RC = 123;
    //Create an alarm manager
    AlarmManager mAlarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

    //Create the time of day you would like it to go off. Use a calendar
    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);

    //Create an intent that points to the receiver. The system will notify the app about the current time, and send a broadcast to the app
    Intent intent = new Intent(this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, DATA_FETCHER_RC,intent, PendingIntent.FLAG_UPDATE_CURRENT);

    //initialize the alarm by using inexactrepeating. This allows the system to scheduler your alarm at the most efficient time around your 
    //set time, it is usually a few seconds off your requested time.
    // you can also use setExact however this is not recommended. Use this only if it must be done then.

    //Also set the interval using the AlarmManager constants
    mAlarmManager.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY, pendingIntent);

}

2. Create the BroadcastReceiver

//This is the broadcast receiver you create where you place your logic once the alarm is run. Once the system realizes your alarm should be run, it will communicate to your app via the BroadcastReceiver. You must implement onReceive.
public class AlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        //Your code once the alarm is set off goes here
        //You can use an intent filter to filter the specified intent
    }
}

3. In your app manifest register the receiver

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package">
//This is a useful permission as it allows your apps alarm to still be active once a reboot takes place
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <receiver
        android:name=".MainActivity$AlarmReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...