Android API21から追加されたJobSchedulerに慣れていこう

こんにちは、KID.Aです。

 

最近、Camera周りの記事が多かったため、ここら辺で違う記事を書こうと思います。

 

ちょっと古いですが、API Level 21(L)から追加されたJobSchedulerの記事になります。

Android開発者ならおそらく知っていると思いますが、API Level 21(L)から追加されたJobSchedulerというものがあります。

開発サイトのAPI
https://developer.android.com/intl/ja/reference/android/app/job/JobScheduler.html

Lから追加されておりますが、サポートライブラリーなどに組み込まれておらず2.3や4.0から対応させているアプリ開発者はあまり使う機会ないというのが現状だと思います。

ただMがリリースされてこれからKitkat以前のバージョンが減ってきたらJobSchedulerが使える機会が増えてくると思います。今回はJobSchedulerに慣れようということで簡単な概要や使い方を記載しようと思います。

 

・JobSchedulerとは?

Project Volta(簡単にいうとGoogleのバッテリーの省電力プロジェクト)がバッテリーを長くするために提供したAPIです。開発者はJobSchedulerで消費電力を意識した実装ができます。

JobSchedulerは色々な種類のジョブをスケジュールしてくれるAPIです。
設定した種類の条件と端末の状態があっていればジョブを実行してくれます。
また実行遅延やリトライ間隔などの細かな設定もできます。

どのような設定ができるか見てみましょう。

メソッド名 説明
setBackoffCriteria back-off/retryのポリシーを設定できます。retry時間を2、4、8など遅れさせることができます。
setMinimumLatency 実行前の遅延時間を設定することができます。
setExtras PersistableBundleを設定できます。
setOverrideDeadline スケジュールの最大遅延時間を設定することができます。
setPeriodic 数回実行する場合に、実行間隔を設定することができます。
setPersisted デバイス再起動後もタスクを実行するかどうかを設定できます。アプリがRECEIVE_BOOT_COMPLETED権限がなければ効果がありません。
setRequiredNetworkType ネットワークが必要かどうかを設定できます。ネットワークが必要な場合は、ネットワークが利用できない状況でタスクは実行されません。
setRequiresCharging デバイスを電源に接続している必要があるか設定できます。デフォルトは必要なしに設定されています。
setRequiresDeviceIdle アイドルモード上で動作するか設定できます。アイドルモードでは、デバイスが使用されていない状態で、使用されていないかどうかはシステムが定義しています。

かなり細かい動作ができますね。

 

それでは実際に動かしてみましょう。
以下はボタンを押下したらJobScheduler経由でトーストがでるサンプルコードになります。

まずはJobServiceを継承したサービスを作ります。
・MyJobService.java

public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(JobParameters params) {
        new ToastTask().execute(params);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        return false;
    }


    private class ToastTask extends AsyncTask<JobParameters, Void, String> {

        protected JobParameters mJobParam;

        @Override
        protected String doInBackground(JobParameters... params) {
            mJobParam = params[0];
            return String.valueOf(mJobParam.getJobId());
        }

        @Override
        protected void onPostExecute(String result) {
            jobFinished(mJobParam, false);
            Toast.makeText(MyJobService.this, "job id = " + result, Toast.LENGTH_SHORT).show();
        }
    }

}

 

ボタンをつけたactivityを作ります。(単純なボタンでよいのでlayout.xmlは省きます)
・MainActivity.java

public class MainActivity extends AppCompatActivity {

    ComponentName mServiceName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mServiceName = new ComponentName(this, MyJobService.class);
        Intent intent = new Intent(this, MyJobService.class);
        startService(intent);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
                for (int i = 0; i < 2; i++) {
                   JobInfo jobInfo = new JobInfo.Builder(i, mServiceName)
                            .setMinimumLatency(3000)
                            .setOverrideDeadline(60000)
                            .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                            .build();
                    scheduler.schedule(jobInfo);
                }
            }
        });
    }
}

 

AndroidManifestに以下のように記載しいます。
Serviceにはandroid.permission.BIND_JOB_SERVICEが必要です。
・AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package=“jp.co.jobscheduler" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name=".MyJobService"
                 android:permission="android.permission.BIND_JOB_SERVICE"
                 android:exported="true" />
    </application>

</manifest>

 

簡単に一連の流れを説明すると、

  1. JobInfo.BuilderでJobInfoオブジェクトを作成します
  2. JobSchedulerに渡して実行します
  3. MyJobServiceのonStartJobが呼ばれます
  4. jobFinishedを呼ぶとMyJobServiceのonStopJobが呼ばれます

になります。

 

今回のアプリではJobInfo.Builderで以下の設定をしています。
・setMinimumLatency(3000)⇒実行時間を3秒遅らせる
・setOverrideDeadline(60000)⇒ジョブの最大遅延時間60秒
・setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)⇒ネットワークが有効のときに実行する

ボタンを押下してから、3秒後にトーストがでると思います。
また、setRequiredNetworkTypeがJobInfo.NETWORK_TYPE_ANYにしているのでネットワークを有効にしていないとボタンを押下してもトーストがでないです。
ネットワークが無効の状態で、ボタンを押下後にネットワークを有効にすると60秒の期間内であればタスクが実行されてトーストがでます。

 

状態によってジョブを実装の可否を自動的に判定してくれます。これで不要な処理を実行させないことにより省電力につなげることができるはずです。

 

省電力を意識することはユーザにとってよいし、その分(マーケットや顧客に)指摘される心配も少なくなるので開発者にとってもよいことです。
もしLから対応するアプリであれば使うのを考えるのもよいと思います。

 

 

KID.A

KID.A の紹介

楽して生きることと一発逆転を夢見ている、ちゃきちゃきのAndroiderです。 いろいろアプリを出しているのですが、いつもリリース後にターゲットユーザ数を2桁見誤っていたことに気付くので、残念でなりません。下方修正で、ヒットがでません。おしいです。 明日から本気出します。 よろしくお願いします。
カテゴリー: Android タグ: , , , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です