Android: процесс не завершается после выхода из приложения
Написал минимальный пример для демонстрации бага. По нажатию на кнопку запускается служба переднего плана. Текст на кнопке меняется с "▶" на "❚❚". При повторном нажатии, служба останавливается, а текст меняется обратно.
- Если запустить программу, а потом выйти, то всё работает как надо.
- Если запустить программу, запустить службу, потом остановить и выйти, то тоже всё как надо.
- Но если запустить программу, запустить службу а потом выйти, то процесс остаётся висеть в памяти. В т.ч. активна красная кнопка стоп в андроид - студии. Пробовал с onTaskRemoved и без, игрался с флагом манифеста
android:stopWithTask- не помогает. Хотя сама служба останавливается (Toastвыводит: "service stopped").
Вот код.
MainActivity.kt
package com.example.test_fgsvc
import android.app.Service
import android.content.Intent
import android.os.Bundle
import android.os.IBinder
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.PendingIntent.FLAG_IMMUTABLE
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
import android.content.Context
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING
import android.graphics.Color
import android.os.Build
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat.startForegroundService
import com.example.test_fgsvc.ui.theme.TestfgsvcTheme
class MyService : Service() {
private fun createNotification(): Notification {
val notificationChannelId = "ENDLESS SERVICE CHANNEL"
// depending on the Android API that we're dealing with we will have
// to use a specific method to create the notification
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager;
val channel = NotificationChannel(
notificationChannelId,
"Endless Service notifications channel",
NotificationManager.IMPORTANCE_HIGH
).let {
it.description = "Endless Service channel"
it.enableLights(true)
it.lightColor = Color.RED
it.enableVibration(true)
it.vibrationPattern = longArrayOf(100, 200, 300, 400, 500, 400, 300, 200, 400)
it
}
notificationManager.createNotificationChannel(channel)
}
val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
putExtra("type", type)
}
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.getActivity(this, 0, intent, FLAG_UPDATE_CURRENT or FLAG_IMMUTABLE)
} else {
PendingIntent.getActivity(this, 0, intent, FLAG_UPDATE_CURRENT)
}
val builder: Notification.Builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Notification.Builder(
this,
notificationChannelId
) else Notification.Builder(this)
return builder
.setContentTitle("saybot service")
.setContentText("saybot")
.setContentIntent(pendingIntent)
.setSmallIcon(R.mipmap.ic_launcher)
.setTicker("Ticker text")
.setPriority(Notification.PRIORITY_HIGH) // for under android 26 compatibility
.build()
}
override fun onDestroy()
{
Toast.makeText(this, "service stopped", Toast.LENGTH_LONG).show()
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onCreate() {
startForeground(1, createNotification(), FOREGROUND_SERVICE_TYPE_REMOTE_MESSAGING)
Toast.makeText(this, "service started", Toast.LENGTH_LONG).show()
}
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
return START_NOT_STICKY
}
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
override fun onTaskRemoved(rootIntent: Intent?) {
stopSelf()
}
}
class MainActivity : ComponentActivity() {
val btcap = listOf("❚❚", "▶")
lateinit var ctx : Context
val mysvcIntent : Intent = Intent()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ctx = this
mysvcIntent.setClass(ctx, MyService::class.java)
setContent {
TestfgsvcTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
//Greeting("Android")
Box(
modifier = Modifier
.fillMaxSize()
) {
var btnChecked by remember { mutableStateOf(false) }
Button(
enabled = true,
shape = RectangleShape,
onClick = {
if (btnChecked) { // pause
ctx.stopService(mysvcIntent)
} else { // play
startForegroundService(ctx, mysvcIntent)
}
btnChecked = !btnChecked
},
modifier = Modifier
.align(Alignment.Center)
) {
Text(btcap[if (btnChecked) 0 else 1])
}
}
}
}
}
} // onCreate
/*override fun onDestroy() {
super.onDestroy()
ctx.stopService(mysvcIntent)
}*/
}
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" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
<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.Testfgsvc"
tools:targetApi="31">
<service
android:name=".MyService"
android:enabled="true"
android:exported="false"
android:stopWithTask="false"
android:foregroundServiceType="remoteMessaging" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Testfgsvc">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Почему программа не завершается, и как это исправить?