Как узнать, когда в Froyo происходит изменение конфигурации?

В моем приложении я хочу, чтобы медиафайл воспроизводился и продолжал играть, если пользователь поворачивает экран (уничтожая действие), но я хочу, чтобы он прекратил играть, если пользователь переходит к другому действию или другому действию над этим, они нажимают кнопку "Назад", что угодно.

Я считаю, что для этого в Honeycomb есть API, но мне нужно что-то, что будет работать в Android 2.2.

Я бы предпочел не использовать onConfigurationChanged, чтобы самостоятельно обрабатывать все изменения конфигурации - это звучит как большая работа и потенциальные ошибки - и проблема с onRetainNonConfigurationInstance() заключается в том, что он не запускается до тех пор, пока onStop не срабатывает - -but onPause будет логичным местом для приостановки носителя, если это необходимо.

Есть ли способ в onPause определить, приостановлена ​​ли операция для изменения конфигурации по другой причине?

Ответ 1

У вашего решения есть хотя бы одна потенциальная проблема.

Согласно документации на Android:

Некоторые конфигурации устройств могут меняться во время выполнения (например, ориентация экрана, доступность клавиатуры и язык). Когда произойдет такое изменение, Android перезапустит текущую активность (вызывается onDestroy(), а затем onCreate()).

Тестирование на изменение вращения обрабатывает только один случай. Поскольку это, вероятно, будет самой распространенной причиной изменения конфигурации, это решение OK. Но что делать, если вы можете обрабатывать все случаи, существующие или добавленные в какой-либо будущей версии Android, без каких-либо накладных расходов на обработку конфигурации?

Обновлено для использования onRetainNonConfigurationInstance. В Android-документах есть об этом:

Вызывается системой как часть уничтожения активности из-за изменения конфигурации, когда известно, что новый экземпляр будет немедленно создан для новой конфигурации.

Также изменилась цепочка на super.onDestroy(), чтобы произойти после остановки носителя, но не совсем уверен в этом. Полагаю, это зависит от того, что означает средства остановки, и о том, что может вызвать разрушение при остановке носителя.

private Boolean mConfigurationChange = false;

public Object onRetainNonConfigurationInstance() {
    mConfigurationChange = true;
    return null;
}

public void onDestroy() {
    if (!mConfigurationChange) {
        // Code to stop media file goes here.
    }
    super.onDestroy();
}    

Ответ 2

До сота, onRetainNonConfigurationInstance(), как указано в принятом ответе, это лучший способ сделать это.

Начиная с Honeycomb, который устарел, но есть гораздо более простой способ: вызовите isChangingConfigurations() вместо этого во время любого из ваших onPause()/onStop()/onDestroy().

Наконец, при использовании библиотеки поддержки FragmentActivity ( android.support.v4.app.FragmentActivity) на pre-Honeycomb, onRetainNonConfigurationInstance() объявлен окончательным, но вы можете переопределить onRetainCustomNonConfigurationInstance() вместо того же эффекта.

Ответ 3

Наконец-то я понял ответ на свой вопрос!

public class MyActivity extends Activity {

  Display display; 
  int originalRotation;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
      originalRotation = display.getRotation();
  }

  public boolean endingDueToConfigurationChanging() {
   int newRotation = display.getRotation();
   return (newRotation != originalRotation);
  }
}

Display.getRotation() предназначен для возврата константы, указывающей, находится ли устройство на 0, 90, 180 или 270 градусов от его естественного вращения. Однако, когда устройство повернуто, это значение обновляется до завершения действия - оно фактически обновляется уже в onPause()! Поэтому, если вы сравниваете значение в onPause() (новое значение) с значением в onCreate() (исходное значение), то вы знаете, что действие отключается из-за поворота экрана или нет.

Ответ 4

Вы можете попробовать прослушивать намерение ACTION_CONFIGURATION_CHANGED и установить внутренний флаг, указывающий, что пауза - это изменение конфигурации.

Я не уверен, что вы получите намерение вовремя или что вам будет гарантировано, что он прибудет вовремя, поскольку он, вероятно, асинхронен. Возможно, стоит попробовать.

Ответ 5

Вы также можете попробовать использовать View#onConfigurationChanged в случае, если это применимо в вашем случае (т.е. у вас есть представление для вашего медиаплеера и ссылка на него в представлении).