我的主要活动A
在清单中设置为android:launchMode="singleTask"
。现在,每当我从那里开始另一项活动,例如B
然后按手机上的HOME BUTTON
返回主屏幕,然后再次返回我的应用,方法是按应用按钮或按HOME BUTTON
长以显示我的最最近的应用程序不保留我的活动堆栈并直接返回A
而不是预期的活动B
。
这两个行为:
Expected: A > B > HOME > B
Actual: A > B > HOME > A (bad!)
是否有我缺少的设置或这是一个错误?如果是后者,在修复错误之前是否有解决方法?
仅供参考:这个问题已经讨论过here。但是,似乎没有任何真正的解决方案,但是。
答案 0 :(得分:41)
这不是错误。当启动现有的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的launchMode为“标准”时,情况有所不同。包含A的任务将到达前台并保持状态与之前相同。
您可以创建“标准”活动,例如。 C作为启动器和C的onCreate方法中的startActivity(A)
或强>
只要调用A
意图,只需删除launchMode="singleTask"
并设置FLAG_ACTIVITY_CLEAR_TOP|FLAG_ACTIVITY_SINGLE_TOP
标记即可
答案 1 :(得分:6)
singleTask
系统在新任务的根目录下创建活动并将意图路由到该任务。但是,如果活动的实例已经存在,系统会通过调用onNewIntent()方法将意图路由到现有实例,而不是创建新实例。
这意味着当action.MAIN和category.LAUNCHER标志从Launcher定位您的应用程序时,系统宁愿将意图路由到现有的ActivityA,而不是创建新任务并将新的ActivityA设置为根。它宁愿拆除活动现有任务上面的所有活动,并调用它onNewIntent()。
如果要同时捕获singleTop和singleTask的行为,请创建一个单独的"委托"使用singleTask launchMode命名SingleTaskActivity的活动,它只是在onCreate()中调用singleTop活动,然后自行完成。 singleTop活动仍然会有MAIN / LAUNCHER intent-filters继续充当应用程序的主要Launcher活动,但是当其他活动希望调用此singleTop活动时,它必须调用SingleTaskActivity以保留singleTask行为。传递给singleTask活动的意图也应该转移到singleTop Activity,所以类似下面的内容对我有用,因为我想同时拥有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"/>
祝你好运。
答案 2 :(得分:5)
的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无济于事。这似乎只是一个错误,至少根据documentation,其中陈述如下:
如上所述,“singleTask”或“singleInstance”活动永远不会超过一个实例,因此该实例应该处理所有新意图。 “singleInstance”活动始终位于堆栈的顶部(因为它是任务中唯一的活动),因此它始终处于处理意图的位置。但是,“singleTask”活动在堆栈中可能有也可能没有其他活动。如果是,则无法处理意图,并且意图被删除。 (即使意图被删除,它的到来也会导致任务到达前台,它将保留在前台。)
答案 3 :(得分:3)
我认为这是你想要的行为:
singleTask在主页上重置堆栈是因为我不明白的一些迟钝的原因。 相反,解决方案是不使用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中添加
如果设置,此活动将成为此任务的新任务的开始 历史堆栈。任务(从启动它到下一个的活动 任务活动)定义用户可以进行的活动的原子组 搬去。任务可以移动到前台和后台;所有的 特定任务内部的活动始终保持不变 订购。有关任务的详细信息,请参阅任务和后台堆栈。
此标志通常由想要呈现的活动使用 &#34;发射器&#34;样式行为:它们为用户提供单独的列表 可以完成的事情,否则完全独立运行 启动它们的活动。
使用此标志时,如果某个任务已在运行该活动 你现在开始,然后一个新的活动将不会开始; 相反,当前的任务将被简单地带到前面 屏幕显示它的最后状态。请参阅FLAG_ACTIVITY_MULTIPLE_TASK 用于禁用此行为的标志。
当呼叫者请求结果时,不能使用此标志 正在推出的活动。
和
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED在API级别1中添加
如果已设置,则此活动要么在新任务中启动,要么启动 将现有任务带到顶端,然后它将作为 前门的任务。这将导致任何应用 使这项任务处于适当状态所需的亲和力(要么是移动 来自或来自它的活动),或者只是将该任务重置为它 初始状态,如果需要。
如果没有它们,已启动的活动将被推到旧堆栈的顶部或其他一些不良行为(当然在这种情况下)
我相信没有收到最新意图的问题可以像这样(我的头脑)解决:
@Override
public void onActivityReenter (int resultCode, Intent data) {
onNewIntent(data);
}
尝试一下!
答案 4 :(得分:1)
如果A和B都属于同一Application
,请尝试删除
android:launchMode="singleTask"
来自Activities
的并进行测试,因为我认为默认行为是您所描述的预期行为。
答案 5 :(得分:0)
每当您按主页按钮返回主屏幕时,活动堆栈会杀死以前启动和运行的一些应用程序。
要验证此事实,请尝试在应用中从A到B之后从通知面板启动应用,然后使用后退按钮返回..........您将在同一个应用中找到您的应用当你离开它时说。
答案 6 :(得分:0)
当使用启动模式作为singleTop时,确保在启动下一个活动时调用finish()(在当前活动中说A)(使用startActivity(Intent)方法,如B)。这样,当前活动就会被破坏。 A - &gt; B - &gt;暂停应用程序并单击启动器图标,启动A 在A的oncreate方法中,您需要检查,
if(!TaskRoot()) {
finish();
return;
}
这种方式在启动app时我们正在检查root任务,之前的root任务是B而不是A.所以这个检查会破坏活动A并将我们带到活动B,这是当前堆栈的顶层。 希望它对你有用!。
答案 7 :(得分:0)
这就是我最终解决这种奇怪行为的方式。在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>"
答案 8 :(得分:0)
<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 =&#34; singleTop&#34;在您的主要活动中维护您的应用程序的单个实例。去清单和改变。
答案 9 :(得分:0)
在android manifest活动中添加以下内容,它将在视图顶部添加新任务,从而销毁先前的任务。 android:launchMode =“ singleTop”如下
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/AppTheme.NoActionBar">
</activity>
答案 10 :(得分:0)
我发现只有在启动器活动的启动模式设置为singleTask或singleInstance时,才会发生此问题。
因此,我创建了一个新的启动器活动,其启动模式为标准或singleTop。并将这个启动器活动称为我的旧主要活动,该活动的启动模式是单个任务。
LauncherActivity (standard/no history) -> MainActivity (singleTask).
将启动屏幕设置为启动器活动。在我调用主要活动后立即杀死了发射器活动。
public LauncherActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(intent);
finish();
}
}
<activity
android:name=".LauncherActivity"
android:noHistory="true"
android:theme="@style/Theme.LauncherScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Launcher screen theme should be set for the case that app is restarting after the process is killed. -->
<activity
android:name=".MainActivity"
android:launchMode="singleTask"
android:theme="@style/Theme.LauncherScreen"/>
优点:可以将MainActivity的启动模式保持为singleTask,以确保始终不超过一个MainActivity。