今さらだけど！　AndroidのWorkManagerをJavaで実装してみる(初級編)

# はじめに
AndroidのWorkManagerを使う機会があり、色々調べてみたことを備忘録として記します。
当記事はWorkManagerの基本的な使い方を記します。内容は初心者向けの簡単なものになっています。

# WorkManagerとは
[公式ページ](https://developer.android.com/topic/libraries/architecture/workmanager?hl=ja)によると以下のような記述があります
>WorkManager API を使用すると、アプリが終了、またはデバイスが再起動した場合でも実行することが要求される延期可能な非同期タスクのスケジュールを簡単に設定できます。

要するに、

* 遅延タスク、非同期タスクの実行に使える
* バックグラウンドで実行する

というAPIだということがわかります。
以前は、JobSchedulerやBroadcastReceiverを使って実装していたアレです。これが簡単にできるようになったみたいです。
詳細な機能としては、ネットワークや充電状態の制約を追加したり、実行タイミングを指定したりできるようです。また、APIレベルに応じて適切な方法で実装されているようですので、私たちはAPIレベルを気にすることなく実装できます。これはかなり便利なAPIですね。

# 今回作るもの (サンプルアプリ）
今回のサンプルアプリは、アプリを終了した10秒後に通知(今回はログ)を出力するアプリを作成します。

* アプリを終了した・・・　→　バックグラウンドでの実行
* 10秒後に・・・ →　実行タイミングの指定

これを試します。
しかも現在はAndroidではKotlinが主流ですが、今回はJavaで実装したいと思います。


## 実装
では、早速実装しましょう。
`Worker`を継承したクラスにタスクを実装し、`WorkRequest`に制約を追加し、`WorkManager`に実行依頼をするというような流れになります。

今回は以下の流れで説明します。
1. ライブラリの追加
2. バックグラウンドで動作するタスクの作成
3. タスクを実行する 


### ライブラリの追加
まずは、WorkManager ライブラリを Android プロジェクトにインポートします。アプリの`build.gradle` ファイルに次の依存関係を追加します。

``` java
dependencies {
    implementation "androidx.work:work-runtime:2.4.0"
    // ・・・（省略）・・・
}
```

### バックグラウンドで動作するタスクを作成する

タスクは`Worker`クラスを継承して実装します。 `doWork()` メソッドをオーバーライドします。

``` java
public class SampleWorker extends Worker {    // ・・・ (1)

    private static String TAG = SampleWorker.class.getName();

    public SampleWorker(Context context, WorkerParameters params) {
        super(context, params);
    }

    @Override
    public Result doWork() {                  // ・・・ (2)
        Log.d(TAG, "バックグラウンドタスクの実行");
        return Result.success();              // ・・・ (3)
    }
}
```

1. Workerクラスを継承しタスクを作成します。
2. doWorkメソッドをオーバーライドします。このメソッドにバックグラウンドで実行する処理を記述します。
3. doWorkメソッドは戻り値があります。今回は正常終了を返却します。

| 戻り値 | 概要 |
|:--|:--|
|Result.success()   |タスクが正常に終了したとき   |
|Result.failure()   |タスクが失敗したとき   |
|Result.retry()   |後でタスクを再試行する必要があるとき   |


### タスクを実行する
タスクを実行させるには、`WorkRequest`クラスを利用します。
`Worker` がタスクを定義するのに対し、`WorkRequest` はタスクを実行する方法とタイミングを定義します。タスクを1回だけ実行する`OneTimeWorkRequest`と、定期的に実行する`PeriodicWorkRequest`があります。
今回は、1回だけ実行する`OneTimeWorkRequest`を利用します。

``` java

public class SampleActivity extends AppCompatActivity {

    // ・・・（省略）・・・

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {      // ・・・ (1)
        if (keyCode == KeyEvent.KEYCODE_BACK) {
          
            // ・・・ (2)
            OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(SampleWorker.class)
                    .setInitialDelay(10, TimeUnit.SECONDS)       // ・・・ (3)
                    .build();

            WorkManager.getInstance(getApplicationContext()).enqueue(workRequest);
                                                                 // ・・・ (4)
        }

        return super.onKeyDown(keyCode, event);
    }
```

1. 今回のサンプルはバックグラウンドで動作していることがわかるようにアプリをバックキーで閉じたときに実行させます。
2. １回だけ実行する`OneTimeWorkRequest`を生成します。
3. 10秒後に実行するように制約を追加します。
4. `WorkRequest`を定義した後、`WorkManager`で`enqueue()`メソッドを使用して設定します。

## 動作確認
まず、アプリを起動します。次に、バックキーを押してホーム画面に戻ります（バックグラウンドへ）
10秒後にログが出力されれば成功です！

# まとめ
無事にサンプルは動作しましたか？
初めはわかりづらいかもしれませんが、何回か実装しているうちに慣れると思います。
WorkManagerは、いろいろな制約（充電中であるとか、ネットワークの接続状態など）が設定できます。また、定期的に実行する方法もあります。
このあたりは近いうちに記事にしたいと思います。

では、また！