Android Media3:点击媒体通知启动应用,PendingIntent附加数据丢失
问题分析与解决方案
核心问题根源
getLaunchIntentForPackage的局限性
该方法返回的是应用默认的启动Intent(带有MAIN/LAUNCHER过滤器),当应用已处于前台时,系统会复用栈顶的MainActivity实例,默认不会传递新Intent的extras——除非Activity配置了特定启动模式并正确处理新Intent。未处理
onNewIntent生命周期回调
当Activity以singleTop/singleTask模式运行且已在栈顶时,系统不会重新创建实例,而是调用onNewIntent传递新Intent。如果未重写该方法并更新Activity的Intent引用,onStart中获取的始终是旧Intent,自然拿不到新的extras。
具体修复步骤
1. 改用显式Intent替代默认启动Intent
避免依赖getLaunchIntentForPackage,直接创建指向MainActivity的显式Intent,确保extras能被正确传递:
// 在MediaSessionService的onCreate中修改intent创建逻辑 val intent = Intent(this, MainActivity::class.java) intent.putExtra("DESTINATION", "player") // 添加flags确保行为可控 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP) val pendingIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT ) mediaSession = MediaSession.Builder(this, player) .setSessionActivity(pendingIntent) .build()
2. 配置MainActivity的启动模式
在Manifest中给MainActivity添加singleTop启动模式,确保栈顶存在时复用实例并触发onNewIntent:
<!-- app模块的Manifest --> <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"> <!-- 添加这行 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
3. 重写MainActivity的onNewIntent方法
更新Activity的Intent引用并处理跳转逻辑:
class MainActivity : AppCompatActivity() { override fun onStart() { super.onStart() // 现在可以正确获取到最新的extras Timber.e("onStart: intents: ${intent.extras?.size()}") handleDestination(intent) } override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) // 必须更新Activity的intent变量,否则后续生命周期拿到的还是旧值 setIntent(intent) handleDestination(intent) } private fun handleDestination(intent: Intent?) { intent?.getStringExtra("DESTINATION")?.let { destination -> if (destination == "player") { // 跳转至播放器UI的逻辑 } } } }
额外注意事项
- API 34要求PendingIntent必须指定
FLAG_IMMUTABLE或FLAG_MUTABLE,你当前使用的FLAG_IMMUTABLE符合要求。 - 由于
MainActivity和MediaSessionService分属不同模块,确保MainActivity的全类名在显式Intent中正确引用(如果存在包名差异,需使用完整包名+类名)。
内容的提问来源于stack exchange,提问作者rysv
相关产品推荐
相关产品推荐

