当我使用Android市场上的"打开"按钮启动时,我在应用程序中遇到了一个错误.似乎从市场上推出它会使用不同的意图,然后从手机的应用程序菜单中启动它.这导致启动相同活动的多个副本,这些副本彼此冲突.
例如,如果我的应用程序包含ABC活动,则上述问题可能会导致堆栈ABCA.
我尝试使用Intent所有活动来解决这个问题,但每当我点击HOME时,它都会产生不必要的副作用,即将活动堆栈清除为root.
示例: ABC - > HOME - > A当我需要的是ABC - > HOME - > ABC
在使用HOME时,是否有一种防止启动相同类型的多个活动而不重置根活动的好方法?
仅出于测试目的,我允许通过URL下载和安装我的应用APK.下载到手机上后,可以使用Android应用安装程序启动它,用户可以选择将其安装到自己的设备上然后再运行.
考虑我们是否以上述方式下载并运行应用程序.我的应用中的主/启动器活动是登录页面(Activity A).一旦用户被认证,他们就被带到应用程序的主要区域,例如Activity B.所以现在这个任务的当前活动堆栈是A > B.
然后我按下手机上的主页按钮,然后进入Android主屏幕.我通过菜单中的图标重新启动我的应用程序,我被带到了Activity A,而不是Activity B.活动堆栈现在是A > B > A,或者现在有两个单独的任务与活动堆栈A > B,A分别.我想要的是Activity B在我重新启动应用程序时被收回.在这种状态下按回来将带我回去Activity B.
如果我首先通过安装程序打开应用程序,而不是通过主屏幕/菜单打开应用程序,则只会发生这种不良行为.
我研究了各机制如何开展活动.当我们使用app安装程序时,我们会看到以下日志:
INFO/ActivityManager(XXXX): Starting activity: Intent { dat=file:///mnt/sdcard/download/[my app].apk cmp=com.android.packageinstaller/.InstallAppProgress (has extras) }
INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=[my package]/[Activity A] }
Run Code Online (Sandbox Code Playgroud)
通过发射器/主屏幕:
INFO/ActivityManager(XXXX): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=[my package]/[Activity A] }
Run Code Online (Sandbox Code Playgroud)
当使用安装程序启动时,我们看到它正在使用标志0x10000000,但是当启动器启动时,我们看到它正在使用0x10200000.它也使用意图类别.
从 …
我的应用状态栏中有通知:
Notification notification = new Notification(R.drawable.icon, null, System.currentTimeMillis());
Intent notificationIntent = new Intent(this.parent, MainActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this.parent, 0, notificationIntent, 0);
...
notification.flags = Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(NOTIFICATION_ID, notification);
Run Code Online (Sandbox Code Playgroud)
这个问题是当你从应用程序按下主页按钮(将其推到后台),然后按下从状态栏访问的列表中的通知,它会启动活动的新副本.我想要做的就是恢复应用程序(比如当你长按主页按钮并按下应用程序的图标时).有没有办法创建一个Intent来做到这一点?
我向用户发送推送通知,点击它时会打开应用程序.
我的问题是,当应用程序已经打开时,单击通知会再次启动应用程序.
我只希望它启动应用程序,如果它还没有运行.
我在通知中使用Pending Intent:
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, Splash.class), 0);
Run Code Online (Sandbox Code Playgroud)
我看到帖子说使用:
<activity
android:name=".Splash"
android:launchMode="singleTask"
Run Code Online (Sandbox Code Playgroud)
但问题是我正在运行的应用程序正在运行其他活动,然后启动应用程序启动后7秒内完成,因此当应用程序运行时,Splash不是当前活动
notifications android push-notification android-pendingintent
我正在浏览单个实例的文档,并尝试了几个样本.在我的一个示例中,我有三个活动:A-> B-> C,其中B 在清单中有android:launchMode ="singleInstance".活动A和C具有默认启动模式.
场景:
通过A和B导航到C(即A-> B-> C)后,从活动C按下后退按钮进入活动A(C-> A),但从活动A按下后退按钮不退出应用程序,而是将活动B置于前面,然后按活动B的后退按钮退出应用程序.
题
当从活动A按下后退按钮时,为什么活动B会到达前景?
其他情况:
类似于,如果用户按下设备主页按钮,则从活动C开始,并通过长按主页回来应用程序,C保持在前台.但后退按钮流程需要C-> A - >退出应用程序.这次活动B没有出现.
现在我已经研究了这个,我正在改写它以使它更清楚.如果您正在寻找更多信息,可以使用旧编辑中的一些信息.
怎么了:
(这是指未设置任何launchMode设置的应用程序,因此使用默认设置)
您从市场或安装程序启动应用程序.这将使用FLAG_ACTIVITY_NEW_TASK标志启动应用程序的根/主活动,而不是类别.现在应用程序堆栈是[A]
然后,您将继续执行应用程序中的下一个活动.现在这个任务的堆栈是[A> B]
然后按主页键,然后按主屏幕或应用程序托盘中的图标重新启动相同的应用程序.
在这一点上预期的是活动B将显示,因为那是你离开的地方.但是显示A并且任务堆栈是[A> B> A]使用以下标志启动A的第二个实例:FLAG_ACTIVITY_NEW_TASK,FLAG_ACTIVITY_RESET_IF_NEEDED和FLAG_ACTIVITY_BROUGHT_TO_FRONT.它还有android.intent.category.LAUNCHER类别.
此时,如果您按下后退键,它将返回B,就像您离开时一样.
看一下文档,似乎只应为使用singleTask或singleTop launchModes的活动设置FLAG_ACTIVITY_BROUGHT_TO_FRONT.但是,此应用程序尚未设置任何launchModes,因此使用默认的标准launchMode.
我认为在这种情况下不会发生这种情况?
我还应该注意,一旦它进入这个奇怪的状态,那么每次从主屏幕或应用程序托盘启动应用程序时都会发生这种情况.如果任务完成(重新启动手机,强制停止应用程序,或一直回到堆栈)将解决此问题,并将不再错误地启动它.只有从安装程序或市场启动应用程序然后尝试从启动程序启动它时才会发生这种情况.
总而言之,为什么会发生这种情况?有没有办法防止它?
我希望广播接收器以这种方式启动我的应用程序:
如果应用程序不在前台或后台,请将其启动,就好像它是从启动器启动一样.
如果应用程序在后台,请将其带到最后一个状态的前台.
如果应用程序位于前台,则不执行任何操作.
这是我的代码:
@Override
public void onReceive(Context context, Intent intent) {
Intent launch_intent = new Intent("android.intent.action.MAIN");
launch_intent.setComponent(new ComponentName("com.example.helloworld","com.example.helloworld.MainActivity"));
launch_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launch_intent.addCategory(Intent.CATEGORY_LAUNCHER);
launch_intent.putExtra("some_data", "value");
context.startActivity(launch_intent);
}
Run Code Online (Sandbox Code Playgroud)
MainActivity是我的根活动.就像我说的,如果应用程序已经运行,我只是想把它带到前面而不改变它的状态.如果在MainActivity之上有一些活动,请保持原样.
大多数情况下上面的代码工作正常,但有时我注意到应用程序重新启动(或状态被重置 - 根回到顶部)当它从后台运行时.
我应该使用什么代码?任何帮助表示赞赏!
Android问题:此问题仅在安装后第一次出现并单击打开按钮,启动带有启动器图标的应用程序后,将永远不会出现问题.
重现问题的步骤.
发生了什么.
我已经解释了安装后的一般行为,并使用打开按钮启动应用程序.在我的应用程序中,它创建了2次启动应用程序的不一致状态.
你认为正确的行为应该是什么.
我有一些日志..
10-04 21:45:28.703:INFO/ActivityManager(243):从pid 15146开始活动:Intent {act = android.intent.action.MAIN flg = 0x10000000 cmp = com.test/.TestnewversionActivity}.
"看不到上面意图中添加的类别"
10-04 21:46:46.109:INFO/ActivityManager(243):开始活动:意图{act = android.intent.action.MAIN cat = [android.intent.category.LAUNCHER] flg = 0x10200000 cmp = com.test /来自pid 428的.TestnewversionActivity}
"参见上面意图中添加的类别".
如果有人告诉我如何解决这个或告诉我如何在"打开"按钮上添加类别android.intent.category.LAUNCHER点击然后问题将解决.
我试图在app start,oncreate和很多地方添加意图类别.intent.addCategory( "android.intent.category.LAUNCHER"); 还尝试使用IntentFilter,PackageManager.
这个问题出现在每部Android手机中.
我已经在HTC-SENSE Android版本2.3.3上使用了Logs
这就是问题所在。我的清单中有一个 <activity-alias> 定义如下:
<activity
android:name=".HomeActivity"/>
<activity-alias
android:name=".MainActivity"
android:targetActivity=".HomeActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>
Run Code Online (Sandbox Code Playgroud)
现在,用户开始MainActivity使用启动器图标,它转发到HomeActivity.
我也有一个HomeActivity从导航抽屉开始的意图。它以Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP标志开始- 重用现有的活动实例。
问题是这不能按预期工作,它实际上创建了一个新实例HomeActivity(即使它当前位于顶部且可见!)。发生这种情况是因为活动 backstack 包含 的条目.MainActivity,而不是HomeActivity它最终转发到的条目。
问题:我怀疑这可能是也可能不是 Android 中的错误,但我很难找到合适的解决方法。在这里寻求帮助!:)
我只需要启动单个活动,当用户在导航抽屉中选择一个项目时,该单个活动应该得到 onNewIntent(),而不是新活动的产生!
摆脱活动别名可以解决问题,但这对我来说不是一个可以接受的选择......
这adb dumpsys是从启动器启动活动后的结果,然后用户在 navdrawer 中选择“主页”直接启动活动,而不是通过别名(此转储确认有两个具有不同名称的条目):
Main stack:
TaskRecord{4181c408 #61 A ru.treto.tile U 0}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=ru.treto.tile/.HomeActivity }
Hist #2: ActivityRecord{412514b8 ru.treto.tile/.HomeActivity}
Intent { flg=0x24000000 cmp=ru.treto.tile/.HomeActivity }
ProcessRecord{412b06e0 10165:ru.treto.tile/u0a63}
Hist …Run Code Online (Sandbox Code Playgroud) 我观察过几个类似的问题,但他们无法帮助我.我需要在用户点击通知时显示上次活动.这是我的代码:
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(YourService.this)
.setContentTitle(getResources().getText(R.string.app_name))
.setContentText(getServiceStateDescription(YourService.this))
.setSmallIcon(iconId)
.setWhen(System.currentTimeMillis());
Intent nIntent = getPreviousIntent();
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
// Adds the back stack
stackBuilder.addParentStack(MainActivity_.class);
stackBuilder.addNextIntent(nIntent);
PendingIntent pendingIntent =
stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
notificationBuilder.setContentIntent(pendingIntent);
startForeground(ContextConstants.LAUNCHER_SERVICE_NOTE_ID, notificationBuilder.build());
private Intent getPreviousIntent() {
Intent newIntent = null;
final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
final List<ActivityManager.AppTask> recentTaskInfos = activityManager.getAppTasks();
if (!recentTaskInfos.isEmpty()) {
for (ActivityManager.AppTask appTaskTaskInfo: recentTaskInfos) {
if (appTaskTaskInfo.getTaskInfo().baseIntent.getComponent().getPackageName().equals(ContextConstants.PACKAGE_NAME)) {
newIntent = appTaskTaskInfo.getTaskInfo().baseIntent;
newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
}
} else {
final List<ActivityManager.RecentTaskInfo> …Run Code Online (Sandbox Code Playgroud)