在Android 10(SDK 29)上运行我的应用程序(最小SDK 21)时遇到问题。
应用程序的初始活动即将开始,并按预期显示。现在,当按下按钮以在顶部弹出第二个活动时,我看到以下崩溃日志:
java.lang.IllegalStateException: Activity top position already set to onTop=false
at android.app.ActivityThread.handleTopResumedActivityChanged(ActivityThread.java:4370)
at android.app.servertransaction.TopResumedActivityChangeItem.execute(TopResumedActivityChangeItem.java:39)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
第二个活动是针对SDK 29以下的所有Android版本正常启动。代码很简单
this.startActivity (new Intent (MyFirstActivity.this, MySecondActivity.class));
关于什么可能触发此问题以及异常(“活动顶部位置已设置为onTop = false”)实际上告诉我的任何提示?
为方便起见,这是ActivityThread.java代码:
@Override
public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r == null || r.activity == null) {
Slog.w(TAG, "Not found target activity to report position change for token: " + token);
return;
}
if (DEBUG_ORDER) {
Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r);
}
if (r.isTopResumedActivity == onTop) {
throw new IllegalStateException("Activity top position already set to onTop=" + onTop);
}
r.isTopResumedActivity = onTop;
if (r.getLifecycleState() == ON_RESUME) {
reportTopResumedActivityChanged(r, onTop, "topStateChangedWhenResumed");
} else {
if (DEBUG_ORDER) {
Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState());
}
}
}
以下是AndroidManifest的摘录:
<application
...
<activity
android:name="com.xxx.MyFirstActivity"
android:label="@string/${applicationLabel}"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...
<activity
android:name="com.xxx.MySecondActivity"
android:label="@string/ls_Quick_Reference"
android:icon="@drawable/action_help" >
</activity>
...
</application>
答案 0 :(得分:0)
我在这里回答我自己的问题。我已经在Google / Android的跟踪工具中对此提交了一个错误,并与作者并行联系。
https://issuetracker.google.com/issues/140571893
总而言之,我的部分代码搞砸了Android的活动堆栈,导致崩溃的原因是延迟的结果。
详细信息:启动我的应用程序时,有时有必要从以前的运行中运行一些迁移或修复操作。由于这些操作需要在主线程上完成,并且我想通知用户他/她需要稍等一下,因此提出了显示消息的视图。由于我的应用程序正忙于主线程,因此显示没有刷新,并且视图不可见。要解决此问题,我运行了一个“内部循环”以允许发送显示消息:
try
{
// At this point all draw events should be in the event queue,
// now add another event to the end of queue to finish the loop once everything is processed.
Handler handler = new Handler (Looper.myLooper());
handler.postDelayed (new Runnable() {
@Override
public void run() {
throw new FinishLoopRunTimeException();
}
}, 50);
Looper.loop();
}
catch (FinishLoopRunTimeException e) {}
FinishLoopRunTimeException是RuntimeException的简单特化。
虽然这是刷新显示消息的有效方法,但在Android 10中更改活动状态时,不得运行Looper.loop()。对于我的应用程序,情况如此,因为主要活动处于中间状态该代码运行时启动。如果这样做,活动线程的状态将被破坏,另一个活动的稍后启动将崩溃。
因此,解决方案是在为Android 10执行内部循环时确保活动处于稳定状态。较旧的Android版本未显示此问题。
虽然这可以被认为是Android 10的错误(在Looper文档中没有提及活动状态,不能更改),并且应该在以后的版本中修复为更健壮,但可以通过使用Looper代码来解决此问题。 / p>