当前位置: 首页 > news >正文

Android屏幕旋转流程(1)

(1)Gsensor的注册和监听

App -->I2C过程:App通过SensorManager.getSystemServer调用到SystemSensorManager,SystemSensorManager通过jni调用到SensorManager.cpp,后通过binder调用到SensorService。SensorService通过SystemServer启动,后调用到hal kernel。

I2C -->App过程:通过JNI调用到SystemSensorManager中的SensorEventQueue.dispatchSensorEvent,然后通过App向SensorEventQueue注册的mListener,来回调数据到App的onSensorChanged()方法。

(网图)
在这里插入图片描述

//frameworks/base/core/java/android/hardware/SensorManager.javapublic boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs) {return registerListener(listener, sensor, samplingPeriodUs, null);}public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, int maxReportLatencyUs) {int delay = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0);}public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, Handler handler) {int delay = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delay, handler, 0, 0);}public boolean registerListener(SensorEventListener listener, Sensor sensor,int samplingPeriodUs, int maxReportLatencyUs, Handler handler) {int delayUs = getDelay(samplingPeriodUs);return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0);}/** @hide */
protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags);

registerListenerImpl的具体实现如下:

//frameworks/base/core/java/android/hardware/SystemSensorManager.javapublic class SystemSensorManager extends SensorManager {protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {//...synchronized (mSensorListeners) {SensorEventQueue queue = mSensorListeners.get(listener);if (queue == null) {Looper looper = (handler != null) ? handler.getLooper() : mMainLooper;final String fullClassName =listener.getClass().getEnclosingClass() != null? listener.getClass().getEnclosingClass().getName(): listener.getClass().getName();//这里创建SensorEventQueue,并调用addSensor进而调用addSensorEvent函数queue = new SensorEventQueue(listener, looper, this, fullClassName);if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) {queue.dispose();return false;}mSensorListeners.put(listener, queue);return true;} else {return queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs);}}}
}

接下来我们看一下SensorEventQueue队列

static final class SensorEventQueue extends BaseEventQueue {private final SensorEventListener mListener;private final SparseArray<SensorEvent> mSensorsEvents = new SparseArray<SensorEvent>();public SensorEventQueue(SensorEventListener listener, Looper looper,SystemSensorManager manager, String packageName) {super(looper, manager, OPERATING_MODE_NORMAL, packageName);//App传过来的监听器进行赋值mListener = listener;}@Overridepublic void addSensorEvent(Sensor sensor) {SensorEvent t = new SensorEvent(Sensor.getMaxLengthValuesArray(sensor,mManager.mTargetSdkLevel));synchronized (mSensorsEvents) {mSensorsEvents.put(sensor.getHandle(), t);}}@Overridepublic void removeSensorEvent(Sensor sensor) {synchronized (mSensorsEvents) {mSensorsEvents.delete(sensor.getHandle());}}// Called from native code.@SuppressWarnings("unused")@Override//在addSensorEvent put事件后,通过mSensorsEvents.get获取事件,然后通过mListener分发,这里的mListener就是App传过来的监听接口protected void dispatchSensorEvent(int handle, float[] values, int inAccuracy,long timestamp) {final Sensor sensor = mManager.mHandleToSensor.get(handle);if (sensor == null) {// sensor disconnectedreturn;}SensorEvent t = null;synchronized (mSensorsEvents) {t = mSensorsEvents.get(handle);}//...//这里会回调注册过的监听器的onSensorChangedmListener.onSensorChanged(t);}}

后续文章所提及的屏幕旋转方向等都和这里事件分发相关。

(2)应用注册屏幕旋转事件监听

应用注册使用,通过enable和disable来控制注册和取消注册

private class OrientationEventListenerImpl extends OrientationEventListener {public OrientationEventListenerImpl(Context context) {super(context);}@Overridepublic void onOrientationChanged(int orientation) {if (orientation == ORIENTATION_UNKNOWN) {return;}//...}}mOrientationListener.enable();
mOrientationListener.disable();

如下为系统代码

//frameworks/base/core/java/android/view/OrientationEventListener.javapublic abstract class OrientationEventListener {public OrientationEventListener(Context context) {this(context, SensorManager.SENSOR_DELAY_NORMAL);}public OrientationEventListener(Context context, int rate) {mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);mRate = rate;mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);if (mSensor != null) {// Create listener only if sensors do existmSensorEventListener = new SensorEventListenerImpl();}}public void enable() {if (mSensor == null) {Log.w(TAG, "Cannot detect sensors. Not enabled");return;}if (mEnabled == false) {if (localLOGV) Log.d(TAG, "OrientationEventListener enabled");mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);mEnabled = true;}}public void disable() {if (mSensor == null) {Log.w(TAG, "Cannot detect sensors. Invalid disable");return;}if (mEnabled == true) {if (localLOGV) Log.d(TAG, "OrientationEventListener disabled");mSensorManager.unregisterListener(mSensorEventListener);mEnabled = false;}}class SensorEventListenerImpl implements SensorEventListener {private static final int _DATA_X = 0;private static final int _DATA_Y = 1;private static final int _DATA_Z = 2;public void onSensorChanged(SensorEvent event) {float[] values = event.values;int orientation = ORIENTATION_UNKNOWN;float X = -values[_DATA_X];float Y = -values[_DATA_Y];float Z = -values[_DATA_Z];        float magnitude = X*X + Y*Y;// Don't trust the angle if the magnitude is small compared to the y valueif (magnitude * 4 >= Z*Z) {float OneEightyOverPi = 57.29577957855f;float angle = (float)Math.atan2(-Y, X) * OneEightyOverPi;orientation = 90 - (int)Math.round(angle);// normalize to 0 - 359 rangewhile (orientation >= 360) {orientation -= 360;} while (orientation < 0) {orientation += 360;}}if (mOldListener != null) {mOldListener.onSensorChanged(Sensor.TYPE_ACCELEROMETER, event.values);}if (orientation != mOrientation) {mOrientation = orientation;//回调函数onOrientationChanged(orientation);}}//回调函数public void onAccuracyChanged(Sensor sensor, int accuracy) {}}
}

相关文章:

Android屏幕旋转流程(1)

&#xff08;1&#xff09;Gsensor的注册和监听 App -->I2C过程&#xff1a;App通过SensorManager.getSystemServer调用到SystemSensorManager&#xff0c;SystemSensorManager通过jni调用到SensorManager.cpp&#xff0c;后通过binder调用到SensorService。SensorService通…...

JS常见的运算符有哪些?

在JavaScript中&#xff0c;常见的运算符可以分为以下几类&#xff1a; 算术运算符&#xff1a; &#xff1a;加法-&#xff1a;减法*&#xff1a;乘法/&#xff1a;除法%&#xff1a;取余&#xff08;模运算&#xff09;&#xff1a;递增--&#xff1a;递减**&#xff1a;幂运…...

【scikit-learn入门指南】:机器学习从零开始

1. 简介 scikit-learn是一款用于数据挖掘和数据分析的简单高效的工具&#xff0c;基于NumPy、SciPy和Matplotlib构建。它能够进行各种机器学习任务&#xff0c;如分类、回归和聚类。 2. 安装scikit-learn 在开始使用scikit-learn之前&#xff0c;需要确保已经安装了scikit-le…...

MEMS:Lecture 17 Noise MDS

讲义 Minimum Detectable Signal (MDS) Minimum Detectable Signal&#xff08;最小可检测信号&#xff09;是指当信号-噪声比&#xff08;Signal-to-Noise Ratio, SNR&#xff09;等于1时的输入信号水平。简单来说&#xff0c;MDS 是一个系统能够分辨出信号存在的最低输入信号…...

Windows运维:找到指定端口的服务

运维过windows的或多或少都遇到过需要找到一个端口对应的服务&#xff0c;或者是因为端口占用&#xff0c;或者是想看下对应的服务是哪个&#xff0c;那么如何操作呢&#xff1f;看看本文吧。 1、按照端口找到进程ID 例如想找8000端口的进程ID netstat -ano | findstr :8000 2…...

Linux文件系统讲解!

一、Linux文件系统历史 1、在早期的时候Linux各种不同发行版拥有自己各自自定义的文件系统层级结构。 2、当我用Red hat转向玩Debian时&#xff0c;我进入/etc我都是懵的。 3、后来Linux社区做了一个标准、FHS&#xff08;文件系统标准层次结构&#xff09;。来帮助Linux系统的…...

mysql集群,两主两从,使用mysql-proxy实现读写分离

主从复制 一、IP规划 服务器IP备注master1192.168.100.131master2的从master2192.168.100.132master1的从slave1192.168.100.134slave1的从slave2192.168.100.135slave2的从mysql-proxy192.168.100.137 二、具体配置 1.master1 ​ 配置ip&#xff1a;192.168.100.131 ​ …...

Linux文本处理三剑客+正则表达式

Linux文本处理常用的3个命令&#xff0c;脚本或者文本处理任务中会用到。这里做个整理。 三者的功能都是处理文本&#xff0c;但侧重点各不相同&#xff0c;grep更适合单纯的查找或匹配文本&#xff0c;sed更适合编辑匹配到的文本&#xff0c;awk更适合格式化文本&#xff0c;对…...

Linux启动KKfileview文件在线浏览时报错:启动office组件失败,请检查office组件是否可用

目录 1、导论 2、报错信息 3、问题分析 4、解决方法 4.1、下载 4.2、安装步骤 1、导论 今天进行项目部署时&#xff0c;遇到了一个问题。在启动kkfileview时&#xff0c;出现了报错异常&#xff1a; 2024-06-09 06:36:44.765 ERROR 1 --- [ main] cn.keking.service.Of…...

React <> </>的用法

React &#xff1c;&#xff1e; &#xff1c;/&#xff1e;的用法 介绍为什么使用 <>&#xff1f;例子解释 关于顶级元素总结 介绍 在 React 中&#xff0c;使用 <> 表示一个空标签或片段&#xff08;Fragment&#xff09;&#xff0c;这是一个简洁的方式来包裹一…...

is not null 、StringUtils.isNotEmpty和StringUtils.isNotBlank之间的区别?

这三者主要是针对对象是否为空、是否为空串和是否为空白字符串有不同的功能。 is not null 只是说明该对象不为空&#xff0c;没有考虑是否为空串和空白字符串。 StringUtils.isNotEmpty检查字符串是否不为 null且长度大于零&#xff0c;不考虑字符串中的空白字符。 StringU…...

Git使用-gitlab上面的项目如何整到本地的idea中

场景 一般我们在开发项目或者接手某个项目时&#xff0c;基本都要接触Git&#xff0c;比如上传项目代码&#xff0c;下载同事给你的交接代码等等。 这是一个基本功&#xff0c;小小整理一下日常操作中的使用。 第一步&#xff1a;在 GitLab 上找到你要克隆的项目&#xff0c;复…...

活体检验API在Java、Python、PHP中的使用教程

活体检验API是一种基于生物特征的身份验证技术&#xff0c;通过分析和识别用户的生物信息来确认其身份。这种技术广泛应用于各种领域&#xff0c;如金融、安全、社交媒体等&#xff0c;以提高身份验证的安全性和准确性。以下是描述”活体检验API”背景的一些关键点&#xff1a;…...

智能计算系统-概述

1、人工智能技术分层 2、人工智能方向人才培养 3、课程体系的建议 4、智能系统课程对学生的价值 5、智能计算系统对老师的价值 6、什么是智能计算系统 7、智能计算系统的形态 8、智能计算系统具有重大价值 9、智能计算系统的三大困难 10、开创深度学习处理器方向 11、寒武纪的国…...

SM5101 SOP-8 充电+触摸+发执丝控制多合一IC触摸打火机专用IC

SM5101 SOP-8 2.7V 涓流充电 具电池过充过放 触摸控制 发热丝电流控制多功能为一体专用芯片 昱灿-海川 SM5101 SOP-8 充电触摸发执丝控制多合一IC触摸打火机方案 &#xff01;&#xff01;&#xff01; 简介&#xff1a; SM5101是一款针对电子点烟器的专用芯片&#xff0c;具…...

Mysql-题目02

下面列出的&#xff08; DBMS &#xff09;是数据库管理系统的简称。 A、DB&#xff08;数据库&#xff09; B、DBA C、DBMS(数据库管理系统&#xff09; D、DBS&#xff08;数据库系统) 以下选项中&#xff0c;&#xff08; 概念模式 &#xff09;面向数据库设计人员&…...

Swift开发——循环执行方式

本文将介绍 Swift 语言的循环执行方式 01、循环执行方式 在Swift语言中,主要有两种循环执行控制方式: for-in结构和while结构。while结构又细分为当型while结构和直到型while结构,后者称为repeat-while结构。下面首先介绍for-in结构。 循环控制方式for-in结构可用于区间中的…...

Navicat和SQLynx产品功能比较一(整体比较)

Navicat和SQLynx都是数据库管理工具&#xff0c;在过去的二十年中&#xff0c;国内用户主要是使用Navicat偏多&#xff0c;一般是个人简单开发需要&#xff0c;数据量一般不大&#xff0c;开发相对简单。SQLynx是最近几年的数据库管理工具&#xff0c;Web开发&#xff0c;桌面版…...

pip 配置缓存路径

在windows操作平台&#xff0c;默认情况&#xff0c;pip下使用的系统目录 C:\Users\用名名称\AppData\Local\pip C盘是系统盘&#xff0c;如果常常使用pip安装会占用大量的空间很快就满&#xff0c;这时候就有必要变更一下缓存保存路径了。 pip 配置缓存路径&#xff1a; Win…...

大数据开发语言Scala(一) - Scala入门

引言 在当今的大数据时代&#xff0c;数据量和数据处理的复杂性不断增加&#xff0c;传统的编程语言已经难以满足需求。Scala作为一门新兴的编程语言&#xff0c;以其简洁、强大和高效的特性&#xff0c;迅速成为大数据开发的热门选择。本文将详细介绍Scala语言的基础知识&…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...