使用Android中的JobSchedulers检测网络状态更改

时间:2016-05-13 18:46:49

标签: android networking android-7.0-nougat

使用Android N,您无法静态注册CONNECTIVITY_CHANGE意图的广播接收器。

来自http://developer.android.com/preview/features/background-optimization.html#connectivity-action Google文档建议使用Job Scheduler执行此任务。

是否可以使用Android中的Job Scheduler检测网络状态变化(LTE到wifi),反之亦然?

2 个答案:

答案 0 :(得分:14)

是和否。

JobInfo.Builder.setRequiredNetworkType()方法允许您安排在满足特定网络条件时运行的作业。

网络类型可以是以下三个值之一:

  • JobInfo.NETWORK_TYPE_NONE:无需网络连接。
  • JobInfo.NETWORK_TYPE_UNMETERED未计量 WiFi或以太网连接。
  • JobInfo.NETWORK_TYPE_ANY:任何网络连接(WiFi或手机)。

现在,抓住......没有NETWORK_TYPE_CELLUAR。您的应用只有在蜂窝电话上时才会被唤醒。 (你为什么要那样做?)

另一个问题...... WiFi连接可以计量或不计量。计量连接通常是移动热点之类的东西,可以自动检测(热点可以发送特殊的DHCP选项),或者用户可以通过WiFi设置在每个网络上手动切换它。

所以,是的,您可以在JobScheduler作业上设置网络类型约束。但是,不,您没有达到您要求的粒度级别。

正如@CommonsWare所提到的,我们的想法是,除非您有充分的理由,否则您通常希望在网络连接未计量时安排与网络相关的作业。 (使用setRequiresCharging(true)可以使用SUM( CASE WHEN a = b THEN c ELSE d END )来延迟工作,直到工作推迟工作,这也是一个好主意。)

答案 1 :(得分: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方法中

首次安排此任务。