android:永远每小时安排工作

时间:2018-02-13 07:31:31

标签: android android-service android-alarms firebase-job-dispatcher

我的服务器上有一个需要每小时ping一次的Web服务。为此,我使用Android应用程序每小时ping一次。我尝试过使用闹钟管理器,但几小时后就停止工作了,如果我滑动退出它。我尝试过使用服务,但由于某种原因,这似乎不起作用,我的应用程序一直在崩溃。我正在考虑使用Firebase Job调度程序。我的要求是应用程序需要每小时ping我服务器上的Web服务。这应该至少持续3-4个月。有没有办法实现这个目标?提前谢谢!

编辑:我已经尝试过使用Alarm Manager的广播接收器但是未能持续发射超过4小时。

4 个答案:

答案 0 :(得分:2)

Jhon你可以使用firebase jobdispatcher。因为它将从api级别9支持。您可以在下面看到如何创建作业调度程序以及如何调用它。

  public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    scheduleJob(this);
}

public static void scheduleJob(Context context) {
    //creating new firebase job dispatcher
    FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
    //creating new job and adding it with dispatcher
    Job job = createJob(dispatcher);
    dispatcher.mustSchedule(job);
}

public static Job createJob(FirebaseJobDispatcher dispatcher){

    Job job = dispatcher.newJobBuilder()
            //persist the task across boots
            .setLifetime(Lifetime.FOREVER)
            //.setLifetime(Lifetime.UNTIL_NEXT_BOOT)
            //call this service when the criteria are met.
            .setService(ScheduledJobService.class)
            //unique id of the task
            .setTag("UniqueTagForYourJob")
            //don't overwrite an existing job with the same tag
            .setReplaceCurrent(false)
            // We are mentioning that the job is periodic.
            .setRecurring(true)
            // Run between 30 - 60 seconds from now.
            .setTrigger(Trigger.executionWindow(30, 60))
            // retry with exponential backoff
            .setRetryStrategy(RetryStrategy.DEFAULT_LINEAR)
            //.setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
            //Run this job only when the network is available.
            .setConstraints(Constraint.ON_ANY_NETWORK, Constraint.DEVICE_CHARGING)
            .build();
    return job;
}

public static Job updateJob(FirebaseJobDispatcher dispatcher) {
    Job newJob = dispatcher.newJobBuilder()
            //update if any task with the given tag exists.
            .setReplaceCurrent(true)
            //Integrate the job you want to start.
            .setService(ScheduledJobService.class)
            .setTag("UniqueTagForYourJob")
            // Run between 30 - 60 seconds from now.
            .setTrigger(Trigger.executionWindow(30, 60))
            .build();
    return newJob;
}

public void cancelJob(Context context){

    FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
    //Cancel all the jobs for this package
    dispatcher.cancelAll();
    // Cancel the job for this tag
    dispatcher.cancel("UniqueTagForYourJob");

}}

<强> ScheduledJobService.java

public class ScheduledJobService extends JobService {

private static final String TAG = ScheduledJobService.class.getSimpleName();

@Override
public boolean onStartJob(final JobParameters params) {
    //Offloading work to a new thread.
    new Thread(new Runnable() {
        @Override
        public void run() {
            codeYouWantToRun(params);
        }
    }).start();

    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    return false;
}

public void codeYouWantToRun(final JobParameters parameters) {
    try {

        Log.d(TAG, "completeJob: " + "jobStarted");
        //This task takes 2 seconds to complete.
        Thread.sleep(2000);

        Log.d(TAG, "completeJob: " + "jobFinished");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        //Tell the framework that the job has completed and doesnot needs to be reschedule
        jobFinished(parameters, true);
    }
}}

答案 1 :(得分:2)

我是第二个Anantha's answer,但似乎工作参数对你的需求来说很少。

您可以通过this article了解各种作业调度程序之间的细微差别。

事实上,如果应用因各种原因需要进行网络通信,即使Google建议使用Firebase Job Schedular。请在Github页面上观看附加视频,了解相关信息。这也为您提供了启动应用程序的基本代码。您只需更改作业参数以满足您的需求

希望以下代码符合您的要求,即每隔一小时触发一次,容差为15分钟

 FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(getContext()));
    final int periodicity = (int)TimeUnit.HOURS.toSeconds(1); // Every 1 hour periodicity expressed as seconds
    final int toleranceInterval = (int)TimeUnit.MINUTES.toSeconds(15); // a small(ish) window of time when triggering is OK

    Job myJob = dispatcher.newJobBuilder()
            // the JobService that will be called
            .setService(yourJobService.class)
            // uniquely identifies the job
            .setTag("my-unique-tag")
            // recurring job
            .setRecurring(true)
            // persist past a device reboot
            .setLifetime(Lifetime.FOREVER)
            // start between 0 and 60 seconds from now
            .setTrigger(Trigger.executionWindow(periodicity, toleranceInterval))
            // overwrite an existing job with the same tag
            .setReplaceCurrent(true)
            // retry with exponential backoff
            .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL)
            // constraints that need to be satisfied for the job to run
            .setConstraints(
                    // only run on an unmetered network
                    Constraint.ON_ANY_NETWORK
            )
            .setExtras(schedulerextras)
            .build();

    dispatcher.mustSchedule(myJob);

答案 2 :(得分:1)

你试试广播接收器吗?我使用带有报警管理器的广播接收器来振动每一分钟,它工作正常。唯一的问题是当设备关闭或重启时,它不会振动,直到我进入我的应用程序。

我的测试代码。

 public void setAlarm() {
    alarmMgr =(AlarmManager)getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(AlarmManagerActivity.this, AlarmManagerBroadcastReceiver.class);
    intent.setAction("a.b.c.d");
    PendingIntent pi = PendingIntent.getBroadcast( getApplicationContext(), 0, intent, 0);
    //After after 5 seconds
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 13);
    calendar.set(Calendar.MINUTE, 40);
    alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis()
            , (1000) * (60)
            , pi);
}

我的接收器

@Override
public void onReceive(Context context, Intent intent) {
    Log.d(getClass().getSimpleName(), Intent.ACTION_BOOT_COMPLETED);
if ( intent.getAction().equals("a.b.c.d")) {
        Log.d(getClass().getSimpleName(), "Custom Broadcast01");
    Vibrator  vibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(10000);
    }
    else
        Log.d(getClass().getSimpleName(), "no this action for intent!");
}
  

广播接收器在设备重启时启动警报

<receiver
            android:name=".OnBootBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
</receiver>

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class OnBootBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {

        setAlarm();
    }
}

答案 3 :(得分:1)

根据android的api级别,您需要使用JobScheduler(api&gt; 21)和GcmNetworkManager(api&lt; 21)。 Check out this library from evernote which takes care of it.