Android 13调用Activity.startActivities时AOSP空指针崩溃求助
Android 13下启动Activity栈时的NullPointerException排查
崩溃现象
- 仅出现于Android 13系统
- 高发设备:三星Galaxy S23+/S22+/S22 Ultra/S21 FE 5G;OPPO Reno5、小米12、小米11T各出现1次
- 触发场景:仅在通过SplashActivity启动
ListActivity -> DetailsActivity任务栈时崩溃
堆栈信息
Non-fatal Exception: java.lang.NullPointerException Attempt to invoke virtual method 'com.android.server.wm.ActivityRecord com.android.server.wm.WindowContainer.getActivity(java.util.function.Predicate)' on a null object reference android.os.Parcel.createExceptionOrNull (Parcel.java:3029) android.os.Parcel.createException (Parcel.java:3007) android.os.Parcel.readException (Parcel.java:2990) android.os.Parcel.readException (Parcel.java:2932) android.app.IActivityTaskManager$Stub$Proxy.startActivities (IActivityTaskManager.java:2816) android.app.Instrumentation.execStartActivitiesAsUser (Instrumentation.java:1876) android.app.Instrumentation.execStartActivities (Instrumentation.java:1823) android.app.Activity.startActivities (Activity.java:6096) android.app.Activity.startActivities (Activity.java:6069) .SplashActivity.startMain (SplashActivity.java:149)
排查现状
怀疑崩溃源于自身实现(AOSP代码问题可能性低),尝试查阅AOSP中ActivityTaskManagerService.startActivities的实现,试图解析WindowContainer为空的原因,但代码导航困难、交叉引用失效,克隆仓库后仍未定位到相关逻辑,陷入瓶颈。
核心实现代码
SplashActivity简化逻辑
public final class SplashActivity { private boolean resumed; @Override protected void onStart() { super.onStart(); fetchAsyncData(SplashActivity::onDataFetched); } @Override protected void onPostResume() { super.onPostResume(); resumed = true; } @Override protected void onPause() { super.onPause(); resumed = false; } public void onDataFetched() { String res1, res2; // 解析深层链接或后台通知,填充res1、res2或置空 // 非活跃状态下不启动Activity if (resumed) { if (res1 != null && res2 != null) { Intent intent = getIntent(); Bundle extras = intent.getExtras(); Intent listIntent = new Intent(this, ListActivity.class); // 转发原Intent的参数和标记 listIntent.putExtras(extras != null ? extras : new Bundle()); listIntent.addFlags(intent.getFlags()); Intent detailsIntent = new Intent(this, DetailsActivity.class); detailsIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); detailsIntent.putExtra("res1", res1); detailsIntent.putExtra("res2", res2); startActivities(new Intent[]{listIntent, detailsIntent}); finish(); } else { // 启动其他Activity逻辑 } } } }
Manifest中Activity声明
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application> <activity android:name=".SplashActivity" android:launchMode="singleInstance" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter android:autoVerify="true" tools:targetApi="m"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="example.com" android:pathPattern="/res1/.*/res2/.*" /> </intent-filter> </activity> <activity android:name=".ListActivity" android:exported="true" android:launchMode="singleTop" /> <activity android:name=".DetailsActivity" android:launchMode="singleTop" android:exported="true" android:parentActivityName=".ListActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ListActivity" /> </activity> </application> </manifest>
问题分析与解决方案建议
可能的问题根源
- 启动模式冲突:SplashActivity是
singleInstance启动模式,属于独立任务栈,调用startActivities启动多Activity时,系统可能无法正确匹配任务栈,导致WindowContainer为空。 - Intent标记误用:DetailsActivity的Intent设置了
FLAG_ACTIVITY_CLEAR_TOP,该标记会清除目标Activity之上的所有Activity,但在启动栈的场景下,会干扰系统对新任务栈的创建逻辑。 - 生命周期判断不可靠:自定义的
resumed标记可能存在时序问题,异步数据返回时,Activity可能处于生命周期的过渡状态(如onPause执行中),此时调用startActivities会导致系统获取WindowContainer失败。
解决方案
- 调整启动模式:将SplashActivity的
singleInstance改为singleTask,避免独立任务栈带来的启动冲突;或者在启动Intent中显式指定任务栈信息(通过TaskStackBuilder或Intent.setFlags(FLAG_ACTIVITY_NEW_TASK)配合任务栈属性)。 - 修正Intent标记:移除DetailsActivity的
FLAG_ACTIVITY_CLEAR_TOP标记,依赖parentActivityName的导航关系来维护栈结构;若需要复用已存在的DetailsActivity,可单独在启动后通过onNewIntent处理参数。 - 优化生命周期判断:使用系统提供的
isResumed()方法替代自定义的resumed标记,确保Activity完全处于前台活跃状态后再执行启动逻辑;或者将数据加载逻辑移至onPostResume中,避免异步回调的时序问题。 - 添加异常兜底:在调用
startActivities的代码块外添加try-catch捕获NullPointerException,兜底处理(如降级启动单个ListActivity),避免影响用户体验。
内容的提问来源于stack exchange,提问作者Doc_1faux
相关产品推荐
相关产品推荐

