2016-07-13 29 views
23

Job Scheduler funziona come previsto su dispositivi Android Marshmallow e Lollipop, ma non è in esecuzione e Nexus 5x (anteprima Android N).Job Scheduler non in esecuzione su Android N

Codice in materia di pianificazione del processo

 ComponentName componentName = new ComponentName(MainActivity.this, TestJobService.class.getName()); 
     JobInfo.Builder builder; 
     builder = new JobInfo.Builder(JOB_ID, componentName); 
     builder.setPeriodic(5000); 
     JobInfo jobInfo; 
     jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); 
     jobInfo = builder.build(); 
     int jobId = jobScheduler.schedule(jobInfo); 

servizio è definito in manifestano come:

<service android:name=".TestJobService" 
      android:permission="android.permission.BIND_JOB_SERVICE" /> 

è uno qualsiasi avere questo problema su Android N (Anteprima)?

+0

Dove provi a pianificare un lavoro? Voglio dire è un ricevitore broadcast o qualcosa del genere? – rom4ek

+0

@ rom4ek è nell'attività al momento, come se fosse un'app campione. – kaibuki

risposta

32

In Android Torrone la chiamata al metodo setPeriodic(long intervalMillis) fa uso di setPeriodic (long intervalMillis, long flexMillis) per pianificare i processi periodici.

Come per la documentazione:

JobInfo.Builder setPeriodic (lunghe intervalMillis, lunghe flexMillis)

Specificare che questo lavoro dovrebbe ripresentarsi con l'intervallo fornito e flex. Il lavoro può essere eseguito in qualsiasi momento in una finestra di lunghezza flessibile al alla fine del periodo.

intervalloMillis lungo: Intervallo del millisecondo per il quale questo lavoro verrà ripetuto. Viene applicato un valore minimo di getMinPeriodMillis().

flexMillis long: flex millisecondo per questo lavoro. Flex è bloccato per essere almeno getMinFlexMillis() o il 5% del periodo, a seconda di quale sia il più alto.

Lavoro di prova periodica prevista per 5 secondi:

private static final int JOB_ID = 1001; 
private static final long REFRESH_INTERVAL = 5 * 1000; // 5 seconds 

JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName) 
     .setPeriodic(REFRESH_INTERVAL) 
     .setExtras(bundle).build(); 

Il codice di cui sopra funziona bene in Lollipop & Marshmallow, ma quando si esegue in Torrone si noterà il seguente registro:

W/JobInfo: Specified interval for 1001 is +5s0ms. Clamped to +15m0s0ms 
W/JobInfo: Specified flex for 1001 is +5s0ms. Clamped to +5m0s0ms 

Poiché abbiamo impostato l'intervallo di aggiornamento periodico su 5 secondi che è inferiore alla soglia getMinPeriodMillis(). Android Nougat applica lo getMinPeriodMillis().

Come soluzione temporanea, sto utilizzando il seguente codice per pianificare i lavori a intervalli periodici se l'intervallo di lavoro è inferiore a 15 minuti.

JobInfo jobInfo; 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
    jobInfo = new JobInfo.Builder(JOB_ID, serviceName) 
     .setMinimumLatency(REFRESH_INTERVAL) 
     .setExtras(bundle).build(); 
} else { 
    jobInfo = new JobInfo.Builder(JOB_ID, serviceName) 
     .setPeriodic(REFRESH_INTERVAL) 
     .setExtras(bundle).build(); 
} 

Esempio esempio JobService:

public class SampleService extends JobService { 
    @Override public boolean onStartJob(JobParameters params) { 
     doSampleJob(params); 
     return true; 
    } 

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

    public void doSampleJob(JobParameters params) { 
     // Do some heavy operation 
     ...... 
     // At the end inform job manager the status of the job. 
     jobFinished(params, false); 
    } 
} 
+1

ma sembra funzionare una sola volta con setMinimumLatency –

+1

@KarthikRk, il lavoro non può essere periodico e avere una minima visibilità, quindi se si imposta la latenza minima è un lavoro singolo. – DataDino

+2

Questo non risolve il problema ... il lavoro non verrà eseguito periodicamente con questo codice. – forresthopkinsa

4

ho trovato la risposta al problema che ci troviamo di fronte con i dispositivi torrone. I dispositivi Nougat non sono in grado di pianificare il lavoro se il lavoro deve essere riprogrammato meno di 15 minuti.

Ho provato dando all'intervallo 15 minuti e il lavoro ha iniziato a essere programmato ogni 15 minuti.

lavoro Codice Scheduler:

public static void scheduleJob(Context context) { 
    ComponentName serviceComponent = new ComponentName(context, PAJobService.class); 
    JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, serviceComponent); 
    builder.setPeriodic(15 * 60 * 1000, 5 * 60 *1000); 

    JobScheduler jobScheduler = context.getSystemService(JobScheduler.class); 
    int ret = jobScheduler.schedule(builder.build()); 
    if (ret == JobScheduler.RESULT_SUCCESS) { 
     Log.d(TAG, "Job scheduled successfully"); 
    } else { 
     Log.d(TAG, "Job scheduling failed"); 
    } 
} 

Servizio Lavoro:

public class PAJobService extends JobService { 
    private static final String TAG = PRE_TAG + PAJobService.class.getSimpleName(); 
    private LocationManager mLocationManager; 

    public boolean onStartJob(JobParameters params) { 
     Log.d(TAG, "onStartJob"); 
     Toast.makeText(getApplicationContext(), "Job Started", Toast.LENGTH_SHORT).show(); 
     return false; 
    } 

    public boolean onStopJob(JobParameters params) { 
     Log.d(TAG, "onStopJob"); 
     return false; 
    } 
} 

In breve se avrebbe aumentato l'intervallo di tempo a 15 minuti il ​​codice avrebbe iniziato a lavorare.

private static final long REFRESH_INTERVAL = 15 * 60 * 1000;

4

Ecco una soluzione per> = Android N (Se si desidera impostare il lavoro periodico inferiore a 15 minuti) Verificare che solo setMinimumLatency viene utilizzato. Inoltre, se si esegue un compito che richiede molto tempo, il lavoro successivo sarà previsto per le ore, attuale tempo di fine lavoro + PROVIDED_TIME_INTERVAL

.SetPeriodic (lungo millis) funziona bene per il livello API sotto Android N

@Override 
public boolean onStartJob(final JobParameters jobParameters) { 
    Log.d(TAG,"Running service now.."); 
    //Small or Long Running task with callback 

    //Reschedule the Service before calling job finished 
    if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) 
       scheduleRefresh(); 

    //Call Job Finished 
    jobFinished(jobParameters, false); 

    return true; 
} 

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

private void scheduleRefresh() { 
    JobScheduler mJobScheduler = (JobScheduler)getApplicationContext() 
        .getSystemService(JOB_SCHEDULER_SERVICE); 
    JobInfo.Builder mJobBuilder = 
    new JobInfo.Builder(YOUR_JOB_ID, 
        new ComponentName(getPackageName(), 
        YourJobService.class.getName())); 

    /* For Android N and Upper Versions */ 
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { 
     mJobBuilder 
       .setMinimumLatency(60*1000) //YOUR_TIME_INTERVAL 
       .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); 
    } 


    if (mJobScheduler != null && mJobScheduler.schedule(mJobBuilder.build()) 
       <= JobScheduler.RESULT_FAILURE) { 
    //Scheduled Failed/LOG or run fail safe measures 
    Log.d(TAG, "Unable to schedule the service!"); 
    } 
} 
0

se si desidera eseguire il codice periodicamente meno di 15 minuti, è possibile utilizzare in modo complicato. Imposta il tuo jobFinished() come questo

jobFinished(parameters, true); 

sarà riprogrammare il codice con una strategia di tentativi. Definire un criterio personalizzato di backoff usando

.setBackoffCriteria(); 

nel costruttore. Quindi verrà eseguito periodicamente

Problemi correlati