用户滑动卸载应用前删除临时录音文件的实现问题
解决Android应用滑动卸载时删除临时录制文件的方案
这个场景确实有点棘手——因为用户从最近任务列表滑掉应用时,进程可能直接被终止,Activity的onDestroy方法不一定能正常执行,常规的退出逻辑会失效。不过我们可以结合WorkManager和全局状态记录来覆盖所有场景,确保未保存的临时文件一定会被清理掉。
核心思路
我们需要处理两种情况:
- 用户正常退出
ExoPlayerActivity(比如按返回键):直接在生命周期方法里删除文件。 - 用户滑掉应用/进程被系统杀死:用WorkManager启动延迟删除任务,同时在应用下次启动时兜底清理。
具体实现步骤
1. 先添加WorkManager依赖
在你的app/build.gradle中加入WorkManager的依赖(版本可以用最新稳定版):
implementation "androidx.work:work-runtime:2.8.1"
2. 创建删除文件的Worker类
这个类负责实际执行文件删除操作,即使应用进程被杀死,WorkManager也会在合适的时机触发它:
class DeleteTempFileWorker(context: Context, params: WorkerParameters) : Worker(context, params) { override fun doWork(): Result { val filePath = inputData.getString("FILE_PATH") ?: return Result.failure() val tempFile = File(filePath) // 删除文件 if (tempFile.exists()) tempFile.delete() // 清除临时文件的记录 val prefs = applicationContext.getSharedPreferences("TempFilePrefs", Context.MODE_PRIVATE) prefs.edit().remove("current_temp_file").apply() return Result.success() } }
3. 在ExoPlayerActivity中处理逻辑
我们需要跟踪用户是否点击了保存按钮,同时在Activity前后台切换时管理删除任务:
class ExoPlayerActivity : AppCompatActivity() { private var isSaved = false // 标记用户是否点击保存 private var tempFilePath: String? = null private var deleteWorkRequestId: UUID? = null // 记录Work任务ID,用于取消 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_exo_player) // 获取从SingActivity传递过来的文件路径 tempFilePath = intent.getStringExtra("RECORD_FILE_PATH") // 把文件路径存到SharedPreferences,防止进程被杀后丢失 val prefs = getSharedPreferences("TempFilePrefs", MODE_PRIVATE) prefs.edit().putString("current_temp_file", tempFilePath).apply() // 保存按钮点击事件 findViewById<Button>(R.id.btn_save).setOnClickListener { isSaved = true // 取消延迟删除任务 deleteWorkRequestId?.let { WorkManager.getInstance(this).cancelWorkById(it) } // 清除临时记录 prefs.edit().remove("current_temp_file").apply() Toast.makeText(this, "文件已保存", Toast.LENGTH_SHORT).show() finish() } } // 当Activity退到后台时,启动延迟删除任务 override fun onStop() { super.onStop() if (!isSaved && tempFilePath != null) { val constraints = Constraints.Builder() .setRequiredNetworkType(NetworkType.NOT_REQUIRED) // 不需要网络 .build() val data = Data.Builder() .putString("FILE_PATH", tempFilePath) .build() // 延迟10分钟执行删除,给用户留足够时间回到应用 val deleteWorkRequest = OneTimeWorkRequestBuilder<DeleteTempFileWorker>() .setConstraints(constraints) .setInitialDelay(10, TimeUnit.MINUTES) .setInputData(data) .build() deleteWorkRequestId = deleteWorkRequest.id WorkManager.getInstance(this).enqueue(deleteWorkRequest) } } // 当Activity回到前台时,取消删除任务 override fun onStart() { super.onStart() deleteWorkRequestId?.let { WorkManager.getInstance(this).cancelWorkById(it) } } // 正常退出时直接删除文件 override fun onDestroy() { super.onDestroy() if (!isSaved && tempFilePath != null) { val tempFile = File(tempFilePath!!) if (tempFile.exists()) tempFile.delete() val prefs = getSharedPreferences("TempFilePrefs", MODE_PRIVATE) prefs.edit().remove("current_temp_file").apply() } } }
4. 应用启动时兜底清理
万一WorkManager的任务没触发(比如系统长时间空闲),我们在应用启动时再检查一次,确保临时文件被删除:
class MyApplication : Application() { override fun onCreate() { super.onCreate() val prefs = getSharedPreferences("TempFilePrefs", MODE_PRIVATE) val tempFilePath = prefs.getString("current_temp_file", null) tempFilePath?.let { val tempFile = File(it) if (tempFile.exists()) tempFile.delete() prefs.edit().remove("current_temp_file").apply() } } }
记得在AndroidManifest.xml中注册这个Application:
<application android:name=".MyApplication" ...> ... </application>
方案优势
- 覆盖所有场景:不管用户是正常退出、滑掉应用,还是进程被系统杀死,未保存的临时文件都会被清理。
- 可靠性高:WorkManager是Android官方推荐的后台任务管理工具,能保证任务在合适的时机执行。
- 友好性:延迟删除给用户留了反悔时间,只要在延迟时间内回到应用,文件就不会被删除。
内容的提问来源于stack exchange,提问作者BraveEvidence
相关产品推荐
相关产品推荐

