Android サービスとは
Android端末でバックグラウンドで動作するアプリケーションです。
Empty Projectの作成
Android Studioの[File] - [New] - [New Project] から [Empty Activity]を選択する。ただしEmpty Project以外でももちろんOKです。
Language: Kotlin以外は適当でOKです。サービスとして動作するクラスの作成
Android Studioの[File] - [New] - [Kotlin Class/File]を選択する。
クラス名を ServiceSample とした例で以下を進めていきます。以下のプログラムに入れ替えてください。package jp.ac.nuis.nakada.myservice
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.ContentValues.TAG
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.util.Log
import androidx.annotation.RequiresApi
import java.util.*
// ServiceSampleクラスは、android.app.Serviceから派生させる。
class ServiceSample : Service() {
// onBindメソッドをオーバライドし、nullを返す。
override fun onBind(intent: Intent?): IBinder? {
return null
}
// onStartCommandメソッドをオーバライドする。
@RequiresApi(Build.VERSION_CODES.O)
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// ここでサービスとして実行する非同期処理のメソッドを呼び出す。
worker()
// 通知を出力する。
val channelID = TAG
val notificationManager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
if (notificationManager.getNotificationChannel(channelID) == null) {
val channel =
NotificationChannel(channelID, "サービス起動中通知", NotificationManager.IMPORTANCE_HIGH)
notificationManager.createNotificationChannel(channel)
}
val notification = Notification.Builder(applicationContext, channelID)
.setSmallIcon((R.drawable.ic_launcher_background))
.build()
startForeground(1, notification)
return START_NOT_STICKY
}
// サービスとして実行するメソッド
private fun worker() {
val timer = Timer()
timer.schedule(object: TimerTask(){
override fun run() {
Log.d(TAG,"timeout")
}
},1000,1000)
}
}
ServiceSampleクラスはandroid.app.Serviceクラスの派生となり、onBind、onStartCommandメソッドをオーバライドします。onBindではnullを返し、onStartCommandではサービスとして非同期処理を行うworkerメソッドを呼び出した後、サービスとして動作していることをユーザに通知します。この通知をしないとAndroidシステムにサービスが落とされるようです。
AndroidManifest.xmlでサービスを作ることを宣言する
Android Studioの左側でAndroidManifest.xmlを選択し、uses-permissionタグ、Serviceタグを追加する。
uses-permissionタグの詳細です。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
Serviceタグの詳細です。
<service android:name=".ServiceSample" android:foregroundServiceType="mediaProjection"
android:exported="true">
</service>
uses-permissionではフォアグランドサービスとして実施することの許可を行い、serviceタグでサービスのクラス名を指定しておきます。
MainActivityからサービスを起動する
package jp.ac.nuis.nakada.myservice
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.annotation.RequiresApi
class MainActivity : AppCompatActivity() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// ServiceSampleクラスのサービスを起動する。
startForegroundService(Intent(this,ServiceSample::class.java))
}
}
このアプリでは、起動と当時にサービスをスタートさせます。
実行を確認する
サービスとして動作する処理は、ServiceSampleクラスの Worker メソッドに記述した以下のプログラムです。
// サービスとして実行するメソッド
private fun worker() {
val timer = Timer()
timer.schedule(object: TimerTask(){
override fun run() {
Log.d(TAG,"timeout")
}
},1000,1000)
}
1秒のディレイ後に、1秒ごとにLogcatに"timeout"と表示します。
このアプリケーションをAndroidで実行して、Android端末でアプリケーションを終了させたときに、"timeout"が表示され続ければサービスとして実行されています。
サービスの終了方法
stopServiceメソッドによってサービスを終了させられるようですが、現在のプログラムではアプリの終了後にstopServiceを呼び出すところがないので、とりあえずAndroid Studioの終了ボタンで終了してください。