You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中DialogActivity执行onDestroy后仍驻留后台的解决求助

问题描述

我正在开发一款每10秒询问用户当前行为的应用,为此创建了用于弹出多选对话框的DialogActivity,以及触发它的Worker和MainActivity代码(代码见下方)。

问题:点击对话框的OK/取消按钮后,对话框消失,但DialogActivity仍驻留在后台可重新打开,且已确认onDestroy方法已被调用。设备为基于Android 12的MIUI 14.0.1,求彻底销毁该Activity的方法。

DialogActivity代码

import android.app.AlertDialog
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import java.util.concurrent.TimeUnit

class DialogActivity : AppCompatActivity() {
    override fun onStop() {
        super.onStop()
        Log.d("DialogActivity", "onStop")
        // Votre code personnalisé ici
    }
    override fun onDestroy() {
        super.onDestroy()
        Log.d("DialogActivity", "onDestroy")

    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val builder = AlertDialog.Builder(this)
        builder.setTitle("Que fais-tu ?")

        val items = arrayOf("Activité 1", "Activité 2", "Activité 3")
        val checkedItems = BooleanArray(items.size) { false }
        builder.setMultiChoiceItems(items, checkedItems) { _, which, isChecked ->
            checkedItems[which] = isChecked
        }

        builder.setPositiveButton("OK") { _, _ ->
            val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] }
            Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems")
            //planNextWorker()
            finishAffinity()
        }

        builder.setNegativeButton("Annuler") { dialog, _ ->
            dialog.cancel()
            //planNextWorker()
            finishAffinity()
        }

        builder.setOnCancelListener {
            //planNextWorker()
            finishAffinity()
        }

        // Afficher le dialogue APRÈS avoir défini tous les écouteurs et les boutons.
        builder.show()
    }

    private fun planNextWorker() {
        val followUpRequest = OneTimeWorkRequest.Builder(UserActivityAskingWorker::class.java)
            .setInitialDelay(10, TimeUnit.SECONDS)
            .build()
        WorkManager.getInstance(this).enqueue(followUpRequest)
    }
}

MainActivity及Worker代码

package com.treehousetutorial.controll_app_0_2

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.treehousetutorial.controll_app_0_2.ui.theme.Controll_app_0_2Theme
import java.util.concurrent.TimeUnit

class MainActivity : ComponentActivity() {
    private val overlayPermissionLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
        // Gérez le résultat ici si nécessaire
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Demander la permission SYSTEM_ALERT_WINDOW
        if (!Settings.canDrawOverlays(this)) {
            val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:$packageName"))
            overlayPermissionLauncher.launch(intent)
        }

        setContent {
            Controll_app_0_2Theme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Greeting("Android")
                }
            }
        }

        // Commencer le Worker
        startOneTimeWork()
    }

    private fun startOneTimeWork() {
        val oneTimeRequest = OneTimeWorkRequest.Builder(UserActivityAskingWorker::class.java)
            .setInitialDelay(10, TimeUnit.SECONDS)
            .build()

        WorkManager.getInstance(this).enqueue(oneTimeRequest)
    }

    companion object {
        const val OVERLAY_PERMISSION_REQ_CODE = 1001
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    Controll_app_0_2Theme {
        Greeting("Android")
    }
}

class UserActivityAskingWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {

    override fun doWork(): Result {
        val intent = Intent(applicationContext, DialogActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
        applicationContext.startActivity(intent)

        return Result.success()
    }
}
解决方案

针对MIUI系统的定制化任务栈管理逻辑,可尝试以下几种方法彻底销毁DialogActivity:

1. 替换finishAffinity()为finishAndRemoveTask()

finishAffinity()仅结束当前任务栈内有亲缘关系的Activity,但MIUI可能仍保留任务栈记录。finishAndRemoveTask()会直接将整个任务栈从系统最近任务列表中移除:

// OK按钮点击事件
builder.setPositiveButton("OK") { _, _ ->
    val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] }
    Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems")
    //planNextWorker()
    finishAndRemoveTask()
}

// 取消按钮点击事件
builder.setNegativeButton("Annuler") { dialog, _ ->
    dialog.cancel()
    //planNextWorker()
    finishAndRemoveTask()
}

// 对话框取消监听
builder.setOnCancelListener {
    //planNextWorker()
    finishAndRemoveTask()
}

2. 在Manifest中配置Activity的历史记录属性

给DialogActivity添加android:noHistory="true"和android:excludeFromRecents="true"属性,确保Activity退出后不会留在历史栈和最近任务列表中:

<activity
    android:name=".DialogActivity"
    android:noHistory="true"
    android:excludeFromRecents="true" />

3. 启动Activity时添加FLAG_ACTIVITY_NO_HISTORY标记

在Worker启动DialogActivity时,添加该标记让Activity不会被加入任务栈历史:

class UserActivityAskingWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
    override fun doWork(): Result {
        val intent = Intent(applicationContext, DialogActivity::class.java)
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 
                        or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
                        or Intent.FLAG_ACTIVITY_NO_HISTORY)
        applicationContext.startActivity(intent)
        return Result.success()
    }
}

4. 组合调用多种销毁方法

如果单一方法无效,可组合调用确保彻底清理:

builder.setPositiveButton("OK") { _, _ ->
    val selectedItems = items.filterIndexed { index, _ -> checkedItems[index] }
    Log.d("DialogActivity", "L'utilisateur a sélectionné : $selectedItems")
    //planNextWorker()
    finish()
    finishAffinity()
    finishAndRemoveTask()
}

优先尝试方法1和方法2的组合,这是针对MIUI系统最有效的解决方案。

内容的提问来源于stack exchange,提问作者Brinax

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:44:56