2016-05-13 3 views
9

С Android N вы не можете статически регистрировать приемники Broadcast для намерения CONNECTIVITY_CHANGE.Обнаружение изменения состояния сети с помощью JobSchedulers в Android

От http://developer.android.com/preview/features/background-optimization.html#connectivity-action В документации Google предлагается использовать Планировщики заданий для выполнения этой задачи.

Можно ли определить изменение состояния сети (LTE на Wi-Fi) и наоборот с помощью планировщика заданий в Android?

+0

AFAIK, идея не в том, чтобы обнаруживать изменение состояния, а скорее использовать «JobScheduler», чтобы организовать выполнение определенной фоновой работы, когда вы находитесь на немодулированном соединении, вместо того, чтобы пытаться моделировать это с помощью трансляций CONNECTIVITY_CHANGE. – CommonsWare

+0

@CommonsWare Я хочу получать уведомления, когда тип сетевого подключения изменен с 'wifi' на' cell' и наоборот. Чтобы использовать его с таргетингом на android 'oreo', я застрял, чтобы найти решение. Есть ли у вас предложения? – Merka

+0

@Merka: Нет, извините. – CommonsWare

ответ

11

Да и нет.

Метод JobInfo.Builder.setRequiredNetworkType() позволяет планировать задания для запуска при выполнении определенных условий сети.

Тип сети может быть один из трех значений:

  • JobInfo.NETWORK_TYPE_NONE: Нет подключения к сети требуется.
  • JobInfo.NETWORK_TYPE_UNMETERED: unmetered Wi-Fi или соединение Ethernet.
  • JobInfo.NETWORK_TYPE_ANY: Любое сетевое соединение (WiFi или сотовая связь).

Теперь улов ... нет NETWORK_TYPE_CELLUAR. У вас не может быть ваше приложение только просыпаться, когда он только на сотовой. (Зачем вы хотите это сделать?)

Другие уловы ... WiFi-соединения могут быть измерены или не определены. Замещенные соединения обычно такие, как мобильные горячие точки, и это может быть либо автоматически обнаружено (есть специальная опция DHCP, которую может отправлять точка доступа), либо пользователь может вручную переключать ее по сети в соответствии с настройками WiFi.

Итак, да, вы можете установить ограничения сетевого типа в задании JobScheduler. Однако нет, вы не получаете уровень детализации, о котором вы просите.

Как упоминалось в @CommonsWare, идея состоит в том, что вы обычно планируете назначать сетевые задания, когда сетевое подключение не изменяется, если у вас нет веской причины. (Это также хорошая идея отложить работу до тех пор, пока не будет доступна переменная мощность, используя setRequiresCharging(true), чтобы сохранить батарею.)

+1

Ну, есть случай, когда каждый будет использовать NETWORK_TYPE_CELLULAR. Предположим, у пользователя нет SIM-карты, и пользователь подключен к Wi-Fi. Если вы хотите, чтобы ваше приложение было запущено, если пользователь отключил Wi-Fi, нет никакого способа! После того, как он отключится от Wi-Fi, он не отправляется в сеть METERED, потому что у него нет доступа к Интернету, и нет способа оповестить об этом приложение. – febaisi

3

Это может быть не лучшее решение. Пожалуйста, объясните, почему перед вами проголосовать за это.

Я использовал GcmTaskService, чтобы обнаружить изменение состояния сети, используя следующий код. Это было для приложения погоды, которое я разрабатываю.

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"); 
    } 
} 

Это, кажется, работает отлично для меня. Он не обнаруживает мгновенное изменение связи, как это делает широковещательный приемник. Но он работает каждые 30 секунд, если доступно сетевое соединение. Убедитесь, что вы звоните

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

в вашем основном методе деятельности onCreate при первом запуске приложения, чтобы запланировать эту задачу в первый раз.

+0

Hi Vajira, один маленький исправление. GcmTaskService имеет обратную совместимость. Поэтому нет необходимости проверять Utilities.checkIsNougat(). Я тестировал в Android 4.0 и 4.4. Это работает и спасибо за этот образец. – Thirumalvalavan

+0

@Thirumalvalavan Правда, что. Но в моем приложении я использовал обычный широковещательный приемник для немедленного запуска программы обновления на устройствах с поддержкой Nougat. –