关于Android app首次安装完成后在安装界面直接“打开”应用再按home键返回桌面,重新进入app重复实例化launcher activity的问题的解决

如标题所述,最近被重复实例化launcher activity这个问题搞得很惨,这个问题有哪些表现呢?如下:


1. 在package installers 安装界面安装完一个应用后,直接打开app,然后进入了 Activity_1, 此时再通过此activity用startActivity(intent)的方法打开 Activity_2.

2. 然后按home键返回桌面,在桌面点击app图标进入,你觉得应该进入的是 Activity_2 ,实际上却是launcher Activity_1 .

3. 然而还没完,这时候你按 back 返回键,会发现返回到了之前打开的 Activity_2,再按返回,又出现 launcherActivity_1. 也就是说系统重复实例化了Activity_1.

4. 退出app后再次点击桌面图标进入,反复试验,没有再出现这个问题。也就是说,这个问题(bug ?)只出现在操作步骤(1)后才会产生.

------------------------------------------------

以上问题我在一些知名厂商的app 上发现也存在这个BUG :

百度云

陌陌

去哪儿旅行

...QQ没有出现这个问题

另外,如果以root方式静默安装的话不会出现这个问题,在eclipse里直接发布到模拟器上运行也没有出现这个问题

---------------------------------------------

我在百度后发现大家都拿launchMode说事,不知道他们试验过没,完全不能解决。况且从那四个属性的描述来看,也与此无关。

照理说,launcher Activity_1 启动Activity_2后自身就进入栈底,而Activity_2就在栈顶了,实际上从 操作(3)来看也确实如此。

对操作(2)出现的情况,有文章说这个时候Activity_2此时也退栈了,而Activity_1弹出来了。这是个什么情况?虽然在返回桌面时Activity_2处于onStop()阶段,但并没有立刻被系统销毁,从操作(3)就可看出。在该APP的内存空间的中,此时的Activity_2是最后与用户交互的activity在没有被系统销毁前肯定是在Activity_1之上的。

在onResume()后肯定也应该显示的栈顶的Activity_2.

上面的问题,我觉得是android系统的bug,4.4.4也存在这个问题。

说了这么多废话,下面提供解决方案。


在super.onCreate(...)方法之后插入代码:


		
                if(!this.isTaskRoot()) { //判断该Activity是不是任务空间的源Activity,“非”也就是说是被系统重新实例化出来
			//如果你就放在launcher Activity中话,这里可以直接return了
                        Intent mainIntent=getIntent(); 
			String action=mainIntent.getAction();
			if(mainIntent.hasCategory(Intent.CATEGORY_LAUNCHER) && action.equals(Intent.ACTION_MAIN)) {
				finish();
				return;//finish()之后该活动会继续执行后面的代码,你可以logCat验证,加return避免可能的exception
			}
		}

来源google :

https://code.google.com/p/android/issues/detail?id=14262

https://code.google.com/p/android/issues/detail?id=2373#c40


还有另一种方案:

http://stackoverflow.com/questions/3042420/home-key-press-behaviour/4782423#4782423


转载 stackoverflow  部分描述:

While developing a sample android application i have constructed two activities 1)Activity 1 2)Activity 2

Now Activity 2 is the foreground activity whereas Activity 1 is the background one. Now user presses Home key. The application(i.e. both the activities) dissappear. Now is we relaunch the application we see Activity 1 as the foreground activity. My question is:

1)Does the platform maintain any history entry when pressed home key? 

2)How do we take the user to the last launch activity on relaunching the application?

----------------------------------------------------------------------------------------------------

I've struggled with this odd behavior for more than a month but I finally found out the explanation by trial and error.

This behavior happens when you start your application from Eclipse, from command line or if you install an application and press on the Open button(instead of the Done button) to start the application right after you installed it.

If in one of those cases, you start your apllication, go to Activity1 and then to Activity 2, press HOME button and then press the application icon, it will open a new instance of Activity1. Don't take my word for it. Just press BACK and see that it gets you to your Activity2 that you left when you pressed HOME.

It seems that the launcher activity is not put on the activity stack if the application is started in one of those ways mentioned above so that's why it creates a new instance of the launcher activity on top of the current activities in the application's stack. This looks to me like a bug.

So, the workaround would be to exit the application, the first time it was started from Eclipse or command line or Open button etc., by pressing the BACK button as many times as needed, and then enter the application again. From then on, the behavior will be as expected.

EDIT: A better workaround would be this: Create a DummyActivity and set it up as the main entry point into the application. Also, add the flag android:noHistory="true". The DummyActivity is simple and would look like this:

public class DummyActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (!MyApplication.startedApp) {
        Intent intent = new Intent(this, HomeActivity.class);
        startActivity(intent);
    }

    finish();
} }

MyApplication is a class that extends android.app.Application and is defined inside AndroidManifest.xml. In HomeActivity.class you set inside the onCreate() method the boolean field startedApp to true. If the user presses BACK from the screen, you need to move the value for startedApp to false.

public class HomeActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MyApplication.startedApp = true;
}

@Override
public void onBackPressed() {
    MacawApplication.startedApp = false;
    super.onBackPressed();
}

}

So, the first time the app is launched it enters the if block and launches the first real activity in our application. If you navigate through the app, then press HOME and then launch the app again, DummyActivity will get called a second time and it will just call finish() on itself and the app will show the last activity before you pressed HOME.








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值