Android:在launchMode =“singleTask”中的错误? – >活动堆栈未保存

我的主要活动A在清单中设置了android:launchMode="singleTask" 。 现在,每当我从那里开始另一个活动,例如B ,然后按手机上的HOME BUTTON返回到主屏幕,然后再次回到我的应用程序,通过按下应用程序的button或长按HOME BUTTON显示我的最近的应用程序不会保留我的活动堆栈,并直接返回到A而不是预期的活动B

这里有两个行为:

 Expected: A > B > HOME > B Actual: A > B > HOME > A (bad!) 

有没有我错过的设置或这是一个错误? 如果是后者,是否有解决方法,直到错误被修复?

供参考:这个问题已经在这里讨论了 。 不过,目前似乎还没有任何真正的解决scheme。

这不是一个错误。 当现有的singleTask活动启动时,堆栈中的所有其他活动将被销毁。

当您按HOME并再次启动活动时, ActivityManger调用一个意图

 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]flag=FLAG_ACTIVITY_NEW_TASK|FLAG_ACTIVITY_RESET_IF_NEEDED cmp=A} 

所以结果是A> B> HOME> A.

A的launchMode是“标准”的时候是不一样的。 包含A的任务将会前台并保持与以前相同的状态。

您可以创build一个“标准”活动,例如。 C作为启动程序,并在C的onCreate方法中使用startActivity(A)

要么

只要移除launchMode="singleTask"并设置launchMode="singleTask" FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP标志,每当调用一个意图到A

斯蒂芬,你有没有find答案呢? 我把这个testing用例放在一起,看到相同的(令人费解的)行为…我会粘贴下面的代码,以防万一有人出现,看到一些明显的东西:

AndroidManifest.xml中:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example" > <uses-sdk android:minSdkVersion="3"/> <application android:icon="@drawable/icon" android:label="testSingleTask"> <activity android:name=".ActivityA" android:launchMode="singleTask"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".ActivityB"/> </application> </manifest> 

ActivityA.java:

 public class ActivityA extends Activity implements View.OnClickListener { @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.main ); View button = findViewById( R.id.tacos ); button.setOnClickListener( this ); } public void onClick( View view ) { //Intent i = new Intent( this, ActivityB.class ); Intent i = new Intent(); i.setComponent( new ComponentName( this, ActivityB.class ) ); startActivity( i ); } } 

ActivityB.java:

 public class ActivityB extends Activity { @Override public void onCreate( Bundle savedInstanceState ) { super.onCreate( savedInstanceState ); setContentView( R.layout.layout_b ); } } 

我试图改变minSdkVersion无济于事。 这似乎只是一个错误,至less根据文件 ,其中说明如下:

如上所述,“singleTask”或“singleInstance”活动不会有一个以上的实例,所以这个实例可以处理所有新的意图。 一个“singleInstance”活动总是在堆栈顶部(因为它是任务中唯一的活动),所以它总是处于处理意图的位置。 然而,一个“singleTask”活动在堆栈中可能有或者没有其他的活动。 如果是这样,那么它就无法处理这个意图,意图就被抛弃了。 (即使意图被放弃了,它的到来也会导致任务到达前台,并保持原样)。

Frome http://developer.android.com/guide/topics/manifest/activity-element.html关于;singleTask

系统在新任务的根目录下创build活动,并将意图发送给它。 但是,如果活动的实例已经存在,则系统通过调用onNewIntent()方法将意图路由到现有实例,而不是创build新实例。

这意味着,当action.MAIN和category.LAUNCHER标志将您的应用程序从Launcher中引导时,系统宁愿将意图路由到现有的ActivityA,而不是创build一个新的任务并将一个新的ActivityA设置为根。 它宁愿拆除ActivityA所在的现有任务上的所有活动,并调用onNewIntent()。

如果要捕获singleTop和singleTask的行为,请使用singleTask launchMode创build一个名为SingleTaskActivity的单独“委托”活动,它只是在其onCreate()中调用singleTop活动,然后自行完成。 singleTop活动仍然具有MAIN / LAUNCHER意图filter继续作为应用程序的主Launcher活动,但是当其他活动需要调用此SingleTop活动时,它必须调用SingleTaskActivity来保留singleTask行为。 传递给singleTop活动的意图也应该inheritance到singleTop活动,所以类似下面的内容已经为我工作,因为我想有singleTask和singleTop启动模式。

 <activity android:name=".activities.SingleTaskActivity" android:launchMode="singleTask"> public class SingleTaskActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); intent.setClass(this, SingleTop.class); startActivity(intent); } } 

而你的singleTop活动将继续拥有singleTop启动模式。

  <activity android:name=".activities.SingleTopActivity" android:launchMode="singleTop"/> 

祝你好运。

如果A和B都属于同一个Application ,请尝试删除

 android:launchMode="singleTask" 

从您的Activities和testing,因为我认为默认行为是你所描述的预期。

我认为这是你想要的行为:

singleTask在家庭媒体上重新设置了一些我不明白的原因。 该解决scheme是不使用singleTask,并使用标准singleTop发射器的活动,而不是(我只尝试与singleTop迄今为止)。

因为应用程序彼此之间有亲和力,所以启动一个这样的活动:

 Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageName); if(launchIntent!=null) { launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); } 

会导致你的活动堆栈重新出现,没有开始一个新的活动(这是我以前的主要问题)。 旗帜是重要的

FLAG_ACTIVITY_NEW_TASK在API级别1中添加

如果设置,此活动将成为此历史堆栈上新任务的开始。 任务(从启动它到下一个任务活动的活动)定义用户可以移动到的活动的primefaces组。 任务可以移动到前台和后台; 特定任务内的所有活动始终保持相同的顺序。 有关任务的更多信息,请参阅任务和返回堆栈。

这个标志通常被想要呈现“启动器”风格行为的活动所使用:它们向用户提供可以完成的单独事件的列表,否则这些事情完全独立于启动它们的活动。

当使用这个标志时,如果一个任务已经开始执行,那么新的活动将不会开始。 取而代之的是,当前的任务将被简单地带到屏幕的最前面的状态。请参阅FLAG_ACTIVITY_MULTIPLE_TASK标志来禁用此行为。

调用者请求正在启动的活动的结果时,不能使用此标志。

和:

FLAG_ACTIVITY_RESET_TASK_IF_NEEDED在API级别1中添加

如果设置了,这个活动要么在新任务中启动,要么在现有任务的顶部启动,那么它将作为任务的前门启动。 这将导致应用任何需要在适当的状态下执行该任务的亲和力(或者将活动移入或移出该活动),或者如果需要的话,简单地将该任务重置到其初始状态。

如果没有他们,推出的活动只会推到旧堆栈或其他不良行为(当然在这种情况下)

我相信没有收到最新的意图的问题可以像这样解决(从我的头上):

 @Override public void onActivityReenter (int resultCode, Intent data) { onNewIntent(data); } 

试试看!

每当你按主页button回到你的主屏幕,活动堆栈会杀死一些以前启动和运行的应用程序。

要validation这一事实,请尝试从应用程序中的A到B之后从通知面板启动应用程序,然后使用后退button……….您会发现您的应用程序与您的状态相同留下它。

当使用launch模式作为singleTop时,请确保在开始下一个活动(使用startActivity(Intent)方法,如B)时调用finish()(对当前活动说A)。 这样当前的活动被破坏。 A – > B – >暂停应用程序,然后单击启动器图标,启动A在A的创build方法,您需要检查,

 if(!TaskRoot()) { finish(); return; } 

这种方式启动应用程序时,我们正在检查根任务和以前的根任务是B,但不是A.所以这个检查破坏活动A,并带我们到当前堆栈顶部的活动B. 希望对你有帮助!。

这就是我终于解决了这个奇怪的行为。 在AndroidManifest中,这是我添加的:

 Application & Root activity android:launchMode="singleTop" android:alwaysRetainTaskState="true" android:taskAffinity="<name of package>" Child Activity android:parentActivityName=".<name of parent activity>" android:taskAffinity="<name of package>" 
  <activity android:name=".MainActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> 

//尝试在主要活动中使用launchMode =“singleTop”来维护应用程序的单个实例。 去体现和改变。

Interesting Posts