基本思路:在输入事件分发线程中(代码在WindowManagerService.java中),当事件为按键事件而且按键码与自定义功能键的码值一样时,向一个特定的Service(如com.android.settings.ButtonService)来请求服务。示例代码为

If (code == KeyEvent.KEYCODE_***)

mContext.startService(newIntent(“com.android.settings.ButtonService”)); //当该service对象不存在时,系统将会创建一个service实例对象来响应该请求,此时会执行service的onCreate( )方法,在执行onStartCommand( )方法,若已存在一个该service的实例对象时,只执行onStartCommand( )方法。

在Service的onStartCommand( )方法中,如果执行一个时间较长的任务,则会阻塞该service所在的线程,如果没有指定service的android:process属性,则service运行在UI线程中,会出现ANR的错误,一般解决方法为new一个Thread来解决阻塞问题。在本示例中只需要改变一个ContentProvider中所存储的一个key-value的值,该值相当于全局标志,当重力传感器的值发生变化需要进行屏幕旋转之前先检查ContentProvider中的标志值,如果未设置,则执行屏幕旋转动作,否则不执行,(不同应用程序之间共享数据由ContentProvider类来提供服务)。每次按下功能键时,先判定按键禁止屏幕的选项有没有开启,开启则反转ContentProvider中标志值,未开启就直接退出,判定选项有没有开启的方法也是设置一个标志值,当选项选中时,置位标志值,取消时,复位标志值,并将ContentProvider中的标志值也复位。

控制手机屏幕旋转的关键类为WindowOrientationListener, 该类为抽象类,系统中唯一实现继续该类的为PhoneWindowManager类,在WindowOrientationListener类的构造函数中,会获取一个SensorManager类的实例对象,通过SensorManager获取一个加速度传感器对象,最后new一个SensorEventListener。代码为:

mSensorManager=(SensorManager)context.getSystemService(Context.SENSOR_SERVICE);

mRate = rate;

mSensor =mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

if (mSensor != null) {

// Create listener only if sensors do exist

mSensorEventListener = newSensorEventListenerImpl();

}

在WindowOrientationListener类的enable方法中,向SensorManager中注册一个传感器事件监听器。

/**

* Enables theWindowOrientationListener so it will monitor the sensor and call

* {@link#onOrientationChanged} when the device orientation changes.

*/

public void enable() {

if (mSensor == null) {

Log.w(TAG,"Cannot detect sensors. Not enabled");

return;

}

if (mEnabled == false){

if (localLOGV)Log.d(TAG, "WindowOrientationListener enabled");

mSensorManager.registerListener(mSensorEventListener,mSensor, mRate);

mEnabled = true;

}

}

在WindowOrientationListener类中有一个实现了SensorEventListener接口的SensorEventListenerImpl的内部类,当传感器的数据发生变化时,会调用其onSensorChanged方法,该方法的实现主要是将加速度传感器上报的数据转换为设备旋转的方位角,然后在调用calculateNewRotation方法将方位角确定为屏幕的旋转方向,其实现主要是利用WindowOrientationListener类里的两个数组:THRESHOLDS和ROTATE_TO数组来实现确定屏幕的旋转方向。示例代码为:

private int[][][]THRESHOLDS = new int[][][] {

{{79, 180}, {180, 282}},

{{0, 45}, {45, 165}, {300,360}},

{{0, 53}, {195, 315}, {315,360}}

};

// See THRESHOLDS

private final int[][] ROTATE_TO = new int[][]{

{ROTATION_270, ROTATION_90},

{ROTATION_0, ROTATION_270,ROTATION_0},

{ROTATION_0, ROTATION_90,ROTATION_0}

};

这两个数组是一一对应的,THRESHOLDS数组为三维数组(可看作一个一维数组,数组中的元素类型为二维数组),THRESHOLDS数组第一行代表当手机屏幕处于ROTATION_0时,当手机旋转到79~180度,calculateNewRotation将根据相应的ROTATE_TO数组计算得出屏幕该旋转的方向为ROTATION_270, 旋转到180~282度时,同理得出屏幕该旋转的方向为ROTATION_90。THRESHOLDS数组第二行代表当手机屏幕处于ROTATION_90,如果屏幕旋转的角度在所定义的角度范围内,屏幕将会旋转,最终的旋转方向取决于ROTATE_TO数组的第二行,依次类推,第三行对应ROTATION_270,如果要支持ROTATION_180,则只需要在两个数组中添加相应的元素即可。

当calculateNewRotation计算出应该旋转的方位时,会将结果传递给onOrientationChanged( ),该方法为抽象方法,需要继承的子类来实现,系统中WindowOrientaionListener唯一继承该子类为PhoneWindowManager类的一个内部类MyOrientationListener类,在该类的onOrientationChanged方法的实现中,将会调用WindowManagerService类的一个实例对象的setRotation方法。

class MyOrientationListener extends WindowOrientationListener {

//构造函数

MyOrientationListener(Context context){

super(context);

}

@Override

public void onOrientationChanged(introtation) {

// Send updates based onorientation value

if (localLOGV) Log.v(TAG,"onOrientationChanged, rotation changed to " +rotation);

try {

mWindowManager.setRotation(rotation, false,

mFancyRotationAnimation);

} catch (RemoteException e) {

// Ignore

}

}

}

在WindowManagerService的setRotation方法中实现屏幕的旋转和view树的重绘。其主要实现是Surface.setOrientation方法的调用。

知道了屏幕旋转的核心代码,禁止屏幕旋转的方法就很简单了,只要在mWindowManager.setRotation(rotation, false, mFancyRotationAnimation)方法调用之用加入一个条件语句就OK了,设置一个全局标志位,在功能键禁止/使能屏幕旋转选项没选中时,全局标志位设为0,当选项选中时,当功能键按下时,反转全局标志位的值就可以决定是否旋转屏幕。当选项没选中时,必须复位全局标志位,否则在将自动旋转屏幕和功能键禁止/使能选项全部选中时,如果按下功能键,此时将功能键的选项取消时,屏幕将不会在自动旋转。

android 屏幕旋转相关推荐

  1. Android屏幕旋转时Activity不重新调用onCreate的方法

    2019独角兽企业重金招聘Python工程师标准>>> android屏幕旋转时Activity不重新调用onCreate的方法 当手机转屏时,Activity的onDestroy和 ...

  2. Android 屏幕旋转时Activity的变化

    Android开发文档上专门有一小节解释这个问题.简单来说,Activity是负责与用户交互的最主要机制,任何"设置"(Configuration)的改变都可能对Activity的 ...

  3. 通过广播获取Android屏幕旋转事件

         Android获取系统屏幕旋转的方式有几种,其中比较常见的是通过重写Activity中的onConfigurationChanged方法,但是这种方法有个缺陷,当测试程序在后台运行的时候不能 ...

  4. android 屏幕旋转不重新加载,Android webview旋转屏幕导致页面重新加载问题解决办法...

    Android webview旋转屏幕导致页面重新加载问题解决办法 1. 在create时候加个状态判断 protected void onCreate(Bundle savedInstanceSta ...

  5. android 屏幕旋转流程,android自动屏幕旋转流程分析.doc

    android自动屏幕旋转流程分析.doc android自动屏幕旋转流程分析 在android设置(Settings)中我们可以看到显示(display)下有一个自动屏幕旋转的checkbox, 如 ...

  6. android 屏幕方向监听,android 屏幕旋转问题 - jwzhangjie的个人空间 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...

    settings设置 在Android的Settings-> Display中有Orientation这一设置项.当选中时,屏幕会随设备旋转. settings设置是在文件SoundAndDis ...

  7. Android 屏幕旋转 全解析

    屏幕旋转一般的解决方案 关于屏幕旋转这里,之前一直没太注意,因为根据设备会有指定的屏幕旋转策略如: 开发手机应用时一直使用强制竖屏布局 开发平板设备一直使用横屏布局 开发系统应用,一般给两套即横竖各一 ...

  8. Android屏幕旋转,赶紧学习一下

    ActivityInfo.SCREEN_ORIENTATION_SENSOR //根据传感器设置方向 ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR //根据传 ...

  9. Android 屏幕旋转的处理

    1. 不做任何处理的情况下 如果没有针对性地做任何处理的话,默认情况下,当用户手机的重力感应器打开后,旋转屏幕方向,会导致app的当前activity发生onDestroy-> onCreate ...

最新文章

  1. JavaScript+TensorFlow.js让你在视频中瞬间消失
  2. shell编程入门步步高(八、函数)
  3. PHP 5.6.32 增加pdo_dblib.so拓展
  4. t66y.buzz index.php,6.FizzBuzz
  5. 64位有符号与无符号类型的整数
  6. void ,NULL与0的区别联系
  7. ManualResetEvent详解
  8. SpringCloud创建Eureka Client服务注册
  9. nodejs/pomelo 使用 mongodb 连接 mongo时 出现
  10. imx8开发之~源码编译
  11. FlashFXP v3.5.4注册码+FlashFXP v3.6.0注册码+FlashFXP v3.7.2.build.1266...
  12. 中国脑计划颠覆性创新之路九,进化的方向,脑科学,互联网和人工智能联合突破达尔文进化论局限
  13. 《程序开发心理学——程序开发组》
  14. 2021年N2观光车和观光列车司机考试内容及N2观光车和观光列车司机模拟考试题库
  15. 吃透Kafka六:topic 创建过程
  16. 虚拟机(vmware)linux中ctrl按键失灵 解决办法
  17. 全国省市拼音数据json
  18. 在线英语广播==好好学习,天天向上
  19. 九、cadence ic 5141 ——反相器版图绘制
  20. 【商品架构day5】淘宝:TOP1的商品系统长什么样子

热门文章

  1. php 没有读取权限能不能复制,“需要提供管理员权限才能复制此文件夹”怎么办...
  2. xy苹果助手未受信任_重要通知:苹果APP紧急修复!
  3. windows如何使用bat快速安装计划任务?
  4. 阿里云大咖秀——了不起的“空格”
  5. Could not calculate build plan: Plugin org.apache.maven.plugins:maven-war-plugin:3.2.2
  6. Excel计算BOM物料数量的公式
  7. 《他是谁》爆火,优酷的成功并非偶然
  8. 挥一挥衣袖,贝索斯宣布“退位”,去追寻“诗和远方”
  9. 店铺消费短信通知模板
  10. 曲面电视市场日渐成熟,TCL缘何“一骑绝尘”?