大家好,欢迎来到IT知识分享网。
实现步骤
强制应用旋转功能可以让用户强制所有应用以横屏或竖屏的方式显示,无论应用本身是否支持旋转,包括 竖屏、横屏、反向竖屏和反向横屏。
修改代码
frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java
updateOrientation()
if (newOrientation != mCurrentAppOrientation) { mCurrentAppOrientation = newOrientation; String rot = SystemProperties.get("persist.sys.app.rotation", "middle_port"); / * 在rotationForOrientation()和updateOrientation()方法中, * 需要根据persist.sys.app.rotation的值来修改当前应用的方向, * 如果是force_landscape,则强制为横屏; * 如果是force_portrait,则强制为竖屏; * 如果是force_reverse_landscape,则强制为反向横屏; * 如果是force_reverse_portrait,则强制为反向竖屏; */ Slog.d(TAG, "-----updateOrientation-----rot:" + rot); if (rot.equals("force_landscape")) { mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; } else if (rot.equals("force_portrait")) { mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT; } else if (rot.equals("force_reverse_landscape")) { mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; } else if (rot.equals("force_reverse_portrait")) { mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; } if (rot.equals("force_land") && "box".equals(SystemProperties.get("ro.target.product"))) mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE; if (isDefaultDisplay) { Slog.v(TAG, "asx force_land :" + mLandscapeRotation); return mLandscapeRotation; }
rotationForOrientation()
String rot = SystemProperties.get("persist.sys.app.rotation", "middle_port"); if (rot.equals("force_land") && "box".equals(SystemProperties.get("ro.target.product"))) { Slog.v(TAG, "asx force_land :" + mLandscapeRotation); return mLandscapeRotation; } Slog.d(TAG, "----rotationForOrientation-------rot :" + rot); Slog.d(TAG, "----rotationForOrientation-------orientation :" + orientation); if (rot.equals("force_landscape")) { return mLandscapeRotation; } else if (rot.equals("force_portrait")) { return mPortraitRotation; } else if (rot.equals("force_reverse_landscape")) { return mSeascapeRotation; } else if (rot.equals("force_reverse_portrait")) { return mUpsideDownRotation; } Slog.d(TAG, "----rotationForOrientation-------back"); switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: // Return portrait unless overridden. if (isAnyPortrait(preferredRotation)) { return preferredRotation;
packages/apps/Settings/res/values-zh-rCN/strings.xml
<!--APP旋转 --> <string name="forceapp_rotate_summary"> <xliff:g id="forceapprotate_description">%1$s</xliff:g> </string> <string name="ctrl_forceapp_rotate" >"APP旋转"</string>
packages/apps/Settings/res/values/arrays.xml
<!-- app 方向旋转--> <string-array name="forceapp_rotate_entries"> <item>默认</item> <item>竖屏</item> <item>横屏</item> <item>反向竖屏</item> <item>反向横屏</item> </string-array> <!--app 方向旋转 translate. --> <string-array name="forceapp_rotate_values" translatable="false"> <!-- 默认 --> <item>0</item> <!-- 竖屏 --> <item>1</item> <!-- 横屏--> <item>2</item> <!-- 反向竖屏 --> <item>3</item> <!-- 反向横屏--> <item>4</item> </string-array>
packages/apps/Settings/res/values/strings.xml
<!--App旋转 --> <string name="forceapp_rotate_summary"> <xliff:g id="forceapprotate_description">%1$s</xliff:g> </string> <string name="ctrl_forceapp_rotate" >"Force App Rotate"</string>
packages/apps/Settings/res/xml/display_settings.xml
<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"/>
packages/apps/Settings/src/com/android/settings/DisplaySettings.java
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.search.SearchIndexable; import com.android.settings.display.ForceAppRotatePreferenceController; import java.util.ArrayList; import java.util.List; controllers.add(new ThemePreferenceController(context)); controllers.add(new BrightnessLevelPreferenceController(context, lifecycle)); controllers.add(new HdmiSettingsPreferenceController(context, KET_HDMI_SETTINGS)); controllers.add(new ForceAppRotatePreferenceController(context,"forceapp_rotate")); return controllers; }
packages/apps/Settings/src/com/android/settings/display/ForceAppRotateListPreference.java
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; / * * 定义了强制应用旋转的列表偏好类,需要在其中实现以下功能: * 继承RestrictedListPreference类,并在构造方法中初始化初始的选项和值。 * 重写onPrepareDialogBuilder()方法,在对话框中添加管理员限制的视图,如果有的话。 * 重写onDialogCreated()方法,在对话框中添加管理员限制的点击事件,如果有的话。 * 定义一个removeUnusableRotates()方法,用于移除不可用的选项,并根据管理员限制来禁用或启用偏好。 */ 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
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; / * 定义了强制应用旋转的偏好控制器类,需要在其中实现以下功能: * 继承AbstractPreferenceController类,并实现Preference.OnPreferenceChangeListener接口,用于处理偏好变化的事件。 * 在构造方法中初始化键值和上下文。 * 在isAvailable()方法中返回true,表示该控制器可用。 * 在getPreferenceKey()方法中返回键值。 * 在updateState()方法中根据系统属性persist.sys.app.rotation的值来更新偏好的选项和摘要。 * 在onPreferenceChange()方法中根据用户选择的值来修改系统属性persist.sys.app.rotation,并更新偏好的摘要。 * 定义一个getRotateDescription()方法,用于根据当前的值和选项列表来获取对应的描述。 */ 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; String rot = SystemProperties.get("persist.sys.app.rotation", "middle_port"); Log.d(TAG, "--------updateState------------rot:" + rot); long currentRotate = 0; if (rot.equals("force_landscape")) { currentRotate = 2; } else if (rot.equals("force_portrait")) { currentRotate = 1; } else if (rot.equals("force_reverse_portrait")) { currentRotate = 3; } else if (rot.equals("force_reverse_landscape")) { currentRotate = 4; } else { currentRotate = 0; } Log.d(TAG, "--------updateState------------currentRotate:" + currentRotate); 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"); } else if (value == 3) { SystemProperties.set("persist.sys.app.rotation", "force_reverse_portrait"); } else if (value == 4) { SystemProperties.set("persist.sys.app.rotation", "force_reverse_landscape"); } Log.d(TAG, "--------onPreferenceChange------------value:" + String.valueOf(value)); // 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); } Log.d(TAG, "--------updateRotatePreferenceDescription------------summary:" + summary); preference.setSummary(summary); } }
效果图
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/132060.html