【问题标题】:Re-launch of Activity on Home button, but...only the first time重新启动“主页”按钮上的活动,但......只是第一次
【发布时间】:2013-04-23 09:08:31
【问题描述】:

我正在开发的应用程序在第一次安装时出现了奇怪的行为。如果用户第一次正常退出应用程序,它将永远按应有的方式运行。如果用户在安装应用程序后第一次使用主页按钮,它会将应用程序视为应该重新启动主屏幕并在旧版本之前启动新版本的活动。

所以手头确实有两个问题。我似乎无法解决这两个问题。

  1. 在用户点击主页按钮后首次安装应用程序时,防止应用程序关闭。
  2. 执行此操作时阻止应用程序的多个版本启动(launchMode 在这里有点帮助,但第一个组件仍会触发)。

我没有将清单文件中的launchMode 属性定义为任何内容。所以不应该有任何奇怪的行为作为结果。我现在已经对应用程序的launchmode 属性进行了试验,看看我是否可以让它按照预期的方式运行,但这里似乎不仅仅是正确启动活动。据我所知,当按下主页按钮时,应用程序没有理由在第一次关闭时自行关闭。

我也不在应用程序中使用onUserLeaveHint。我必须通过对该项目进行搜索再次确定。所以似乎根本没有尝试覆盖主页按钮。

即使在重新启动手机后,主页按钮也会再次正常运行。不确定是什么导致初始安装将主页按钮视为从头开始启动应用程序的标志。

一旦用户第一次退出应用程序,问题就会永久解决。对我应该看哪里有什么想法吗?

最近在应用程序中进行了一次搜索,以查看它是否可能仅在那时触发,因为 SQLite 数据库方法的 onUpgrade() 组件导致了一些奇怪的行为。

@Override
public void onUpgrade (SQLiteDatabase db, int oldVersion, int newVersion) {
                if (newVersion > oldVersion) {

           }
       }

或者在另一个位置,如果我将更新版本的 APK 传递到设备上的版本已经比当前版本低一个,则该位置可能会触发清单文件的更新。但是,这部分代码中的任何内容都没有让我相信它应该会影响与启动序列相关的任何内容。

下面提供了清单文件(名称已更改),用于说明当前在应用程序中使用的内容。

<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="10"/>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="com.android.vending.CHECK_LICENSE"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<uses-permission android:name="android.permission.VIBRATE" android:required="false"/>
<uses-permission android:name="android.permission.CAMERA" android:required="false"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>

<application android:icon="@drawable/icon"
             android:label="@string/app_name"
             android:allowBackup="false"
             android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
             >
    <activity android:name=".MyMain"
              android:label="@string/app_name_with_version"
              android:screenOrientation="portrait"
              android:windowSoftInputMode="adjustPan"   />
    <activity android:name=".StartupActivity"
              android:label="@string/app_name"
              android:screenOrientation="portrait"
              >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity   android:name=".SelectActivity"  
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"/>
    <activity   android:name=".ImageSelectionActivity"
                android:theme="@android:style/Theme.Dialog"
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"
                android:configChanges="orientation|keyboardHidden"/>            
    <activity   android:name=".DetailsActivity"
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"/>
    <activity   android:name=".EMailActivity"   
                android:label="@string/app_name_with_version"       
                android:screenOrientation="portrait"/>
    <activity   android:name=".SendTo" 
                android:label="@string/share_label" 
                android:theme="@android:style/Theme.Dialog" >
        <INTENT-FILTER>  
            <ACTION android:name="android.intent.action.MAIN">  
            <CATEGORY android:name="android.intent.category.LAUNCHER"/>  
            <INTENT-FILTER>  
                <ACTION android:name="android.intent.action.VIEW">  
                <CATEGORY android:name="android.intent.category.DEFAULT">  
                    <CATEGORY android:name="android.intent.category.BROWSABLE">  
                    <DATA android:scheme="callback" android:host="twitter"/>  
                    </CATEGORY>  
                </CATEGORY>
                </ACTION>
            </INTENT-FILTER>
            </ACTION>
        </INTENT-FILTER>
    </activity>
    <activity   android:name=".CreateMyActivity"
                android:label="@string/create_account_label"
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>
    <activity   android:name=".ViewInLayoutActivity"
                android:label="@string/app_name_with_version"   
                android:screenOrientation="portrait"/>
    <activity   android:name=".Preferences"
                android:label="@string/set_preferences" 
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>
    <activity   android:name=".AboutActivity"   
                android:label="@string/app_name_with_version"       
                android:screenOrientation="portrait"/>
    <activity   android:name=".InteractiveActivity" 
                android:label="@string/app_name_with_version"
                android:screenOrientation="portrait"
                android:theme="@android:style/Theme.Dialog"/>   
    <activity   android:name=".AlertFailedCommunications"
                android:screenOrientation="portrait"
                android:label="@string/alert_account_label"
                android:theme="@android:style/Theme.Dialog"/>
</application>    

【问题讨论】:

  • 它实际上只在第一次与 APK 一起分发时发生。如果从 IDE (Eclipse) 卸载并重新启动,它不会第一次发生。所以它一定与远程安装有关,这与直接安装不同。
  • 此外,它仅在从安装窗口立即启动时才会发生。如果安装后你说关闭,然后从主屏幕或应用程序窗口启动它,它在第一次启动时永远不会进入此状态。在第一个窗口的生命周期中一定有什么东西导致了这种情况。
  • 有很多关于使用单实例的警告,您可能只是遇到了其中一个。从我读到的单个实例将使该活动成为我认为您不希望执行的后台堆栈中的唯一任务。你没有发布你的代码,所以我真的不能给出任何其他答案。请发布您的清单文件和您所指的主要活动,我将能够给出更好的答案。
  • @JaySnayder 我面临同样的问题。我在其中一项活动中覆盖 onUserLeaveHint,一旦我使用主页将应用程序置于后台并使用启动器或快捷方式图标再次启动它,然后应用程序重新启动..重写 onUserLeaveHint 会导致这种情况吗?这仅在第一次从 PlayStore 安装时发生。

标签: android


【解决方案1】:

欢迎来到不断增长的被这个咬过的用户列表。

这是一个众所周知且长期存在的 Android 错误。应用程序首次从安装程序、网络浏览器和 IDE(IntelliJ、Eclipse 等)启动的方式。请参阅很久以前提交的与该问题相关的这些问题:

http://code.google.com/p/android/issues/detail?id=2373

http://code.google.com/p/android/issues/detail?id=26658

它仍然损坏,您无法阻止这种情况发生。您唯一能做的就是检测 Android 何时将您的根 Activity 的第二个实例启动到现有任务中。您可以将此代码放入您的根活动的onCreate() 中:

if (!isTaskRoot()) {
    // Android launched another instance of the root activity into an existing task
    //  so just quietly finish and go away, dropping the user back into the activity
    //  at the top of the stack (ie: the last state of this task)
    finish();
    return;
}

【讨论】:

  • 我一直担心会是这样。至少 QA 允许在程序中继续处理这个问题。我将使用您在未来版本中向我展示的解决方法,但是在我有时间对其进行测试之后。真的很感激。
  • 我的荣幸。如果您能访问 Google Code 上的参考问题并为它们加注星标/评论,我将不胜感激。我们对此发出的噪音越多,它就越有可能在未来的版本中得到修复。作为临时修复,您可以告诉您的用户在安装您的应用程序后不要单击“打开”按钮。另请注意,通过安装程序升级应用程序后也会发生这种情况。
  • 也为这些问题加注了星标。你是对的,我们在这些问题上发出的声音越多越好。许多人甚至可能不知道存在或什至正在他们的应用程序中发生这种奇怪的事情,直到将其提交给他们并进行演示。
  • 在 5.0 中仍然存在问题 :-(
【解决方案2】:

为什么会这样,不知道。但我知道自定义Launcher 有特定的launchModes 设置。

例如 ADW.Launcher:

android:clearTaskOnLaunch="true"
android:launchMode="singleTask" 

Android SDK 示例中的 Home 应用程序:android-sdk\samples\android-16\Home\AndroidManifest.xml

android:launchMode="singleInstance"

引用 CommonsWare:How to prevent custom home launcher app restart activity?

我将使用 SDK 中的 Home 示例应用程序,它使用 单实例。奇怪的是,AOSP 启动器使用 singleTask

【讨论】:

  • 欣赏输入。我之前尝试过主类的各种启动模式。这部分解决了手头的问题,但仍会导致应用程序在点击主页按钮时关闭。但它可以防止 Activity 创建自身的多个副本。
  • 此外,我发现当我按照指示实现 lanchMode 时,应用程序现在每次点击主页按钮时都会关闭,而不仅仅是第一次。这是最大的缺点。
【解决方案3】:

看起来问题是由应用程序的不同实例引起的。当用户单击应用程序图标时,可能第一个实例在安装程序的任务下启动,第二个实例在其自己的任务下启动。在用户看来,他/她恢复了应用程序,但实际上他此时再次启动了它。

如果你想让你的应用只在自己的任务中运行,一种可能的方法是添加

android:allowTaskReparenting="true"

到您的 AndroidManifest 的应用程序级别。安装后第一次点击应用图标后,您的应用将被移动到单独的任务中。

【讨论】:

  • 工作优雅完美。
【解决方案4】:

上面的答案对我使用 Nativescript 不起作用 - 这通过在活动标签中添加这两个属性解决了这个问题:

android:alwaysRetainTaskState="true"
android:launchMode="singleTask"

此链接提供了此解决方案:https://github.com/NativeScript/NativeScript/issues/3415

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多