18

使用 Android N,您不能为 CONNECTIVITY_CHANGE 意图静态注册广播接收器。

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

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

4

2 回答 2

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), 以节省电池电量。)

于 2016-05-18T02:48:23.327 回答
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方法中首次安排此任务。

于 2017-06-11T12:37:41.530 回答