Android WebView下载打开PDF时如何避免返回栈留存旧PDF
问题解决方案
核心根因
你遇到的多次返回问题由两个常见开发误区导致:
- 给
ACTION_VIEWIntent设置的启动标记被Intent.createChooser覆盖,并未实际生效,多次打开PDF会持续往任务栈中压入新的PDF查看Activity实例 - 每次触发下载都会注册新的广播接收器,没有做注销逻辑,不仅会内存泄漏,还可能出现重复回调打开多份PDF的问题
具体修改步骤
1. 调整Intent启动逻辑与标记设置
方案A(保留应用选择器)
将标记设置在createChooser返回的Intent上,同时调整标记组合为FLAG_ACTIVITY_CLEAR_TOP,保证打开新PDF时清空当前任务栈中已存在的PDF查看Activity实例:
val viewIntent = Intent(Intent.ACTION_VIEW).apply { setDataAndType(Uri.parse(downloadLocalUri), downloadMimeType) // 补充读权限,否则第三方应用无法读取你存在应用专属目录的PDF addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } if (viewIntent.resolveActivity(packageManager) != null) { val chooserIntent = Intent.createChooser(viewIntent, "Choose app") // 给选择器返回的Intent设置启动标记,此处才是实际生效的位置 chooserIntent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK startActivity(chooserIntent) }
方案B(不需要选择器,默认打开上次选的PDF应用)
直接启动原Intent,设置正确的启动标记即可:
val viewIntent = Intent(Intent.ACTION_VIEW).apply { setDataAndType(Uri.parse(downloadLocalUri), downloadMimeType) flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_GRANT_READ_URI_PERMISSION } startActivity(viewIntent)
2. 修复广播接收器泄漏问题
将广播接收器声明为类成员变量,在Activity的onDestroy生命周期中调用unregisterReceiver注销,避免多次注册重复触发。
// 类成员变量声明 private var downloadReceiver: BroadcastReceiver? = null // 下载监听中注册接收器改为给成员变量赋值 downloadReceiver = object: BroadcastReceiver() { // 原有onReceive逻辑保持不变 } registerReceiver(downloadReceiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) // 重写onDestroy注销接收器 override fun onDestroy() { super.onDestroy() downloadReceiver?.let { unregisterReceiver(it) } }
注意不要使用原有代码的
FLAG_ACTIVITY_CLEAR_TASK标记,该标记会清空整个任务栈包括你自己的应用Activity,不符合返回后回到自有应用的需求。
内容的提问来源于stack exchange,提问作者Ogre
相关产品推荐
相关产品推荐

