Как предотвратить изменение ориентации экрана после завершения действия на устройствах с версией Android 8.1?
Я работаю над приложением и столкнулся со странным поведением на устройствах 8.1 (Pixel2, Nexus5x), поэтому я написал небольшое приложение для проверки этого поведения.
MainActivity
заблокирован portrait
режим пока LandscapeActivity
заблокирован landscape
, MainActivity
начинает LandscapeActivity
для результата. Переключатели экрана от portrait
в landscape
как и ожидалось. когда LandscapeActivity
закончен, он распространяет результат в MainActivity
при переключении обратно на portrait
(как и ожидалось).
Но иногда я сталкиваюсь здесь с какой-то ошибкой. После onActivityResult
в MainActivity
он переключается с portrait
в landscape
переключиться обратно на portrait
немедленно. Хотя я могу справиться с состоянием, оно все равно выглядит противно.
Для отслеживания я опубликую все, чтобы перестроить его.
Что я могу сделать, чтобы предотвратить это? Также обратите внимание, что это происходит не каждый раз, и, насколько я могу проверить только на устройствах 8.1. Кажется, хорошо на устройствах Android ниже 8.1
РЕДАКТИРОВАТЬ: Добавлено android:configChanges="orientation|screenSize"
на мой манифест, как @Floern предложил в своем ответе без успеха. Подтверждение об ошибке платформы также будет приемлемым ответом.
манифест
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".LandscapeActivity"
android:screenOrientation="landscape"/>
</application>
Основная деятельность
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
private static final int REQ_CODE = 878;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: savedInstanceState=" + savedInstanceState + ", orientation=" + orientation());
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, LandscapeActivity.class);
startActivityForResult(intent, REQ_CODE);
}
});
}
@Override
protected void onResume() {
Log.d(TAG, "onResume: orientation=" + orientation());
super.onResume();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause: orientation=" + orientation());
super.onPause();
}
@Override
protected void onStart() {
Log.d(TAG, "onStart: orientation=" + orientation());
super.onStart();
}
@Override
protected void onStop() {
Log.d(TAG, "onStop: orientation=" + orientation());
super.onStop();
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: orientation=" + orientation());
super.onDestroy();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult: orientation=" + orientation());
if (requestCode == REQ_CODE){
Toast.makeText(this, "Result=" + data.getStringExtra(LandscapeActivity.KEY_DATA), Toast.LENGTH_LONG).show();
}
}
String orientation(){
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? "Landscape" : "Portrait";
}
}
LandscapeActivity
public class LandscapeActivity extends AppCompatActivity{
public static final String TAG = LandscapeActivity.class.getSimpleName();
public static final String KEY_DATA = "DATA";
static int COUNTER = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate: savedInstanceState=" + savedInstanceState + "orientation=" + (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? "Landscape" : "Portrait"));
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent data = new Intent();
COUNTER++;
data.putExtra(KEY_DATA, "Runned " + COUNTER + " times");
setResult(RESULT_OK, data);
finish();
}
});
}
@Override
protected void onResume() {
Log.d(TAG, "onResume: orientation=" + orientation());
super.onResume();
}
@Override
protected void onPause() {
Log.d(TAG, "onPause: orientation=" + orientation());
super.onPause();
}
@Override
protected void onStart() {
Log.d(TAG, "onStart: orientation=" + orientation());
super.onStart();
}
@Override
protected void onStop() {
Log.d(TAG, "onStop: orientation=" + orientation());
super.onStop();
}
@Override
protected void onDestroy() {
Log.d(TAG, "onDestroy: orientation=" + orientation());
super.onDestroy();
}
String orientation(){
return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? "Landscape" : "Portrait";
}
}
build.gradle
android {
compileSdkVersion 26
defaultConfig {
applicationId "android.example.com.orientationtest8_1"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
расположение activity_main
Файл:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="android.dermalog.com.orientationtest8_1.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
И последний журнал от нажатия на кнопки, повторяю:
01-04 15:18:06.744 D/MainActivity: onCreate: savedInstanceState=null
01-04 15:18:06.847 D/MainActivity: onStart: orientation=Portrait
01-04 15:18:06.850 D/MainActivity: onResume: orientation=Portrait
01-04 15:18:14.036 D/MainActivity: onPause: orientation=Portrait
01-04 15:18:14.108 D/LandscapeActivity: onCreate: savedInstanceState=nullorientation=Landscape
01-04 15:18:14.139 D/LandscapeActivity: onStart: orientation=Landscape
01-04 15:18:14.141 D/LandscapeActivity: onResume: orientation=Landscape
01-04 15:18:14.217 D/MainActivity: onStop: orientation=Portrait
01-04 15:18:15.643 D/LandscapeActivity: onPause: orientation=Landscape
01-04 15:18:15.711 D/MainActivity: onActivityResult: orientation=Portrait
01-04 15:18:15.719 D/MainActivity: onStart: orientation=Portrait
01-04 15:18:15.720 D/MainActivity: onResume: orientation=Portrait
01-04 15:18:15.786 D/LandscapeActivity: onStop: orientation=Landscape
01-04 15:18:15.786 D/LandscapeActivity: onDestroy: orientation=Landscape
01-04 15:18:18.036 D/MainActivity: onPause: orientation=Portrait
01-04 15:18:18.097 D/LandscapeActivity: onCreate: savedInstanceState=nullorientation=Landscape
01-04 15:18:18.121 D/LandscapeActivity: onStart: orientation=Landscape
01-04 15:18:18.123 D/LandscapeActivity: onResume: orientation=Landscape
01-04 15:18:18.213 D/MainActivity: onStop: orientation=Portrait
01-04 15:18:19.505 D/LandscapeActivity: onPause: orientation=Landscape
01-04 15:18:19.564 D/MainActivity: onActivityResult: orientation=Portrait
01-04 15:18:19.569 D/MainActivity: onStart: orientation=Portrait
01-04 15:18:19.569 D/MainActivity: onResume: orientation=Portrait
01-04 15:18:19.639 D/LandscapeActivity: onStop: orientation=Landscape
01-04 15:18:19.640 D/LandscapeActivity: onDestroy: orientation=Landscape
01-04 15:18:20.102 D/MainActivity: onPause: orientation=Portrait
01-04 15:18:20.103 D/MainActivity: onStop: orientation=Portrait
01-04 15:18:20.104 D/MainActivity: onDestroy: orientation=Portrait
01-04 15:18:20.123 D/MainActivity: onCreate: savedInstanceState=Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@7ceec3, 2131165191=android.support.v7.widget.Toolbar$SavedState@3c34340, 2131165193=android.view.AbsSavedState$1@7ceec3, 2131165199=android.view.AbsSavedState$1@7ceec3, 2131165219=android.view.AbsSavedState$1@7ceec3, 2131165229=android.view.AbsSavedState$1@7ceec3}}], android:lastAutofillId=1073741823, android:fragments=android.app.FragmentManagerState@c215279}]
01-04 15:18:20.149 D/MainActivity: onStart: orientation=Landscape
01-04 15:18:20.152 D/MainActivity: onResume: orientation=Landscape
01-04 15:18:20.699 D/MainActivity: onPause: orientation=Landscape
01-04 15:18:20.701 D/MainActivity: onStop: orientation=Landscape
01-04 15:18:20.702 D/MainActivity: onDestroy: orientation=Landscape
01-04 15:18:20.718 D/MainActivity: onCreate: savedInstanceState=Bundle[{android:viewHierarchyState=Bundle[{android:views={16908290=android.view.AbsSavedState$1@7ceec3, 2131165191=android.support.v7.widget.Toolbar$SavedState@807af46, 2131165193=android.view.AbsSavedState$1@7ceec3, 2131165199=android.view.AbsSavedState$1@7ceec3, 2131165219=android.view.AbsSavedState$1@7ceec3, 2131165229=android.view.AbsSavedState$1@7ceec3}}], android:lastAutofillId=1073741823, android:fragments=android.app.FragmentManagerState@8d12507}]
01-04 15:18:20.748 D/MainActivity: onStart: orientation=Portrait
01-04 15:18:20.751 D/MainActivity: onResume: orientation=Portrait
3 ответа
Эта ошибка была исправлена. Так что ждем следующего релиза / патча.
Да, это проблема в версии ОС Android 8.1. Как это было сделано устаревшим. мы можем обойти эти проблемы. На этом конкретном уровне API ОС Android может сохранять последнее значение ориентации и применяется ко всем экранам до тех пор, пока предыдущий экран или этот конкретный экран не будет уничтожен. Таким образом, решение этой проблемы заключается в изменении ориентации, прежде чем вернуться к экрану.
Например:
Если ScreenA находится в портретном режиме, а screenB находится в альбомном режиме, и если экран перемещен в ScreenB, который является альбомным, и если вы вернетесь к ScreenA без уничтожения ScreenB (восстановление ScreenA), экран A также будет виден в альбомном режиме.
Чтобы устранить эту проблему, принудительно измените ориентацию ScreenA на Portrait в onPause () или OnStop () ScreenB (чтобы восстановить ScreenA).
if (android.os.Build.VERSION.SDK_INT >= 27) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
после этого звонка ScreenA будет в портрете. Кроме того, в onResume () ScreenB,
if (android.os.Build.VERSION.SDK_INT >= 27) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
Это действительно может быть ошибка в структуре. Я заметил аналогичное поведение на устройствах Samsung при использовании приложения камеры (через Intent) в альбомной ориентации из приложения только для портрета. Я не мог понять, в чем именно причина, но я нашел обходной путь, который минимизирует эффект.
Если вы скажете системе, что хотите самостоятельно изменить ориентацию, добавив android:configChanges="orientation|screenSize"
в вашу активность, она не будет воссоздана при смене ориентации. Таким образом, вы можете избежать дополнительных затрат на воссоздание Activity (дважды), что может повысить производительность до того момента, когда вы вообще не заметите изменения ориентации.
<activity android:name=".MainActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize">