Android T 关于屏幕旋转 (一)
1.Android 11 -- 强制清理app后台,关于权限引发的问题2.Android 11 (MTK)状态栏图标反色-->跟随当前应用变化代码流程3.Android 11 --关于Toast的异常4.Android 11 -- 关于dialog和悬浮窗导致SystemUI状态栏下拉频繁闪烁(窗口焦点问题)5.Android 11 下拉菜单长按WiFi图标SystemUI ANR6.Android 11 sim卡来电不弹出悬浮通知,默认来电默认全屏7.Android Bluetooth 蓝牙开发/蓝牙协议 小结8.Android11 —— 自定义添加一个System Services9.Android系统——AOSP相关-->随记10.Android11 , Launcher3 切换阿拉伯语,最近应用(后台)不能滑动11.Android 底层问题日志记录12.Android 11 -- app 服务保活13.Android11 - 添加自定义服务注意事项14.Android 11 导航栏添加一个虚拟按钮--问题合集15.Android 11--设置第三方Launcher并默认 与 如何预置apk16.Android11 系统修改 AOSP输入法的默认输入键盘布局17.Settings里面切换不同Launcher的代码流程18.关于Android`系统默认屏保`19.关于Android 11 Settings添加新的选项界面的细节20.Android 11 自由窗口模式 || 全屏模式启动app21.强制app横屏显示或者竖屏显示(动态)22.Android 11 禁止从SD卡上安装第三方应用23.实体物理音量键替换为home键24.AMS- kill Launcher进程的代码流程25.Android 11 recovery恢复出厂设置保留某些文件26.Android 11 禁用 adb root (userdebug版本)27.Android11 应用默认获取通知使用权限(可以获取系统所有通知信息)28.Android 11 UsbDebug 关于adb RSA 认证29.Android 11 NavigationBar && Status Bar 如果改变背景颜色30.Anroid 11 关于NotificationManager && NotificationManagerService -- 衍生到权限管理31.Android13 控制设置界面 双栏显示或单栏显示32.Android 13 大屏显示时关于SystemUI和Launcher3问题33.Android 系统适配无源码app34.Android 11 关于app的权限重置35.Android 11.0 关于app进程保活36.Android 11 关于按键拦截/按键事件处理分享37.Android R Settings关于屏保/PowerManagerService欺骗系统不让其进入休眠状态38.Android13 关于SystemUI更新/Nav Bar add volume button&&other button39.Android 13 移植EthernetSettings/Ethernet更新40.Anrdoir 13 关于设置静态IP后,突然断电,在上电开机卡动画41.Android T(13) The app is granted permissions by default
42.Android T 关于屏幕旋转 (一)
43.Android T about screen rotation(二)44.Android 13 about launcher3 (1)45.Android T don't abort background activity starts46.Android T adout replace bootanimation47.Launcher start App WINDOWING_MODE_FREEFORM48.Android 11 About SleepToken / (Settings)Screen timeout49.Settings.System数据监听/prop&SystemProperties数据监听(T to 13)
需求:Settings里面添加一个屏幕旋转的选项
//资源文件diff
--- a/packages/apps/Settings/res/values-zh-rCN/strings.xml
+++ b/packages/apps/Settings/res/values-zh-rCN/strings.xml
@@ -5988,4 +5988,6 @@
<string name="personalize_dashboard_summary">隐藏状态栏、导航栏等高级设置</string>
<string name="swipe_hide_navigation_button">在状态栏显示隐藏导航栏按钮</string>
<string name="host_switch">Host 模式</string>
+ <string name="screen_rotate_title">屏幕旋转</string>
+ <string name="screen_rotate_summary">控制屏幕方向</string>
</resources>
diff --git a/packages/apps/Settings/res/values/arrays.xml b/packages/apps/Settings/res/values/arrays.xml
index 9eebf2b737..7801fde2ea 100644
--- a/packages/apps/Settings/res/values/arrays.xml
+++ b/packages/apps/Settings/res/values/arrays.xml
@@ -1711,5 +1711,17 @@
<!-- hide 3G option from preferred network type UI -->
<integer-array name="network_mode_3g_deprecated_carrier_id" translatable="false">
</integer-array>
-
+ <!-- Screen rotate settings. These are shown in a list dialog. -->
+ <string-array name="screen_rotate_entries">
+ <item>0</item>
+ <item>90</item>
+ <item>180</item>
+ <item>270</item>
+ </string-array>
+ <string-array name="screen_rotate_values" translatable="false">
+ <item>0</item>
+ <item>90</item>
+ <item>180</item>
+ <item>270</item>
+ </string-array>
</resources>
diff --git a/packages/apps/Settings/res/values/strings.xml b/packages/apps/Settings/res/values/strings.xml
index 16b4bcdf5c..96864664ee 100644
--- a/packages/apps/Settings/res/values/strings.xml
+++ b/packages/apps/Settings/res/values/strings.xml
@@ -14618,4 +14618,8 @@
<string name="personalize_dashboard_summary">Hide advanced settings such as status bar and navigation bar</string>
<string name="swipe_hide_navigation_button">Show hidden navigation bar buttons in the status bar</string>
<string name="host_switch">Host mode</string>
+ <!--about screen rotate-->
+ <string name="screen_rotate_title">Screen rotate</string>
+ <string name="screen_rotate_summary">Control screen orientation</string>
+
</resources>
packages/apps/Settings/src/com/android/settings/xxx/TextScreenRotationPreferenceController.java
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.view.Surface;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
public class TextScreenRotationPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
private static final String TAG = "TextScreenRotationPreferenceController";
private final String mScreenRotationKey;
private Context mContext;
public TextScreenRotationPreferenceController(Context context, String key) {
super(context);
mContext = context;
mScreenRotationKey = key;
}
@Override
public void updateState(Preference preference) {
ListPreference pref = (ListPreference) preference;
int index = Settings.System.getInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, 0);
pref.setValueIndex(index);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
setScreenRotation(preference, (String) newValue);
return true;
}
private void setScreenRotation(Preference preference, String value) {
int rotation = Surface.ROTATION_0;
switch (value) {
case "0":
rotation = Surface.ROTATION_0;
break;
case "90":
rotation = Surface.ROTATION_90;
break;
case "180":
rotation = Surface.ROTATION_180;
break;
case "270":
rotation = Surface.ROTATION_270;
break;
}
setOritation(rotation);//to do
preference.setSummary(value);
}
/**
* The setting is available, and searchable to all search clients. AVAILABLE = 0;
*/
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return mScreenRotationKey;
}
//手动控制屏幕旋转的方式
private void setOritation(int i) {
try {
IWindowManager windowManagerService = WindowManagerGlobal.getWindowManagerService();
if (i == 0) {
windowManagerService.freezeRotation(0);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);//关闭自动旋转
} else if (i == 90) {
windowManagerService.freezeRotation(1);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == 180) {
windowManagerService.freezeRotation(2);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == 270) {
windowManagerService.freezeRotation(3);
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 0);
} else if (i == -1) {
Settings.System.putInt(this.mContext.getContentResolver(), "accelerometer_rotation", 1);//打开自动旋转
}
} catch (Exception e) {
...
}
}
//Settings.System.getInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, 0);
//adb shell settings get system user_rotation(修改后查询)
}
利用上面的函数,成功旋转了屏幕,可能遇到的第一个问题:按home键回到Launcher3,旋转的屏幕会被还原.请看这一篇文章.
第二个问题:关机重启后,旋转的屏幕被还原.
分析思路:
在设备开机的过程中不断用adb shell settings get system user_rotation
读取它的值,发现设备显示FallBackHomey引导界面时,
它的值被改为0.那么明显就是系统中有某个部分改了user_rotation的值,思考是谁改动了它?
(经验之谈)一般设备开机就是启动的部分有:Launcher3,SystemUI,frameworks各种服务,其它
排除法:
1.先删除Launcher3,没作用
2.删除SystemUI,有作用(user_rotation没有被还原)
correct diff
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@Override
public void onViewAttached() {
final Display display = mView.getDisplay();
mView.setComponents(mRecentsOptional);
...
// Currently there is no accelerometer sensor on non-default display.
if (mIsOnDefaultDisplay) {
final RotationButtonController rotationButtonController =
mView.getRotationButtonController();
// Reset user rotation pref to match that of the WindowManager if starting in locked mode.
// 如果是locked mode,就会重置user rotation
//This will automatically happen when switching from auto-rotate to locked mode.
if (display != null && rotationButtonController.isRotationLocked()) {
+ //add text
+ int user_rotation = Settings.System.getInt(mContext.getContentResolver(),Settings.System.USER_ROTATION, 0);
+ rotationButtonController.setRotationLockedAtAngle(user_rotation);//display.getRotation()
+ android.util.Log.d("tag","display.getRotation():--->"+display.getRotation());
+ //add text
}
} else {
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
}
...
}
rotationButtonController.setRotationLockedAtAngle(0);
,这里如果是0,就没事,如果是其它,比如1,2,3.
可能就会有偶发bug,概率蛮高的:导致设备定屏 无法操作.怀疑是SystemUI ANR,但是又没发现它的anr log.
kill systemui 的进程,等systemui重新启动,一切就正常了. 问题还没找到原因...
替代方案:
注释SystemUI里面的rotationButtonController.setRotationLockedAtAngle(display.getRotation());
,接受BOOT_COMPLETED的开机广播,然后调用setOritation(...)
Android 10.0系统自动转屏流程(源码分析)-未完待续
关于旋转屏幕流程
//1.0
./frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
public void setRotationLockedAtAngle(int rotationSuggestion) {
RotationPolicy.setRotationLockAtAngle(mContext, /* enabled= */ isRotationLocked(),
/* rotation= */ rotationSuggestion);
}
public boolean isRotationLocked() {
return RotationPolicy.isRotationLocked(mContext);
}
//1.1
frameworks/base/core/java/com/android/internal/view/RotationPolicy.java
/**
* Enables or disables rotation lock at a specific rotation from system UI.
*/
public static void setRotationLockAtAngle(Context context, final boolean enabled,
final int rotation) {
Settings.System.putIntForUser(context.getContentResolver(),
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
UserHandle.USER_CURRENT);//关闭自动旋转
setRotationLock(enabled, rotation);
}
private static void setRotationLock(final boolean enabled, final int rotation) {
AsyncTask.execute(new Runnable() {
@Override
public void run() {
try {
IWindowManager wm = WindowManagerGlobal.getWindowManagerService();//WMS
if (enabled) {
wm.freezeRotation(rotation);//旋转
} else {
wm.thawRotation();
}
} catch (RemoteException exc) {
Log.w(TAG, "Unable to save auto-rotate setting");
}
}
});
}
什么是Display.java
Provides information about the size and density of a logical display.
The display area is described in two different ways.
The application display area specifies the part of the display that may contain an application window, excluding the system decorations.
The application display area may be smaller than the real display area because the system subtracts the space needed for decor elements such as the status bar.
Use WindowMetrics.getBounds() to query the application window bounds.
The real display area specifies the part of the display that is accessible to an application in the current system state.
The real display area may be smaller than the physical size of the display in a few scenarios.
Use WindowManager.getCurrentWindowMetrics() to identify the current size of the activity window.
UI-related work, such as choosing UI layouts, should rely upon WindowMetrics.getBounds(). See getRealSize / getRealMetrics for details.
A logical display does not necessarily represent a particular physical display device such as the internal display or an external display.
The contents of a logical display may be presented on one or more physical displays according to the devices that are currently attached and whether mirroring has been enabled.
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库