Androidのバックグラウンド実行
前々まではこういうのを使ってました
- ForegroundService
- IntentService
- AlarmManager
もちろん今でも使えるAPI達です
ですが実行時間が極端に短かったり、
API変更で裏で動かすのが難しくなりました
そこで登場したのがJobService
ここではこれを使って、
- JobServiceを拡張して作成し、
- バックグラウンド実行の登録し、
- 30分おきに通知を表示する
ということに挑戦してみました。
本当にエッセンスなことだけを解説します。
とにかくバックグラウンド実行するのが目的です
このページの目次
0.初めにJobServiceの制限とできることについて
JobServiceがどういった性質を持つのか…
それは箇条書きするとこうなります。
- バックグラウンドで様々な処理を動かせる
- 動かせるAPIに制限とかはないらしい
- 最小の定期実行間隔は15分(おそらく)
- ジョブの最大実行時間は10分ほど
数秒しか動かせないServiceと大違いです。
最大で1回あたり10分も動かせちゃいます。
大雑把な性質はこういう感じです。
1.まずJobServiceを拡張したクラスを作る
まずJobServiceを拡張したクラスを作ります
名前は NFTJobService とでもしましょう
※ NTF = Notificationの略
▼ 通知表示するコード例は次の通り
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
class NTFJobService : JobService() { override fun onStopJob(params: JobParameters?): Boolean { jobFinished(params, false) return false } override fun onStartJob(params: JobParameters?): Boolean { /// x分おきに呼ばれる処理 (x = 30) /// 通知を表示 showNotification( "JobSchedulerから実行", "30分おきに通知が表示されます" ) return true } private fun _showNotification(title: String, text: String){ /// 通知ID val notificationId = 1 /// 通知チャンネルID val CHANNEL_ID = "1" if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val name = getString(R.string.app_name) val descriptionText = "" val importance = NotificationManager.IMPORTANCE_DEFAULT val channel = NotificationChannel(CHANNEL_ID, name, importance).apply { description = descriptionText } // 通知チャンネルを登録 val notificationManager: NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager notificationManager.createNotificationChannel(channel) } /// 通知タップでMainActivityを開くように設定 val intent = Intent(this, MainActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_ONE_SHOT ) val builder: NotificationCompat.Builder = NotificationCompat.Builder(this, CHANNEL_ID) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle(title) .setContentText(text) .setStyle(NotificationCompat.BigTextStyle().bigText(text)) .setPriority(NotificationCompat.PRIORITY_HIGH) .setVibrate(longArrayOf(100, 0, 100, 0, 100, 0)) .setContentIntent(pendingIntent) with(NotificationManagerCompat.from(this)) { // notificationIdは通知ごとに固有なもの notify(notificationId, builder.build()) } } } |
スケジューラーが起動すると JobService#onStartJob が呼ばれます。
そこに通知表示・バッググラウンド処理を書けばOKです
2.AndroidManifest.xmlに自作サービスを登録
今作ったJobServiceを登録します。
▼ AndroidManifest.xmlに追加
1 2 3 |
<service android:name=".NTFJobService" android:permission="android.permission.BIND_JOB_SERVICE"></service> |
このタグをapplicationタグの内部に書くだけ
説明不要と思いますが android:name=".NTFJobService" のように先ほど作ったJobServiceを登録してます。あと android.permission.BIND_JOB_SERVICE というパーミッションも必須みたいです
3.MainActivityなどからJobServiceを起動する
最後はActivityからサービス起動するだけ
ここではMainActivityがあるものとします。
▼ MainActivity内で次のコードを実行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
class MainActivity : AppCompatActivity() { private val ALERT_SERVICE_JOB_ID = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) scheduleService() } /** * JobServiceをスケジューリング **/ private fun scheduleService(){ val scheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler /// サービスが動いているかの状態を取得 var hasBeenScheduled = false for (jobInfo in scheduler.allPendingJobs) { if (jobInfo.id == ALERT_SERVICE_JOB_ID) { hasBeenScheduled = true break } } /// 未稼働ならスケジュール登録 if( ! hasBeenScheduled) { val componentName = ComponentName(this, NTFJobService::class.java) val jobInfo = JobInfo.Builder(ALERT_SERVICE_JOB_ID, componentName) .apply { setBackoffCriteria(10000, JobInfo.BACKOFF_POLICY_LINEAR); setPersisted(false) setPeriodic(1000 * 60 * 30) /// <= 30分 setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE) setRequiresCharging(false) }.build() scheduler.schedule(jobInfo) } } } |
あとはJobSchdulerが定期的に実行されます。
実際にJobServiceで通知表示してみた様子
このような感じで正常に動作しました。
▼ バックグラウンドから通知表示できた
応用すれば色々なことに使えそう
ここまでのJobServiceの実行方法まとめ
簡単に箇条書きするとこんな感じ
- JobServiceを拡張したクラスを作る
- AndroidManifest.xmlに自作サービスを登録
- ActivityなどからJobServiceを起動する
従来のサービスより使い勝手がアップしてます。
ただし最大実行時間は10分なことに注意
以上、JobServiceによる通知表示でした。ではまた