2016-05-13 11 views
9

Con Android N, non è possibile registrare staticamente un destinatario Broadcast per l'intento CONNECTIVITY_CHANGE.Rileva cambiamento stato di rete utilizzando JobSchedulers in Android

Da http://developer.android.com/preview/features/background-optimization.html#connectivity-action La documentazione di Google suggerisce di utilizzare Job Scheduler per eseguire questa attività.

È possibile rilevare il cambio di stato della rete (da LTE a wifi) e viceversa utilizzando Job Scheduler in Android?

+0

AFAIK, l'idea non è quella di rilevare il cambiamento di stato, ma piuttosto utilizzare 'JobScheduler' per organizzare un lavoro di background specifico quando ci si trova su una connessione non misurata, piuttosto che tentare di modellarlo usando le trasmissioni di' CONNECTIVITY_CHANGE'. – CommonsWare

+0

@CommonsWare Desidero ricevere una notifica quando il tipo di connessione di rete viene cambiato da 'wifi' a' cellulare 'e viceversa. Per usarlo con il targeting Android 'oreo' sono bloccato a trovare una soluzione. Hai qualche suggerimento? – Merka

+0

@Merka: No, mi dispiace. – CommonsWare

risposta

11

Sì e no.

Il metodo JobInfo.Builder.setRequiredNetworkType() consente di pianificare i lavori da eseguire quando vengono soddisfatte determinate condizioni di rete.

Il tipo di rete può essere uno dei tre valori:

  • JobInfo.NETWORK_TYPE_NONE: No connettività di rete necessaria.
  • JobInfo.NETWORK_TYPE_UNMETERED: An unmetered Connessione WiFi o Ethernet.
  • JobInfo.NETWORK_TYPE_ANY: Qualsiasi connessione di rete (WiFi o cellulare).

Ora, il trucco ... non c'è NETWORK_TYPE_CELLUAR. Non puoi fare in modo che la tua app si riattivi solo quando è solo su cellulare. (Perché vorresti farlo?)

L'altro fermo ... Le connessioni WiFi possono essere misurate o non misurate. Le connessioni misurate sono in genere cose come gli hotspot mobili, che possono essere rilevati automaticamente (è disponibile un'opzione DHCP speciale che l'hotspot può inviare) oppure l'utente può commutarla manualmente su base per rete dalle Impostazioni WiFi.

Quindi, sì, è possibile impostare i vincoli di tipo di rete sul lavoro di JobScheduler. Tuttavia, no, non ottieni il livello di granularità che stai richiedendo.

Come @CommonsWare menzionato, l'idea è che di solito si desidera pianificare i lavori relativi alla rete che si verificano quando la connettività di rete non è disponibile, a meno che non si abbia una buona ragione. (È anche consigliabile rimandare i lavori fino a quando non è disponibile l'alimentazione CA, utilizzando setRequiresCharging(true), per risparmiare la batteria.)

+1

Bene, c'è un caso che tutti userebbero NETWORK_TYPE_CELLULAR. Supponiamo che l'utente non abbia SIM card e che l'utente sia connesso al Wi-Fi. Se vuoi che la tua app venga attivata se l'utente spegne il Wi-Fi, non c'è modo! Dopo che è stato disconnesso dal Wi-Fi, non va alla rete METERED perché non ha Internet e non c'è modo di avvisare la tua app al riguardo. – febaisi

3

Questa potrebbe non essere la soluzione migliore. Per favore, spiega perché prima di non votare questo.

Ho utilizzato GcmTaskService per rilevare la modifica dello stato della rete utilizzando il seguente codice. Era per un'app meteo che sto sviluppando.

public class ServiceUpdateWeather extends GcmTaskService { 

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

    public static final String GCM_TAG_REPEAT_CONNECTIVITY_CHANGE = "UPDATE_WEATHER_CONNECTIVITY_CHANGE"; 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
    } 

    @Override 
    public void onInitializeTasks() { 
     //called when app is updated to a new version, reinstalled etc. 
     //you have to schedule your repeating tasks again 
     super.onInitializeTasks(); 
     if (Utilities.checkIsNougat()) { 
      ServiceUpdateWeather.cancelConnectivityChange(getApplicationContext()); 
      ServiceUpdateWeather.scheduleConnectivityChange(getApplicationContext()); 
     } 
    } 

    @Override 
    public int onRunTask(TaskParams taskParams) { 
     Handler h = new Handler(getMainLooper()); 
     if(taskParams.getTag().equals(GCM_TAG_REPEAT_CONNECTIVITY_CHANGE)) { 
      Log.i(TAG, "Connectivity changed task fired"); 
      h.post(new Runnable() { 
        @Override 
        public void run() { 
         Toast.makeText(ServiceUpdateWeather.this, "Updating weather", Toast.LENGTH_SHORT).show(); 
        } 
       }); 
      WeatherHelper.runNetworkConnectedUpdater(ServiceUpdateWeather.this); 
     } 

     return GcmNetworkManager.RESULT_SUCCESS; 
    } 

    public static void scheduleConnectivityChange(Context context) { 
     try { 
      PeriodicTask connectivityChange = new PeriodicTask.Builder() 
        //specify target service - must extend GcmTaskService 
        .setService(ServiceUpdateWeather.class) 
        //repeat every 30 seconds 
        .setPeriod(30) 
        //specify how much earlier the task can be executed (in seconds) 
        .setFlex(10) 
        //tag that is unique to this task (can be used to cancel task) 
        .setTag(GCM_TAG_REPEAT_CONNECTIVITY_CHANGE) 
        //whether the task persists after device reboot 
        .setPersisted(true) 
        //if another task with same tag is already scheduled, replace it with this task 
        .setUpdateCurrent(true) 
        //set required network state, this line is optional 
        .setRequiredNetwork(Task.NETWORK_STATE_CONNECTED) 
        //request that charging must be connected, this line is optional 
        .setRequiresCharging(false) 
        .build(); 
      GcmNetworkManager.getInstance(context).schedule(connectivityChange); 
      Log.i(TAG, "Connectivity change task scheduled"); 
     } catch (Exception e) { 
      Log.e(TAG, "Connectivity change task failed to schedule"); 
      e.printStackTrace(); 
     } 
    } 

    public static void cancelConnectivityChange(Context context) { 
     GcmNetworkManager.getInstance(context).cancelTask(GCM_TAG_REPEAT_CONNECTIVITY_CHANGE, ServiceUpdateWeather.class); 
     Log.v(TAG, "Connectivity change task cancelled"); 
    } 
} 

Questo sembra funzionare bene per me. Non rileva immediatamente il cambiamento di connettività come fa il ricevitore broadcast. Ma funziona ogni 30 secondi se è disponibile una connessione di rete. Assicurati di chiamare

if (Utilities.checkIsNougat()) { 
    ServiceUpdateWeather.cancelConnectivityChange(getApplicationContext()); 
    ServiceUpdateWeather.scheduleConnectivityChange(getApplicationContext()); 
} 

nel metodo principale attività onCreate durante il primo lancio di app per pianificare questa attività per la prima volta.

+0

Ciao Vajira, una piccola correzione. GcmTaskService ha la compatibilità con le versioni precedenti. Quindi non c'è bisogno di controllare Utilities.checkIsNougat(). Ho provato su Android 4.0 e 4.4. Funziona e grazie per questo campione. – Thirumalvalavan

+0

@Thirumalvalavan Questo è vero. Ma nella mia app ho usato un normale ricevitore broadcast per eseguire l'updater istantaneamente sui dispositivi pre Nougat. –

Problemi correlati