web-dev-qa-db-ja.com

AndroidでJobSchedulersを使用してネットワーク状態の変化を検出します

Android Nの場合、CONNECTIVITY_CHANGEインテントのブロードキャストレシーバーを静的に登録することはできません。

http://developer.Android.com/preview/features/background-optimization.html#connectivity-action からGoogleのドキュメントでは、ジョブスケジューラを使用してこのタスクを実行することを推奨しています。

Androidのジョブスケジューラを使用してネットワーク状態の変化(LTEからwifi)を検出することは可能ですか?

16
Mrunal

はいといいえ。

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電源が利用可能になるまでジョブを延期することもお勧めします。)

14
Trevor Johns

これは最善の解決策ではない可能性があります。これに反対票を投じる前に、その理由を説明してください。

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メソッドでこのタスクを初めてスケジュールします。

3
Vajira Lasantha