[当前台服务最后一次停止时,应用程序继续运行

问题描述 投票:4回答:1

我遇到了与前台服务相结合的Android流程管理中的一种行为,这确实让我感到困惑。

对我来说什么合理

  1. [当您从“最新应用”中滑动您的应用时,操作系统应在相对不久的将来完成应用程序流程。
  2. [当您在运行“前台服务,该应用程序仍然有效。
  3. [当您从“最近使用的应用”与1)相同。

什么让我感到困惑

[如果您在前台没有任何活动的情况下停止了前台服务(该应用程序不会出现在“最近使用的应用程序”中,那么我希望该应用程序现在被杀死。

但是,这没有发生,应用程序仍然有效。

示例

我创建了一个显示此行为的最小示例。

ForegroundService:

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
import timber.log.Timber

class MyService : Service() {

    override fun onBind(intent: Intent?): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        Timber.d("onCreate")
    }

    override fun onDestroy() {
        super.onDestroy()
        Timber.d("onDestroy")

        // just to make sure the service really stops
        stopForeground(true)
        stopSelf()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Timber.d("onStartCommand")
        startForeground(ID, serviceNotification())
        return START_NOT_STICKY
    }

    private fun serviceNotification(): Notification {
        createChannel()

        val stopServiceIntent = PendingIntent.getBroadcast(
            this,
            0,
            Intent(this, StopServiceReceiver::class.java),
            PendingIntent.FLAG_UPDATE_CURRENT
        )
        return NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle("This is my service")
            .setContentText("It runs as a foreground service.")
            .addAction(0, "Stop", stopServiceIntent)
            .build()
    }

    private fun createChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationManager = getSystemService(NotificationManager::class.java)
            notificationManager.createNotificationChannel(
                NotificationChannel(
                    CHANNEL_ID,
                    "Test channel",
                    NotificationManager.IMPORTANCE_DEFAULT
                )
            )
        }
    }

    companion object {
        private const val ID = 532207
        private const val CHANNEL_ID = "test_channel"

        fun newIntent(context: Context) = Intent(context, MyService::class.java)
    }
}

BroadcastReceiver停止服务:

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class StopServiceReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {

        val serviceIntent = MyService.newIntent(context)

        context.stopService(serviceIntent)
    }
}

活动:

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        startService(MyService.newIntent(this))
    }
}

清单:

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

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        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=".MyService"/>
        <receiver android:name=".StopServiceReceiver" />
    </application>

</manifest>

尝试以下方法:

  1. 启动应用程序,停止前台服务,从“最新应用程序”中删除应用程序
  2. 启动应用程序,从“最新应用程序”中删除应用程序,停止前台服务

[您可以在Android Studio的LogCat中看到,案例1的应用程序进程被标记为[DEAD],案例2则没有。

由于复制非常容易,这可能是预期的行为,但是我在文档中没有发现任何真正的提及。

有人知道这里发生了什么吗?

我遇到了与前台服务结合在一起的Android流程管理行为,这确实让我感到困惑。对我来说合理的是当您从“最近的应用程序”中滑动应用程序时,...

android foreground-service
1个回答
0
投票

这取决于前台服务的实际作用。如果它使用线程,网络连接,文件I / O等消耗内存的活动,即使您尝试停止该服务,它也不会被破坏,因此该过程将继续存在。这还包括在尝试停止服务时仍保持活动状态的所有接口回调。特别是那些仍在运行(甚至中断)并且绑定了服务的线程会阻塞生命周期,从而无法正常停止该服务。

© www.soinside.com 2019 - 2024. All rights reserved.