Android system adds dynamic control of screen orientation and forces APP to have horizontal and vertical screen orientations

Implementation steps

  • The screen rotation function allows users to choose the default orientation of the screen, including 0 degrees (portrait), 90 degrees (landscape), 180 degrees (reverse portrait) and 270 degrees (reverse landscape).
  • The Force App Rotation feature allows users to force all apps to display in landscape or portrait orientation, regardless of whether the app itself supports rotation.
  • All modifications can be saved after restarting. Force APP rotation priority > system direction priority.

Modify example

DisplayRotation module

frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java

This module is responsible for processing the logic of screen rotation. One system property needs to be added to it: persist.sys.app.rotation, which is used to control the settings of forced application rotation and screen rotation respectively.

In the rotationForOrientation() and updateOrientation() methods, the orientation of the current application needs to be modified according to the value of persist.sys.app.rotation. If it is force_landscape, it is forced to be horizontal; if it is force_portrait, it is forced to be vertical; otherwise Set according to the direction of the application itself.

+++ b/frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -380,6 +380,12 @@ public class DisplayRotation {
    
    
         if (newOrientation != mCurrentAppOrientation) {
    
    
             mCurrentAppOrientation = newOrientation;
             String rot = SystemProperties.get("persist.sys.app.rotation", "middle_port");
+            if (rot.equals("force_landscape")){
    
    
+                mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
+            }else if (rot.equals("force_portrait")){
    
    
+                mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
+                
+            }
             if (rot.equals("force_land") && "box".equals(SystemProperties.get("ro.target.product")))
                 mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
             if (isDefaultDisplay) {
    
    
@@ -1204,6 +1210,13 @@ public class DisplayRotation {
    
    
             Slog.v(TAG, "asx force_land :" + mLandscapeRotation);
             return mLandscapeRotation;
         }
+        
+        if (rot.equals("force_landscape")){
    
    
+            return mLandscapeRotation;
+        }else if (rot.equals("force_portrait")){
    
    
+            return mPortraitRotation;
+        }
+        
         switch (orientation) {
    
    
             case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
                 // Return portrait unless overridden.

Settings module

packages/apps/Settings/res/values/arrays.xml

This file defines a list of options for screen rotation and forced application rotation. Two arrays need to be added to it: screen_rotate_entries and screen_rotate_values, and forceapp_rotate_entries and forceapp_rotate_values.

screen_rotate_entries and screen_rotate_values ​​respectively represent the display name and corresponding value of screen rotation, including 0 degrees, 90 degrees, 180 degrees and 270 degrees.

  • forceapp_rotate_entries and forceapp_rotate_values ​​respectively represent the display name and corresponding value of forced application rotation, including default, horizontal screen and vertical screen.
+++ b/packages/apps/Settings/res/values-zh-rCN/arrays.xml
@@ -20,6 +20,45 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    
+ 
+    <string-array name="screen_totate_entries">
+        <item>0 Degree</item>
+        <item>90 Degree</item>
+        <item>180 Degree</item>
+        <item>270 Degree</item>
+    </string-array>
+
+    <!-- Do not translate. -->
+    <string-array name="screen_rotate_values" translatable="false">
+        <!-- Do not translate. -->
+        <item>0</item>
+        <!-- Do not translate. -->
+        <item>1</item>
+        <!-- Do not translate. -->
+        <item>2</item>
+        <!-- Do not translate. -->
+        <item>3</item>
+    </string-array>
+    
+         <string-array name="forceapp_rotate_entries">
+        <item>default</item>
+        <item>portrait</item>
+        <item>landscape</item>
+
+  
+    </string-array>
+
+    <!-- Do not translate. -->
+    <string-array name="forceapp_rotate_values" translatable="false">
+        <!-- Do not translate. -->
+        <item>0</item>
+        <!-- Do not translate. -->
+        <item>1</item>
+        <!-- Do not translate. -->
+        <item>2</item>
+
+    </string-array>

packages/apps/Settings/res/values/strings.xml

This file defines the English version of the string resource, in which the title and summary of screen rotation and forced application rotation need to be added, as well as the corresponding formatting string.

+++ b/packages/apps/Settings/res/values/strings.xml
@@ -14,6 +14,10 @@
      limitations under the License.
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="forceapp_rotate_summary"> <xliff:g id="forceapprotate_description">%1$s</xliff:g> </string>
+    <string name="screen_rotate_summary"> <xliff:g id="screenrotate_description">%1$s</xliff:g> </string>
+    <string name="ctrl_forceapp_rotate" >"Force App Rotate"</string>
+    <string name="ctrl_screen_rotate">"Screen Rotate"</string>
     <string name="ctrl_statusbar">StatusBar</string>
     <string name="ctrl_explan">ExPlan</string>
     <string name="ctrl_navigationbar">NavigationBar</string>

packages/apps/Settings/res/values-zh-rCN/strings.xml

This file defines the Chinese version of the string resource, in which the title and summary of screen rotation and forced application rotation need to be added, as well as the corresponding formatting string.

+++ b/packages/apps/Settings/res/values-zh-rCN/strings.xml
@@ -16,6 +16,10 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="forceapp_rotate_summary"> <xliff:g id="forceapprotate_description">%1$s</xliff:g> </string>
+    <string name="screen_rotate_summary"> <xliff:g id="screenrotate_description">%1$s</xliff:g> </string>
+    <string name="ctrl_forceapp_rotate" >"APP旋转"</string>
+    <string name="ctrl_screen_rotate">"屏幕旋转"</string>
     <string name="ctrl_statusbar">状态栏</string>
     <string name="ctrl_explan">下拉菜单</string>
     <string name="ctrl_navigationbar">导航栏</string>

packages/apps/Settings/res/xml/display_settings.xml

This file defines the interface layout for display settings, list preferences for adding screen rotation and forced application rotation, as well as corresponding key values, titles, summaries, and options.

We use the custom ScreenRotateListPreference and ForceAppRotateListPreference classes to implement the list preference function. These two classes inherit the RestrictedListPreference class and override some methods to handle administrator restrictions and dialog display.

+++ b/packages/apps/Settings/res/xml/display_settings.xml
@@ -31,7 +31,18 @@
    <SwitchPreference
        android:key="ctrl_explan"
        android:title="@string/ctrl_explan"/>
-       
+   <com.android.settings.display.ScreenRotateListPreference
+        android:key="screen_rotate"
+        android:title="@string/ctrl_screen_rotate"
+        android:summary="@string/summary_placeholder"
+        android:entries="@array/screen_rotate_entries"
+        android:entryValues="@array/screen_rotate_values"/>
+   <com.android.settings.display.ForceAppRotateListPreference 
+        android:key="forceapp_rotate"
+        android:title="@string/ctrl_forceapp_rotate"
+        android:summary="@string/summary_placeholder"
+        android:entries="@array/forceapp_rotate_entries"
+        android:entryValues="@array/forceapp_rotate_values"/>
     <com.android.settingslib.RestrictedPreference
         android:key="brightness"
         android:title="@string/brightness"

packages/apps/Settings/src/com/android/settings/DisplaySettings.java

This file defines the display settings controller, where we need to add the screen rotation and force application rotation preference controller, as well as the corresponding key value and context.

Use the custom ScreenRotatePreferenceController and ForceAppRotatePreferenceController classes to implement the functions of the preference controller. These two classes inherit the AbstractPreferenceController class and implement the Preference.OnPreferenceChangeListener interface for handling preference change events.

+++ b/packages/apps/Settings/src/com/android/settings/DisplaySettings.java
@@ -40,6 +40,8 @@ import com.android.settingslib.search.SearchIndexable;
 import com.android.settings.display.StatusBarPreferenceController;
 import com.android.settings.display.NavigationBarPreferenceController;
 import com.android.settings.display.ExPlanPreferenceController;
+import com.android.settings.display.ForceAppRotatePreferenceController;
+import com.android.settings.display.ScreenRotatePreferenceController;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -98,6 +100,8 @@ public class DisplaySettings extends DashboardFragment {
    
    
         controllers.add(new StatusBarPreferenceController(context));
         controllers.add(new NavigationBarPreferenceController(context));
         controllers.add(new ExPlanPreferenceController(context));
+        controllers.add(new ForceAppRotatePreferenceController(context,"forceapp_rotate"));
+        controllers.add(new ScreenRotatePreferenceController(context,"screen_rotate"));
         return controllers;
     }

packages/apps/Settings/src/com/android/settings/display/ScreenRotateListPreference.java

  • This file defines the list preference class for screen rotation, in which the following functions need to be implemented:
    • Inherit the RestrictedListPreference class and initialize the initial options and values ​​in the constructor.
    • Override the onPrepareDialogBuilder() method to add administrator-restricted views to the dialog box, if any.
    • Override the onDialogCreated() method and add administrator-restricted click events to the dialog box, if any.
    • Define a removeUnusableRotates() method to remove unavailable options and disable or enable preferences based on administrator restrictions.
package com.android.settings.display;

import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import com.android.settings.R;
import android.os.SystemProperties;
public class ScreenRotatePreferenceController extends AbstractPreferenceController implements
        PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
    
    

    private static final String TAG = "ScreenRotatePrefContr";

    /** If there is no setting in the provider, use this. */
    public static final int FALLBACK_SCREEN_ROTATE_VALUE = 0;

    private final String mScreenRotateKey;

    public ScreenRotatePreferenceController(Context context, String key) {
    
    
        super(context);
        mScreenRotateKey = key;
    }

    @Override
    public boolean isAvailable() {
    
    
        return true;
    }

    @Override
    public String getPreferenceKey() {
    
    
        return mScreenRotateKey;
    }

    @Override
    public void updateState(Preference preference) {
    
    
        final ScreenRotateListPreference screenRotateListPreference = (ScreenRotateListPreference) preference;
        long currentRotate = Settings.System.getLong(mContext.getContentResolver(),
                Settings.System.USER_ROTATION, FALLBACK_SCREEN_ROTATE_VALUE);
        screenRotateListPreference.setValue(String.valueOf(currentRotate));

        updateRotatePreferenceDescription(screenRotateListPreference, currentRotate);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
    
    
        try {
    
    
            int value = Integer.parseInt((String) newValue);
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, value);
            updateRotatePreferenceDescription((ScreenRotateListPreference) preference, value);
        } catch (NumberFormatException e) {
    
    
            Log.e(TAG, "could not persist screen rotate setting", e);
        }
        return true;
    }

    public static CharSequence getRotateDescription(
            long currentRotate, CharSequence[] entries, CharSequence[] values) {
    
    
        if (currentRotate < 0 || entries == null || values == null
                || values.length != entries.length) {
    
    
            return null;
        }

        for (int i = 0; i < values.length; i++) {
    
    
            long rotate = Long.parseLong(values[i].toString());
            if (currentRotate == rotate) {
    
    
                return entries[i];
            }
        }
        return null;
    }

    private void updateRotatePreferenceDescription(ScreenRotateListPreference preference,
            long currentRotate) {
    
    
        final CharSequence[] entries = preference.getEntries();
        final CharSequence[] values = preference.getEntryValues();
        final String summary;

        if (preference.isDisabledByAdmin()) {
    
    
            summary = mContext.getString(com.android.settings.R.string.disabled_by_policy_title);
        } else {
    
    
            final CharSequence rotateDescription = getRotateDescription(
                    currentRotate, entries, values);
            summary = rotateDescription == null
                    ? ""
                    : mContext.getString(R.string.screen_rotate_summary, rotateDescription);
        }
        preference.setSummary(summary);
    }
}

packages/apps/Settings/src/com/android/settings/display/ForceAppRotateListPreference.java

  • This file defines the list preference class that forces rotation to be applied, and the following functions need to be implemented in it:
    • Inherit the RestrictedListPreference class and initialize the initial options and values ​​in the constructor.
    • Override the onPrepareDialogBuilder() method to add administrator-restricted views to the dialog box, if any.
    • Override the onDialogCreated() method and add administrator-restricted click events to the dialog box, if any.
    • Define a removeUnusableRotates() method to remove unavailable options and disable or enable preferences based on administrator restrictions.
package com.android.settings.display;

import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;

import androidx.preference.Preference;

import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
import android.app.Dialog;
import java.util.ArrayList;
import android.view.View;
import androidx.appcompat.app.AlertDialog;

import android.util.AttributeSet;
import com.android.settings.R;
import com.android.settings.RestrictedListPreference;
import android.content.DialogInterface;

public class ForceAppRotateListPreference extends RestrictedListPreference {
    
    
    private EnforcedAdmin mAdmin;
    private final CharSequence[] mInitialEntries;
    private final CharSequence[] mInitialValues;

    public ForceAppRotateListPreference(Context context, AttributeSet attrs) {
    
    
        super(context, attrs);
        mInitialEntries = getEntries();
        mInitialValues = getEntryValues();
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder,
                                          DialogInterface.OnClickListener listener) {
    
    
        super.onPrepareDialogBuilder(builder, listener);
        if (mAdmin != null) {
    
    
            builder.setView(R.layout.admin_disabled_other_options_footer);
        } else {
    
    
            builder.setView(null);
        }
    }


    @Override
    protected void onDialogCreated(Dialog dialog) {
    
    
        super.onDialogCreated(dialog);
        dialog.create();
        if (mAdmin != null) {
    
    
            View footerView = dialog.findViewById(R.id.admin_disabled_other_options);
            footerView.findViewById(R.id.admin_more_details_link).setOnClickListener(
                    new View.OnClickListener() {
    
    
                        @Override
                        public void onClick(View view) {
    
    
                           // getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
                                    getContext(), mAdmin);
                        }
                    });
        }
    }

    public void removeUnusableRotates(long maxRotate, EnforcedAdmin admin) {
    
    
        final DevicePolicyManager dpm = (DevicePolicyManager) getContext().getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        if (dpm == null) {
    
    
            return;
        }

        if (admin == null && mAdmin == null && !isDisabledByAdmin()) {
    
    
            return;
        }
        if (admin == null) {
    
    
            maxRotate = Long.MAX_VALUE;
        }

        ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
        ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
        for (int i = 0; i < mInitialValues.length; ++i) {
    
    
            long rotate = Long.parseLong(mInitialValues[i].toString());
            if (rotate <= maxRotate) {
    
    
                revisedEntries.add(mInitialEntries[i]);
                revisedValues.add(mInitialValues[i]);
            }
        }

        // If there are no possible options for the user, then set this preference as disabled
        // by admin, otherwise remove the padlock in case it was set earlier.
        if (revisedValues.size() == 0) {
    
    
            setDisabledByAdmin(admin);
            return;
        } else {
    
    
            setDisabledByAdmin(null);
        }

        if (revisedEntries.size() != getEntries().length) {
    
    
            final int userPreference = Integer.parseInt(getValue());
            setEntries(revisedEntries.toArray(new CharSequence[0]));
            setEntryValues(revisedValues.toArray(new CharSequence[0]));
            mAdmin = admin;
            if (userPreference <= maxRotate) {
    
    
                setValue(String.valueOf(userPreference));
            } else if (revisedValues.size() > 0
                    && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString())
                            == maxRotate) {
    
    
                // If the last one happens to be the same as the max rotate, select that
                setValue(String.valueOf(maxRotate));
            } else {
    
    
                // There will be no highlighted selection since nothing in the list matches
                // maxRotate. The user can still select anything less than maxRotate.
                // TODO: maybe append maxRotate to the list and mark selected.
            }
        }
    }
}

packages/apps/Settings/src/com/android/settings/display/ForceAppRotatePreferenceController.java

  • This file defines the preference controller class that forces the application of rotation, and needs to implement the following functions in it:
    • Inherit the AbstractPreferenceController class and implement the Preference.OnPreferenceChangeListener interface to handle preference change events.
    • Initialize key values ​​and context in the constructor.
    • Return true in the isAvailable() method, indicating that the controller is available.
    • Return the key value in the getPreferenceKey() method.
    • In the updateState() method, the preferred options and summary are updated based on the value of the system property persist.sys.app.rotation.
    • In the onPreferenceChange() method, the system property persist.sys.app.rotation is modified based on the user-selected value and the summary of preferences is updated.
    • Define a getRotateDescription() method to obtain the corresponding description based on the current value and option list.
package com.android.settings.display;

import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import com.android.settings.R;
import android.os.SystemProperties;
public class ScreenRotatePreferenceController extends AbstractPreferenceController implements
        PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
    
    

    private static final String TAG = "ScreenRotatePrefContr";

    /** If there is no setting in the provider, use this. */
    public static final int FALLBACK_SCREEN_ROTATE_VALUE = 0;

    private final String mScreenRotateKey;

    public ScreenRotatePreferenceController(Context context, String key) {
    
    
        super(context);
        mScreenRotateKey = key;
    }

    @Override
    public boolean isAvailable() {
    
    
        return true;
    }

    @Override
    public String getPreferenceKey() {
    
    
        return mScreenRotateKey;
    }

    @Override
    public void updateState(Preference preference) {
    
    
        final ScreenRotateListPreference screenRotateListPreference = (ScreenRotateListPreference) preference;
        long currentRotate = Settings.System.getLong(mContext.getContentResolver(),
                Settings.System.USER_ROTATION, FALLBACK_SCREEN_ROTATE_VALUE);
        screenRotateListPreference.setValue(String.valueOf(currentRotate));

        updateRotatePreferenceDescription(screenRotateListPreference, currentRotate);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
    
    
        try {
    
    
            int value = Integer.parseInt((String) newValue);
            Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, value);
            updateRotatePreferenceDescription((ScreenRotateListPreference) preference, value);
        } catch (NumberFormatException e) {
            Log.e(TAG, "could not persist screen rotate setting", e);
        }
        return true;
    }

    public static CharSequence getRotateDescription(
            long currentRotate, CharSequence[] entries, CharSequence[] values) {
        if (currentRotate < 0 || entries == null || values == null
                || values.length != entries.length) {
            return null;
        }

        for (int i = 0; i < values.length; i++) {
            long rotate = Long.parseLong(values[i].toString());
            if (currentRotate == rotate) {
    
    
                return entries[i];
            }
        }
        return null;
    }

    private void updateRotatePreferenceDescription(ScreenRotateListPreference preference,
            long currentRotate) {
    
    
        final CharSequence[] entries = preference.getEntries();
        final CharSequence[] values = preference.getEntryValues();
        final String summary;

        if (preference.isDisabledByAdmin()) {
    
    
            summary = mContext.getString(com.android.settings.R.string.disabled_by_policy_title);
        } else {
    
    
            final CharSequence rotateDescription = getRotateDescription(
                    currentRotate, entries, values);
            summary = rotateDescription == null
                    ? ""
                    : mContext.getString(R.string.screen_rotate_summary, rotateDescription);
        }
        preference.setSummary(summary);
    }
}

packages/apps/Settings/src/com/android/settings/display/ScreenRotateListPreference.java

  • This file defines the list preference class for screen rotation, in which the following functions need to be implemented:
    • Inherit the RestrictedListPreference class and initialize the initial options and values ​​in the constructor.
    • Override the onPrepareDialogBuilder() method to add administrator-restricted views to the dialog box, if any.
    • Override the onDialogCreated() method and add administrator-restricted click events to the dialog box, if any.
    • Define a removeUnusableRotates() method to remove unavailable options and disable or enable preferences based on administrator restrictions.
package com.android.settings.display;

import android.content.Context;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import android.content.Intent;
import android.util.Log;
import com.android.settings.R;
import android.os.SystemProperties;
public class ForceAppRotatePreferenceController extends AbstractPreferenceController implements
        PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
    
    

    private static final String TAG = "ForceAppRotatePrefContr";

    /** If there is no setting in the provider, use this. */
    public static final int FALLBACK_FORCE_APP_ROTATE_VALUE = 0;

    private final String mForceAppRotateKey;

    public ForceAppRotatePreferenceController(Context context, String key) {
    
    
        super(context);
        mForceAppRotateKey = key;
    }

    @Override
    public boolean isAvailable() {
    
    
        return true;
    }

    @Override
    public String getPreferenceKey() {
    
    
        return mForceAppRotateKey;
    }

    @Override
    public void updateState(Preference preference) {
    
    
        final ForceAppRotateListPreference forceAppRotateListPreference = (ForceAppRotateListPreference) preference;
        long currentRotate = 0;
        String rot = SystemProperties.get("persist.sys.app.rotation", "middle_port");
        if (rot.equals("force_landscape")){
    
    
            currentRotate = 1;
        }else if (rot.equals("force_portrait")){
    
    
            currentRotate = 2;
        }else{
    
    
            currentRotate = 0;
        }
        
        forceAppRotateListPreference.setValue(String.valueOf(currentRotate));

        updateRotatePreferenceDescription(forceAppRotateListPreference, currentRotate);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
    
    
        try {
    
    
            int value = Integer.parseInt((String) newValue);
            if(value==0){    
                SystemProperties.set("persist.sys.app.rotation", "");
            }else if (value==1){
                SystemProperties.set("persist.sys.app.rotation", "force_portrait");
            }else if (value==2){
                SystemProperties.set("persist.sys.app.rotation", "force_landscape");
            }
            //Settings.System.putInt(mContext.getContentResolver(), "FORCE_APP_ROTATION", value);
            updateRotatePreferenceDescription((ForceAppRotateListPreference) preference, value);
        } catch (NumberFormatException e) {
            Log.e(TAG, "could not persist force app rotate setting", e);
        }
        return true;
    }

    public static CharSequence getRotateDescription(
            long currentRotate, CharSequence[] entries, CharSequence[] values) {
        if (currentRotate < 0 || entries == null || values == null
                || values.length != entries.length) {
            return null;
        }

        for (int i = 0; i < values.length; i++) {
            long rotate = Long.parseLong(values[i].toString());
            if (currentRotate == rotate) {
    
    
                return entries[i];
            }
        }
        return null;
    }

    private void updateRotatePreferenceDescription(ForceAppRotateListPreference preference,
            long currentRotate) {
    
    
        final CharSequence[] entries = preference.getEntries();
        final CharSequence[] values = preference.getEntryValues();
        final String summary;

        if (preference.isDisabledByAdmin()) {
    
    
            summary = mContext.getString(com.android.settings.R.string.disabled_by_policy_title);
        } else {
    
    
            final CharSequence rotateDescription = getRotateDescription(
                    currentRotate, entries, values);
            summary = rotateDescription == null
                    ? ""
                    : mContext.getString(R.string.forceapp_rotate_summary, rotateDescription);
        }
        preference.setSummary(summary);
    }
}

OK It’s not difficult to add everything here~

Other records:

  1. For example, why do you need to create this new thing in the ForceAppRotateListPreference file? Earlier versions were not so troublesome.
  2. There is a pitfall. The AlertDialog11+ version in xxxListPreference needs to androidx.appcompat.app.AlertDialog;be used. The earlier version cannot be used. If two packages are imported at the same time, compilation and errors will always be reported. Just keep one.

Test results:

Insert image description here
Insert image description here
Regardless of whether the application supports vertical screen, it will be forced to vertical screen.
Insert image description here

Summarize:

This article describes how to add screen rotation and force App application rotation functions in Android system Settings so that customers can adjust the screen orientation according to project needs.

Guess you like

Origin blog.csdn.net/SHH_1064994894/article/details/132568580