应用程序启动时调用 Activity.startActivities(Intent []intents) 时 AOSP 崩溃

问题描述 投票:0回答:1

我很难解决崩溃,该崩溃要么是由于我自己由于缺乏知识而导致的错误实现,要么是 AOSP 代码(我认为不太可能......)。 它似乎只发生在 Android 13 上,我主要在我没有的三星设备(Galaxy S23+/S22+/S22 Ultra/S21 FE 5G)上得到它(在 OPPO Reno5、小米 12 和小米 11T 上也发生过 1 次)。 这是堆栈跟踪:

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 代码中进行了搜索,以了解

WindowContainer
如何在
null
中成为
IActivityTaskManager.startActivities
,其实现似乎是
ActivityTaskManagerService.startActivities
,但很难深入了解 AOSP 代码...我也尝试过搜索
WindowContainer.getActivity
用法,但交叉引用似乎不适用于此文件...我还按照文档通过
repo
cmd 克隆了存储库,但我没有找到文件...所以我被卡住了:/

我已经实现了

SplashActivity
处理主启动器意图以及任何后台通知和深层链接点击,启动正确的活动或堆栈。 当我需要启动
list -> details
堆栈时,我只遇到崩溃。

这是它的最小综合代码:

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;
        // some code to parse either a deep link or background notification, ending in populated res1 & res2 or not
        // do not start any activity if not resumed (user goes back to home/other app/kills the app)
        if (resumed) {
            if (res1 != null && res2 != null) {
                Intent intent = getIntent();
                Bundle extras = intent.getExtras();

                Intent listIntent = new Intent(this, ListActivity.class);
                // forward extras/flags to new root 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 {
                // start other activities
            }
        }
    }
}

以下是

SplashActivity
ListActivity
DetailsActivity
AndroidManifest.xml
中的声明方式:

<?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>
android android-activity android-task
1个回答
0
投票

我已经更新了上面的代码以使用

TaskStackBuilder
来代替,因为看起来我之前已经这样实现过,但是改变了它,我不知道为什么...... 我会让你知道这是否修复了崩溃(再次?),假设
startActivities
方法已被弃用:/

public void onDataFetched() {
    String res1, res2;
    
    // some code to parse either a deep link or background notification, 
    // ending in populated res1 & res2 or not
    
    // do not start any activity if not resumed
    // (user goes back to home/other app/kills the app)
    if (resumed) {
        if (res1 != null && res2 != null) {
            Intent intent = getIntent();
            Bundle extras = intent.getExtras();

            Intent detailsIntent = new Intent(context, DetailsActivity.class);
            detailsIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP 
                                   | Intent.FLAG_ACTIVITY_CLEAR_TOP);
            detailsIntent.putExtra("res1", res1);
            detailsIntent.putExtra("res2", res2);

            TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
            stackBuilder.addNextIntentWithParentStack(detailsIntent);
            
            // forward extras/flags to list intent 
            // automatically added as new root because
            // declared as parent activity of DetailsActivity in AndroidManifest.xml
            Intent listIntent = stackBuilder.editIntentAt(0);
            if (listIntent != null)
            {
                listIntent.putExtras(extras != null ? extras : new Bundle());
                listIntent.addFlags(intent.getFlags());
            }

            stackBuilder.startActivities();
            finish();
        }
        else {
            // start other activities
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.