Вход в режим PIP с минимизированным приложением (Android Studio)

#android #android-studio

#Android #android-studio

Вопрос:

Мое приложение выполняет вызов сервера, который может занять несколько секунд. Пользователь может свернуть приложение до получения ответа от сервера.

Итак, что я пытаюсь сделать, так это то, что если приложение будет свернуто при получении ответа от сервера, оно перейдет в режим PIP.

Когда я пытаюсь войти в режим Pip с минимизированным приложением, я получаю эту ошибку:

 java.lang.IllegalStateException: Activity must be resumed to enter picture-in-picture
  

При выполнении этой строки возникает ошибка:

 enterPictureInPictureMode();
  

Спасибо.

Комментарии:

1. Смогли ли вы это реализовать?

2. Вы могли бы выполнить вызов сервера, просмотреть результат и последовательно ввести pip с помощью runBlocking . Таким образом, вы убедитесь, что все происходит, и активность находится в состоянии возобновления. Однако сделайте функцию приостанавливаемой

Ответ №1:

Необходимо проверить, предоставлено ли специальное разрешение Picture-in-Picture перед входом в режим.

     AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
      if (manager != null) {
        int modeAllowed = manager.unsafeCheckOpNoThrow(OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
            context.getPackageName());

        if (modeAllowed == AppOpsManager.MODE_ALLOWED) {
          // Enter picture-in-picture
        }
      }
  

Ответ №2:

Если вы используете rn-android-библиотеку pip:

 import android.app.AppOpsManager;
import android.content.Context;
import android.os.Process;

public void enterPictureInPictureMode() {
    if (isPipSupported) {
        AppOpsManager manager = (AppOpsManager) reactContext.getSystemService(Context.APP_OPS_SERVICE);
        if (manager != null) {
            int modeAllowed = manager.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, Process.myUid(),
                reactContext.getPackageName());

            if (modeAllowed == AppOpsManager.MODE_ALLOWED) {
                if (isCustomAspectRatioSupported) {
                    PictureInPictureParams params = new PictureInPictureParams.Builder()
                            .setAspectRatio(this.aspectRatio).build();
                    getCurrentActivity().enterPictureInPictureMode(params);
                } else {
                    getCurrentActivity().enterPictureInPictureMode();
                }
            }
        }
    }
}
  

Ответ №3:

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

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

Переключение в режим PiP вызывает изменения конфигурации, и это приводит к повторному запуску действия, говорит о переходе через остановлено -> уничтожено -> создано -> …

И мы можем узнать, как Activity решает, может ли она перейти в режим PiP или нет: https://cs.android.com/android/platform/superproject/ /master:frameworks/base/core/java/android/app/Activity.java

 final void performStop(boolean preserveWindow, String reason) {
    ...
    
    // Disallow entering picture-in-picture after the activity has been stopped
    mCanEnterPictureInPicture = false;
   ...
}

public boolean enterPictureInPictureMode(@NonNull PictureInPictureParams params) {
    ...
    if (!mCanEnterPictureInPicture) {
        throw new IllegalStateException("Activity must be resumed to enter"
                  " picture-in-picture");
    }
    ...
    mIsInPictureInPictureMode = ActivityClient.getInstance().enterPictureInPictureMode(
                mToken, params);
    return mIsInPictureInPictureMode;
}

  

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

 <activity android:name="VideoActivity"
    android:supportsPictureInPicture="true"
    android:configChanges=
        "screenSize|smallestScreenSize|screenLayout|orientation"
    ...