我试图让一个可以从其他几个活动中打开的活动仅在后退堆栈中出现一次(实际活动是“关于应用程序”对话框活动)。
假设活动A打开活动B,活动B打开活动C。我们希望堆栈看起来像A> B>C。如果活动C然后打开活动B(带有FLAG_ACTIVITY_REORDER_TO_FRONT标志),则我们希望堆栈看起来像A > C>B。在这种情况下,按回车键应将我们返回到C,然后再次按回车键应将我们返回到A,最后再按一次将打开该应用程序。
但是,如果活动B是对话活动,则在Oreo或Nougat下无法正常工作。在Oreo中,当C打开B时,什么也没有发生,并且堆栈仍然是A> B>C。在Nougat中,应用程序的其余部分从后台消失了,而后向堆栈似乎并没有保留以前的活动。
以下是一个演示该问题的示例应用程序。它提供了四个活动。
活动A(入口点)提供用于打开活动b和c的按钮。活动D相同,不同之处在于它在打开活动时会添加FLAG_ACTIVITY_REORDER_TO_FRONT标志。
活动B和C相同,除了活动C是对话活动,并且两者都只是提供了打开活动D的按钮。
当我们打开A,然后按按钮打开活动B时,活动将按预期方式打开。按下按钮以打开活动D,按预期方式工作。此时,堆栈看起来像A> B>D。从活动D的实例打开活动B应该将活动重新排序为A> D>B。按回退应该使我们返回D,然后回到A,最后退出应用程序。这完全符合预期。
问题是当我们在Oreo中涉及活动C(对话活动)时。我们打开应用程序,然后按按钮打开活动C。这按预期工作,然后按按钮打开活动D。同样,按预期工作,堆栈看起来像A> C>D。但是,按再次打开C的按钮不起作用。活动D仍显示在屏幕上。使用adb shell dumpsys activity
表示C已移到顶部,但未显示。按下返回将使我们回到C,然后回到A。
牛轧糖也会发生故障,但方式有所不同。重新排序活动后,它确实会出现,但是应用程序的其余部分会从屏幕上最小化/消失,而不是在后台显示。按下后退出应用程序,而不是返回活动D。
build.gradle
buildscript {
repositories {
mavenCentral()
jcenter()
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.pro'
}
}
}
src / main / AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.bad"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="25" />
<application
android:label="TestBad"
android:allowBackup="true"
android:fullBackupContent="true">
<activity android:name="ActA" android:label="Activity A">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ActB" android:label="Activity B"/>
<activity android:name="ActC" android:label="Activity C" android:theme="@android:style/Theme.Material.Dialog"/>
<activity android:name="ActD" android:label="Activity D"/>
</application>
</manifest>
src / main / java / com / bad / ActA.java
package com.bad;
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Window;
import android.widget.Button;
public class ActA extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_a);
((Button)findViewById(R.id.b_button)).setOnClickListener(but -> openActivity(ActB.class));
((Button)findViewById(R.id.c_button)).setOnClickListener(but -> openActivity(ActC.class));
}
void openActivity(Class<?> cls) {
Intent intent = new Intent(this,cls);
startActivity(intent);
}
}
src / main / java / com / bad / ActB.java
package com.bad;
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Window;
import android.widget.Button;
public class ActB extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_b);
((Button)findViewById(R.id.d_button)).setOnClickListener(but -> openActivity());
}
void openActivity() {
Intent intent = new Intent(this,ActD.class);
startActivity(intent);
}
}
src / main / java / com / bad / ActC.java
package com.bad;
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Window;
import android.widget.Button;
public class ActC extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_b);
((Button)findViewById(R.id.d_button)).setOnClickListener(but -> openActivity());
}
void openActivity() {
Intent intent = new Intent(this,ActD.class);
startActivity(intent);
}
}
src / main / java / com / bad / ActD.java
package com.bad;
import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.view.Window;
import android.widget.Button;
public class ActD extends Activity {
/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_a);
((Button)findViewById(R.id.b_button)).setOnClickListener(but -> openActivity(ActB.class));
((Button)findViewById(R.id.c_button)).setOnClickListener(but -> openActivity(ActC.class));
}
void openActivity(Class<?> cls) {
Intent intent = new Intent(this,cls);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(intent);
}
}
src / main / res / layout / act_a.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<Button
android:id="@+id/b_button"
android:text="open activity b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/c_button"
android:text="open activity c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
src / main / res / layout / act_b.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<Button
android:id="@+id/d_button"
android:text="open activity d"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
我正在运行Android Oreo(8.0.0)的Galaxy S8和运行牛轧糖(7.0)的Galaxy S6上进行测试。
有没有一种方法可以使对话框活动达到预期效果?