Android Nの場合、CONNECTIVITY_CHANGEインテントのブロードキャストレシーバーを静的に登録することはできません。
http://developer.Android.com/preview/features/background-optimization.html#connectivity-action からGoogleのドキュメントでは、ジョブスケジューラを使用してこのタスクを実行することを推奨しています。
Androidのジョブスケジューラを使用してネットワーク状態の変化(LTEからwifi)を検出することは可能ですか?
はいといいえ。
JobInfo.Builder.setRequiredNetworkType()
メソッドを使用すると、特定のネットワーク条件が満たされたときに実行するジョブをスケジュールできます。
ネットワークタイプは、次の3つの値のいずれかになります。
JobInfo.NETWORK_TYPE_NONE
_:ネットワーク接続は必要ありません。JobInfo.NETWORK_TYPE_UNMETERED
_:nmetered WiFiまたはイーサネット接続。JobInfo.NETWORK_TYPE_ANY
_:ネットワーク接続(WiFiまたはセルラー)。さて、問題は... NETWORK_TYPE_CELLUARはありません。セルラー上でonlyのときにのみアプリをウェイクアップさせることはできません。 (なぜそれをしたいのですか?)
他のキャッチ... WiFi接続は従量制または非従量制にすることができます。従量制接続は通常、モバイルホットスポットのようなものであり、これは自動的に検出されるか(ホットスポットが送信できる特別なDHCPオプションがあります)、またはユーザーがWiFi設定からネットワークごとに手動で切り替えることができます。
つまり、JobSchedulerジョブにネットワークタイプの制約を設定できます。ただし、いいえ、要求しているレベルの細分性は得られません。
@CommonsWareで述べたように、正当な理由がない限り、ネットワーク接続が測定されていないときにネットワーク関連のジョブが実行されるようにスケジュールするのが通常の考え方です。 (バッテリを節約するために、setRequiresCharging(true)
を使用してAC電源が利用可能になるまでジョブを延期することもお勧めします。)
これは最善の解決策ではない可能性があります。これに反対票を投じる前に、その理由を説明してください。
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
メソッドでこのタスクを初めてスケジュールします。