2

我有一个活动,在其 onCreate 方法中调用了一个 Init 函数(该函数调用了一些涉及大量内容的本机代码并调用了 openSLES 音频 api)。关键是这个 Init 函数在再次调用时使应用程序崩溃,这发生在屏幕旋转或当我使用后退按钮关闭活动并再次启动它时(但如果同时进程被终止,我没有麻烦)。我无法更改 Init 函数的行为。

我看到当活动被破坏时进程没有被杀死,我在阅读文档后预料到了这一点,这是一件好事,因为 - 如果有一些音频信号正在播放 - 在活动被破坏后继续播放,这是有利于我的目的。

我尝试使用 onSaveInstanceState 检查初始化状态,但这仅适用于屏幕旋转,即调用 onSaveInstanceState 时。当我按下后退按钮时,不会调用回调。

所以我尝试使用共享首选项,在 onPause 中执行状态保存。但此时我遇到了相反的问题:如果进程被终止,共享首选项值将被保留,但在这种情况下,我需要再次执行 Init 以使应用程序正常工作。

我想我需要一种方法来确定我的活动是否是在进程终止后创建的,但目前我不知道如何。我考虑过在 onPause 方法中使用 bundle 实例,但我不知道这如何以及是否可行。任何形式的提示将不胜感激。

4

3 回答 3

1
  1. 您可以将进程的 pid 存储在共享首选项中。如果您在 YourActivity.onCreate 中将您当前的 pid 与存储的 pid 进行比较,您可以确定何时必须初始化 OpenSLES。
  2. 您可以在应用程序派生类的 YourApplication.onCreate 中初始化 OpenSLES - 它只被调用一次。

编辑:

即声明以下类:

public class YourApplication extends Application {
  static private native synchronized void InitOpenSLES();

  public YourApplication() {}

  // see http://developer.android.com/reference/android/app/Application.html#onCreate() for details
  @Override
  public void onCreate() {
    super.onCreate();
    InitOpenSLES();
  }
}
于 2012-04-23T17:21:12.000 回答
0

对于每个进程,您都有 pid 或进程 ID。在您的 init 函数中,您可以轻松获取线程 ID,并将其保存为任何整数值。

Thread.currentThread().getId()));

每当您的活动将重新启动时,只需检查线程 ID 是否相同或不同。如果线程 id 不同,则调用您的函数 init 函数。否则你已经完成了。

于 2012-04-23T17:07:20.973 回答
0

这个问题有一个简单的解决方案。您无需将内容保存在 SharedPreferences 中即可完成此操作。只需使用静态(类)变量。像这样:

public class Globals {
    public static boolean initialized = false;
}

加载类时,该变量initialized将设置为 false。只有一次。在您的代码中,您可以像这样检查并设置变量:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Initialize (but only once per process)
    if (!Globals.initialized) {
        init(); // Call init function that does things one time per process
        Globals.initialized = true; // Remember we are initialized so we don't
                                    //  do it again
    }
    ...
}

即使您的所有活动都已完成,如果操作系统没有终止您的进程,initialized如果再次启动应用程序,该变量仍将为“真”。一旦操作系统终止进程,该变量将在下次启动应用程序并创建新进程时设置为“false”。

于 2012-06-13T14:56:13.300 回答