Android11系统强制APP横竖屏四个方向

Android11系统强制APP横竖屏四个方向

实现步骤

强制应用旋转功能可以让用户强制所有应用以横屏或竖屏的方式显示,无论应用本身是否支持旋转,包括 竖屏、横屏、反向竖屏和反向横屏。

修改代码

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

%1$s

"APP旋转"

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

默认

竖屏

横屏

反向竖屏

反向横屏

0

1

2

3

4

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

%1$s

"Force App Rotate"

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

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 revisedEntries = new ArrayList();

ArrayList revisedValues = new ArrayList();

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);

}

}

效果图

相关推荐

中国最大穆斯林网站被封 365网页版bet

中国最大穆斯林网站被封

📅 09-15 👁️ 6331
Acer ES1-311-C5PG(上市时间2015年) 365网页版bet

Acer ES1-311-C5PG(上市时间2015年)

📅 10-04 👁️ 3204