Android Studio: サービスの使い方

## サービスで、Logcat にメッセージを出す。
こちらのプログラムと同様なことを行います。
[Android サービスの作成 (2022年1月 記事作成)](https://qiita.com/toyohisa/items/31fecb5efde97697df86)

私が作成したプログラムは、何かの問題があります。
サービスが動いたり、動かなかったりします。
原因は、調べている最中です。

## プロジェクトの作成
プロジェクト名: service01

## 環境

```xml:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Service03"
        tools:targetApi="31">
        <service
            android:name=".ServiceSample"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="mediaProjection"></service>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
```

次を加えました。

```xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
```

次は、サービスを作成した時に自動で加わりました。

```xml
<service
            android:name=".ServiceSample"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="mediaProjection"></service>
```



## 画面

```xml:layer/activity_main.xml
```

## プログラム

```:MainActivity.kt
package com.example.service01

import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.annotation.RequiresApi

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        println("*** main *** aaa ***")
        // ServiceSampleクラスのサービスを起動する。
        startForegroundService(Intent(this, ServiceSample::class.java))
println("*** main *** ccc ***")
    }
}
```

```:ServiceSample.kt
package com.example.service01

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() {
    private var counter: Int = 0
    // onBindメソッドをオーバライドし、nullを返す。
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    // onStartCommandメソッドをオーバライドする。
    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\tcounter =  " + counter)
                counter++
            }
        },1000,1000)
    }
}
```

実行結果
これは、うまく動いた時です。同じコードで動かないこともあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/cf81b1ed-f751-84f7-ce87-e1a33d3c0eb4.png)

## 動かない時のエラーメッセージ

```text
FATAL EXCEPTION: main                  
Process: com.example.service03, PID: 8576
java.lang.RuntimeException: Unable to start service com.example.service03.ServiceSample@8d38369 with Intent { cmp=com.example.service03/.ServiceSample }: java.lang.SecurityException: Starting FGS with type mediaProjection callerApp=ProcessRecord{e5d2894 8576:com.example.service03/u0a191} targetSDK=34 requires permissions: all of the permissions allOf=true [android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION] any of the permissions allOf=false [android.permission.CAPTURE_VIDEO_OUTPUT, android:project_media] 
        
        at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4839)

        at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(Unknown Source:0)

        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289)
```                                                                                        


                                                                                        
## adb でログを見る方法

```bash
adb logcat
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ac061bd7-75c6-f033-185a-6b61f313b73f.png)

adb で、emulator が見える時は次のようになります。

```text
$ adb devices
List of devices attached
emulator-5554	device
```

## adb の　Ubuntu へのインストール方法

```bash
sudo apt install google-android-platform-tools-installer
```