【问题标题】:Android - Wrong activity sometimes startsAndroid - 有时会启动错误的活动
【发布时间】:2011-10-04 03:14:50
【问题描述】:

我有一个包含许多活动的 Android 应用。有时会启动错误的活动。

通常,Application 子类启动,然后启动 Activity (StartAct... android:name="android.intent.action.MAIN", android:name="android.intent.category.发射器") 做一些工作,然后启动 InitializeActivity。这会做一些工作,然后触发我的主要显示活动 (MainAct)。前两个活动进行了一些基本的初始化,包括在 MainAct 的意图启动之前设置静态“isInitialized”标志。

Activity 使用特定意图(...activity.class 指定)通过 startActivity() 启动,并在 startActivity() 之后调用 finish()。

但是,有时会发生这种情况,我不知道为什么......

简而言之,应用程序被终止,当按下图标启动它时,它直接跳转到第三个 (MainAct) 活动。这会导致应用检测到错误(isInitialized 标志为假)并停止:

  • 使用图标正常启动应用:
  • ...应用程序子类启动,同时启动一些工作线程
  • ...StartActivity 运行,然后触发 InitializeActivity 并完成
  • ...InitializeActivity 运行,然后设置 isInitialized 并启动 MainAct 并完成
  • ...MainAct 启动,运行正常
  • ...点击主页按钮并运行愤怒的小鸟
  • ...MainAct 记录 onPause,然后是 onStop
  • ...Application 子类拥有的工作线程继续定期执行工作并记录。
  • 25 分钟后,整个应用程序突然被杀死。此观察基于日志记录活动的结束,
  • 时光荏苒
  • 主页按钮点击
  • 为应用按下启动器图标
  • 应用子类onCreate被调用并返回
  • *MainAct.onCreate 被调用! (没有 StartAct,没有 InitializeActivity)*

我错过了什么?

注意:由于这个问题,添加了初始化标志。它设置在代码中唯一启动主Activity的地方,并且只在主Activity的onCreate中勾选。

[每个请求] 清单文件(略有编辑)。请注意,此处的服务当前未使用。

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="xxx.yyy.zzz"
  android:versionCode="1" android:versionName="1.0.1">
  <application
    android:icon="@drawable/icon_nondistr"
    android:label="@string/app_name"
    android:name=".app.MainApp"
    android:debuggable="true">
    <activity
      android:label="@string/app_name"
      android:name=".app.StartAct" android:theme="@android:style/Theme.NoTitleBar">
      <intent-filter>
        <action
          android:name="android.intent.action.MAIN" />
        <category
          android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity
      android:label="Html"
      android:name=".app.HtmlDisplayAct"/>
    <activity
      android:label="Init"
      android:configChanges="orientation"
      android:name=".app.InitializeActivity" android:theme="@android:style/Theme.NoTitleBar"/>
    <activity
      android:label="MyPrefs"
      android:name=".app.PrefsAct" />
    <activity
      android:label="@string/app_name"
      android:theme="@android:style/Theme.NoTitleBar"
      android:name=".app.MainAct">
    </activity>
    <service
      android:name=".app.svcs.DataGetterService" />
  </application>
  <uses-sdk android:minSdkVersion="4"/>
  <uses-permission
    android:name="android.permission.INTERNET" />
  <uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission
    android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission
    android:name="com.android.vending.CHECK_LICENSE" />
  <uses-feature
    android:name="android.hardware.location.network"
    android:required="false" />
</manifest>

【问题讨论】:

  • 你能显示你的清单文件吗...接缝那边的问题..
  • 这是一个非常古老的帖子,但我很高兴你发布了它,我很高兴我找到了它。否则我无法相信我真的在体验 Android 对我的应用所做的事情。不幸的是,唯一的答案是相当有问题的——我必须将 kludgy 代码添加到大约 20 个 Activity 类中才能捕获所有可能的情况。你有没有找到更好的解决方案?

标签: android android-activity restart


【解决方案1】:

应用程序因内存不足而被终止的事实应该对用户是透明的。这就是为什么当应用程序被杀死时,Android 会记住在该应用程序中运行的最后一个活动是什么,并在用户返回应用程序时直接创建此活动。

也许您可以在您的Application(或您的MainAct)的onCreate() 方法中做一些事情,以确保一切都正确初始化。

顺便说一句,除非你真的需要,否则当用户不使用你的应用程序时,你不应该让工作线程做一些工作。根据您的操作,这可能会很快耗尽电池,或者让用户认为它会很快耗尽电池(更糟糕的是,因为用户会卸载您的应用!)

您还可以让应用在用户退出应用时完成所有活动,

【讨论】:

  • 部分功能是在后台执行定期工作,所以我确实需要某个地方的工作线程(可能在服务中,但它们不是)。虽然我可以让 onCreate() 确保初始化,但这并不容易(在初始化期间,我有不同的活动,因此我可以显示有关初始化的内容)。我在文档中找不到 Android 有这种行为,或者我不会问。你确定吗?请注意,它对用户不透明 - 用户必须再次点击活动图标才能重新启动它。仅备份堆栈不会启动应用程序。谢了。
  • 如果你把你的工作线程放在一个服务中,你的应用程序可能不会被杀死,你也不会遇到问题。我不完全确定我所说的是否正确,但文档说 如果一个活动被暂停或停止,系统可以通过要求它完成或简单地杀死它来从内存中删除该活动过程。当它再次显示给用户时,它必须完全重新启动并恢复到之前的状态。 here,不知道是什么意思。
  • 另一个想法,不知道是否可行,将MainAct声明为主要活动(其图标显示在启动器中)并制作应用程序的onCreate()运行StartActivity(您可能需要在MainAct 中等待初始化完成)。
  • 我之前考虑过您的最后一个建议,我认为这可能是正确的解决方案。 Android 似乎认为第一个 Activity 和最近的 Activity 在某种程度上都是特殊的,因此将它们设为相同是有意义的。现在,我只检测条件并让 MainAct 启动 StartAct,然后以一种不优雅的方式解决问题的 finish()。我希望其他人能加入进来,但我将其标记为答案。谢谢!
  • 我也遇到了这个问题,但这是一个非常丑陋的解决方案。我不知道为什么Android会决定启动一个活动,因为它知道它之间存在静态引用,就像你的情况一样,项目在启动时填充。
【解决方案2】:

这确实是一个“雪上加霜”的案例——首先 Android 杀死了我很棒的应用程序,然后当用户重新启动我的应用程序时,Android 试图通过启动错误的活动来“提供帮助”,导致我的应用程序崩溃。叹息。

这是我非常笨拙的解决方法,可以抵消 Android 的帮助。我的应用程序要求 StartActivity 必须是第一个活动,因此对于所有其他活动,我在 onCreate() 方法中添加了一行。例如:

public class HelpActivity extends AppCompatActivity {

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

      if (StaticMethods.switchToStartActivityIfNecessary(this))  return;  // <- this is the magic line

      ...

   }

  ...

}

为了完成这项工作,我在我的应用程序类中添加了一个开关变量:

public class OutBackClientApplication extends Application {

   ...

   // Switch to indicate if StartActivity has been started.
   // Values: -1 = StartActity has never been started or this is first invocation.
   //         0 = normal situation, StartActivity has been run at least once.
   private int _startActivityStatus = -1;

   public int getStartActivityStatus() { return _startActivityStatus; }

   public void setStartActivityStatus(int startActivityStatus) {
      _startActivityStatus = startActivityStatus;
   }

   ...

}

我有一个名为 StaticMethods 的类,其中包括以下方法:

public class StaticMethods {

   /**
    * Method to test for the problematic situation where Android has previously killed this app, and
    * then when the user restarts the app Android tries to be helpful by restarting the activity
    * that was in the foreground when it killed the app, instead of starting the activity specified
    * in the manifest as the launch activity. See here:
    * http://stackoverflow.com/questions/6673271/android-wrong-activity-sometimes-starts
    *
    * The following line should be added to the onCreate() method of every Activity, except for
    * StartActivity, of course:
    *
    *    if (StaticMethods.switchToStartActivityIfNecessary(this))  return;
    */
   public static boolean switchToStartActivityIfNecessary(Activity currentActivity) {

      OutBackClientApplication outBackClientApplication =
                                        (OutBackClientApplication) currentActivity.getApplication();

      if (outBackClientApplication.getStartActivityStatus() == -1) {
         currentActivity.startActivity(new Intent(currentActivity, StartActivity.class));
         currentActivity.finish();
         return true;
      }
      return false;
   }

}

最后,StartActivity启动时需要重置开关:

 public class StartActivity extends AppCompatActivity {

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

      ((OutBackClientApplication) getApplication()).setStartActivityStatus(0);

      ...

   }

   ...

}

所有这些,只是为了抵消 Android 的“乐于助人”......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-01
    • 2012-07-23
    • 1970-01-01
    相关资源
    最近更新 更多