使用 Android N,您不能为 CONNECTIVITY_CHANGE 意图静态注册广播接收器。
从http://developer.android.com/preview/features/background-optimization.html#connectivity-action 谷歌文档建议使用 Job Schedulers 来执行此任务。
是否可以使用 Android 中的 Job Schedulers 检测网络状态变化(LTE 到 wifi),反之亦然?
使用 Android N,您不能为 CONNECTIVITY_CHANGE 意图静态注册广播接收器。
从http://developer.android.com/preview/features/background-optimization.html#connectivity-action 谷歌文档建议使用 Job Schedulers 来执行此任务。
是否可以使用 Android 中的 Job Schedulers 检测网络状态变化(LTE 到 wifi),反之亦然?
是和不是。
该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)
, 以节省电池电量。)
这可能不是最好的解决方案。请在您对此投反对票之前解释原因。
我曾经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
方法中首次安排此任务。