手 机 应 用 平 台 软 件 开 发 12 特 色 开 发 刘 宁 Email:liuning2@mail.sysu.edu.cn
Android 的 传 感 器 系 统 传 感 器 系 统 综 述 传 感 器 系 统 层 次 结 构 传 感 器 系 统 的 硬 件 抽 象 层 传 感 器 系 统 的 使 用
传 感 器 系 统 综 述 传 感 器 (Sensor) 系 统 可 以 让 智 能 手 机 的 功 能 更 加 丰 富 多 彩, 在 Android 系 统 中 支 持 多 种 传 感 器 Android 的 Sensor 系 统 涉 及 了 Android 的 各 个 层 次 Android 系 统 支 持 多 种 传 感 器, 有 的 传 感 器 已 经 在 Android 的 框 架 中 使 用, 大 多 数 传 感 器 由 应 用 程 序 来 使 用
传 感 器 系 统 综 述
传 感 器 系 统 综 述
Sensor 系 统 层 次 结 构 Android 的 传 感 器 系 统 从 驱 动 程 序 层 次 到 上 层 都 有 所 涉 及, 传 感 器 系 统 自 下 而 上 涉 及 到 的 各 个 层 次 为 : 各 种 Sensor 的 内 核 中 的 驱 动 程 序 Sensor 的 硬 件 抽 象 层 ( 硬 件 模 块 ) Sensor 系 统 的 JNI Sensor 的 JAVA 类 JAVA 框 架 中 对 Sensor 的 使 用 JAVA 应 用 程 序 对 Sensor 的 使 用
Sensor 系 统 层 次 结 构 Sensor 系 统 的 JNI 部 分 的 函 数 列 表
Sensor 系 统 层 次 结 构 Sensor 模 块 的 初 始 化 函 数 sensors_module_init()
Sensor 系 统 层 次 结 构 传 感 器 系 统 的 JAVA 部 分 包 含 了 以 下 几 个 文 件 SensorManager.java 实 现 传 感 器 系 统 核 心 的 管 理 类 SensorManager Sensor.java 单 一 传 感 器 的 描 述 性 文 件 Sensor SensorEvent.java 表 示 传 感 器 系 统 的 事 件 类 SensorEvent SensorEventListener.java 传 感 器 事 件 的 监 听 者 SensorEventListener 接 口 SensorListener.java 传 感 器 的 监 听 者 SensorListener 接 口 ( 不 推 荐 使 用 )
Sensor 系 统 层 次 结 构 SensorManager 的 主 要 的 接 口 如 下 所 示
传 感 器 系 统 综 述 Sensor 的 主 要 的 接 口 如 下 所 示 : Sensor 类 的 初 始 化 在 SensorManager 的 JNI 代 码 中 实 现, 在 SensorManager.java 维 护 了 一 个 Sensor 的 列 表
传 感 器 系 统 层 次 结 构 SensorEvent 类 比 较 简 单, 实 际 上 是 Sensor 类 加 上 了 数 值 (values), 精 度 (accuracy), 时 间 戳 (timestamp) 等 内 容 SensorEventListener 接 口 描 述 了 SensorEvent 的 监 听 者 内 容 如 下 所 示 :
Sensor 的 硬 件 抽 象 层 hardware/libhardware/include/hardware/ 目 录 中 的 sensors.h 是 Android 传 感 器 系 统 硬 件 层 的 接 口 Sensor 模 块 的 定 义 如 下 所 示
Sensor 的 硬 件 抽 象 层 sensors_data_t 表 示 传 感 器 的 数 据
Sensor 的 硬 件 抽 象 层 Sensor 的 控 制 设 备 和 数 据 设 备
Sensor 的 硬 件 抽 象 层 sensor_t 表 示 一 个 传 感 器 的 描 述 性 定 义 :
Sensor 的 硬 件 抽 象 层 Sensor 的 硬 件 抽 象 层 实 现 的 要 点 传 感 器 的 硬 件 抽 象 层 可 以 支 持 多 个 传 感 器, 需 要 构 建 一 个 sensor_t 类 型 的 数 组 传 感 器 控 制 设 备 和 数 据 设 备 结 构, 可 能 被 扩 展 传 感 器 在 Linux 内 核 的 驱 动 程 序, 很 可 能 使 用 misc 驱 动 的 程 序, 这 时 需 要 在 控 制 设 备 开 发 的 时 候, 同 样 使 用 open() 打 开 传 感 器 的 设 备 节 点 传 感 器 数 据 设 备 poll 是 实 现 的 重 点, 需 要 在 传 感 器 没 有 数 据 变 化 的 时 候 实 现 阻 塞, 在 数 据 变 化 的 时 候 返 回, 根 据 驱 动 程 序 的 情 况 可 以 使 用 poll(),read() 或 者 ioctl() 等 接 口 来 实 现 sensors_data_t 数 据 结 构 中 的 数 值, 是 最 终 传 感 器 传 出 的 数 据, 在 传 感 器 的 硬 件 抽 象 层 中, 需 要 构 建 这 个 数 据
传 感 器 系 统 的 使 用 传 感 器 系 统 使 用 的 几 个 方 面 JAVA 框 架 的 OrientationEventListener 类 JAVA 框 架 的 ApplicationContext 应 用 程 序 的 AndroidManifest.xml 设 置 方 向 调 用 传 感 器 系 统 接 口
传 感 器 系 统 的 使 用
传 感 器 系 统 的 使 用 Java 代 码 监 听 器 需 要 实 现 SensorEventListner 接 口
传 感 器 API Android 应 用 程 序 中 使 用 传 感 器 要 依 赖 于 android.hardware.sensoreventlistener 接 口 通 过 该 接 口 可 以 监 听 传 感 器 的 各 种 事 件 SensorEventListener 接 口 如 下 : package android.hardware; public interface SensorEventListener { // 传 感 器 采 样 值 发 生 变 化 时 调 用 public abstract void onsensorchanged(sensorevent event); // 传 感 器 精 度 发 生 改 变 时 调 用 public abstract void onaccuracychanged(sensor sensor, int accuracy); }
传 感 器 API 接 口 包 括 了 如 上 段 代 码 中 所 声 明 的 两 个 方 法, 其 中 onaccuracychanged 方 法 在 一 般 场 合 中 比 较 少 使 用 到, 常 用 的 是 onsensorchanged 方 法, 它 只 有 一 个 SensorEvent 类 型 的 参 数 event,sensorevent 类 代 表 了 一 次 传 感 器 的 响 应 事 件, 当 系 统 从 传 感 器 获 取 到 信 息 的 变 更 时, 会 捕 获 该 信 息 并 向 上 层 返 回 一 个 SensorEvent 类 型 的 对 象, 该 对 象 包 含 了 传 感 器 类 型 (public Sensor sensor) 传 感 事 件 的 时 间 戳 (public long timestamp) 传 感 器 数 值 的 精 度 (public int accuracy) 以 及 传 感 器 的 具 体 数 值 (public final float[] values) values 值 非 常 重 要, 其 数 据 类 型 是 float[], 代 表 了 从 各 种 传 感 器 采 集 回 的 数 值 信 息, 该 float 型 的 数 组 最 多 包 含 3 个 成 员, 而 根 据 传 感 器 的 不 同,values 中 个 成 员 所 代 表 的 含 义 也 不 同 例 如, 通 常 温 度 传 感 器 仅 仅 传 回 一 个 用 于 表 示 温 度 的 数 值, 而 加 速 度 传 感 器 则 需 要 传 回 一 个 包 含 X Y Z 三 个 轴 上 的 加 速 度 数 值, 同 样 的 一 个 数 据 10, 如 果 是 从 温 度 传 感 器 传 回 则 可 能 代 表 10 摄 氏 度, 而 如 果 从 亮 度 传 感 器 传 回 则 可 能 代 表 数 值 为 10 的 亮 度 单 位, 如 此 等 等
传 感 器 相 关 的 坐 标 系 为 了 正 确 理 解 传 感 器 所 传 回 的 数 值, 先 介 绍 Android 所 定 义 的 两 个 坐 标 系, 即 世 界 坐 标 系 (world coordinate-system) 和 旋 转 坐 标 系 (rotation coordinate-system) 该 坐 标 系 定 义 了 从 一 个 特 定 的 Android 设 备 上 来 看 待 外 部 世 界 的 方 式, 主 要 是 以 设 备 的 屏 幕 为 基 准 而 定 义, 并 且 该 坐 标 系 依 赖 的 是 屏 幕 的 默 认 方 向, 不 随 屏 幕 显 示 的 方 向 改 变 而 改 变 世 界 坐 标 系
世 界 坐 标 系 坐 标 系 以 屏 幕 的 中 心 为 圆 点, 其 中 : X 轴 方 向 是 沿 着 屏 幕 的 水 平 方 向 从 左 向 右 手 机 默 认 的 正 放 状 态, 一 般 来 说 即 是 如 图 所 示 的 默 认 为 长 边 在 左 右 两 侧 并 且 听 筒 在 上 方 的 情 况, 如 果 是 特 殊 的 设 备, 则 可 能 X 和 Y 轴 会 互 换 Y 轴 方 向 与 屏 幕 的 侧 边 平 行, 是 从 屏 幕 的 正 中 心 开 始 沿 着 平 行 屏 幕 侧 边 的 方 向 指 向 屏 幕 的 顶 端 Z 轴 将 手 机 屏 幕 朝 上 平 放 在 桌 面 上 时, 屏 幕 所 朝 的 方 向
旋 转 坐 标 系 如 图, 图 中 球 体 可 以 理 解 为 地 球, 该 坐 标 系 是 专 用 于 方 位 传 感 器 (Orientation Sensor) 的, 可 以 理 解 为 一 个 反 向 的 ( inverted) 世 界 坐 标 系, 方 位 传 感 器 即 用 于 描 述 设 备 所 朝 向 的 方 向 的 传 感 器, 而 Android 为 描 述 这 个 方 向 而 定 义 了 一 个 坐 标 系, 这 个 坐 标 系 也 由 X Y Z 轴 构 成, 特 别 之 处 是 方 向 传 感 器 所 传 回 的 数 值 是 屏 幕 从 标 准 位 置 ( 屏 幕 水 平 朝 上 且 正 北 ) 开 始 分 别 以 这 三 个 坐 标 轴 为 轴 所 旋 转 的 角 度 使 用 方 位 传 感 器 的 典 型 用 例 即 电 子 罗 盘
旋 转 坐 标 系 旋 转 坐 标 系 X 轴 即 Y 轴 与 Z 轴 的 向 量 积 Y Z, 方 位 是 与 地 球 球 面 相 切 并 且 指 向 地 理 的 西 方 Y 轴 为 设 备 当 前 所 在 位 置 与 地 面 相 切 并 且 指 向 地 磁 北 极 的 方 向 Z 轴 为 设 备 所 在 位 置 指 向 地 心 的 方 向, 垂 直 于 地 面
旋 转 坐 标 系 方 位 传 感 器 与 旋 转 坐 标 系 当 方 向 传 感 器 感 应 到 方 位 变 化 时 会 返 回 一 个 包 含 变 化 结 果 数 值 的 数 组, 即 values[], 数 组 的 长 度 为 3, 它 们 分 别 代 表 : values[0] 方 位 角, 即 手 机 绕 Z 轴 所 旋 转 的 角 度 values[1] 倾 斜 角, 专 指 绕 X 轴 所 旋 转 的 角 度 values[2] 翻 滚 角, 专 指 绕 Y 轴 所 旋 转 的 角 度 以 上 所 指 明 的 角 度 都 是 逆 时 针 方 向 的
获 取 设 备 上 传 感 器 种 类 为 了 获 取 当 前 手 机 上 已 连 接 的 传 感 器 清 单, 需 要 借 助 于 SensorManager 的 getsensorlist() 方 法, 首 先 需 要 获 取 一 个 SensorManager 类 的 实 例, 方 法 如 下 : private SensorManager msensormanager; msensormanager = (SensorManager)getSystemService(SENSOR_SERVICE); 在 获 取 了 当 前 系 统 的 SensorManager 类 的 对 象 后, 就 可 以 通 过 其 getsensorlist() 方 法 来 获 取 相 应 的 传 感 器 清 单 了, 方 法 如 下 : List<Sensor> sensors = msensormanager.getsensorlist(sensor.type_all); 获 取 了 传 感 器 清 单 后, 通 过 如 下 代 码 将 每 个 传 感 器 的 名 称 依 次 显 示 到 TextView 上 : sensorlist = (TextView)findViewById(R.id.sensorlist); for(sensor sensor:sensors) { // 输 出 传 感 器 的 名 称 sensorlist.append(sensor.getname() + "\n"); }
获 取 的 传 感 器 列 表 下 面 是 通 过 前 面 代 码 获 取 到 的 一 个 传 感 器 列 表 : 从 结 果 中 可 以 看 出, 该 款 真 机 支 持 了 如 下 型 号 的 共 六 种 类 型 的 传 感 器 : LIS331DLH 3-axis Accelerometer 加 速 度 传 感 器 ; AK8973 3-axis Magnetic field sensor 磁 场 传 感 器 ; AK8973 Temperature sensor 温 度 传 感 器 ; SFH7743 Proximity sensor 邻 近 度 传 感 器 ; Orientation sensor 方 位 传 感 器 ; LM3530 Light sensor 亮 度 传 感 器
利 用 传 感 器 实 现 指 南 针 功 能 功 能 实 现 分 析 在 指 南 针 应 用 中, 需 要 关 注 的 是 手 机 绕 旋 转 坐 标 系 Z 轴 所 旋 转 的 角 度, 也 就 是 传 感 器 所 传 回 的 values[0] 值, 该 values[0] 的 值 即 代 表 了 手 机 当 前 已 经 绕 Z 轴 所 旋 转 的 角 度, 这 个 角 度 以 正 北 方 向 为 基 准, 其 返 回 的 值 如 下 图 假 定 图 中 右 方 箭 头 所 指 方 向 为 正 北, 左 方 圆 形 中 的 箭 头 所 指 的 是 手 机 ( 传 感 器 ) 所 朝 的 方 向, 数 值 则 是 传 感 器 返 回 的 values[0] 值 0 315 正 北 270 90 180
利 用 传 感 器 实 现 指 南 针 功 能 为 Activity 实 现 SensorEventListener 接 口, 在 类 中 实 现 如 下 两 个 方 法 : public void onaccuracychanged(sensor sensor, int accuracy) {} public void onsensorchanged(sensorevent event) {} 为 当 前 的 Activity 注 册 需 要 使 用 的 传 感 器, 通 过 如 下 的 方 式 获 取 到 系 统 默 认 的 方 位 传 感 器 的 实 例 : msensormanager = (SensorManager)getSystemService(SENSOR_SERVICE); morientation = msensormanager.getdefaultsensor(sensor.type_orientation);
利 用 传 感 器 实 现 指 南 针 功 能 完 成 传 感 器 事 件 监 听 器 和 传 感 器 的 注 册 工 作, 只 有 注 册 了 之 后, 传 感 器 管 理 器 (SensorManager) 才 会 将 相 应 的 传 感 信 号 传 给 该 监 听 器, 通 常 将 这 个 注 册 的 操 作 放 在 Activity 的 onresume() 方 法 下, 同 时 将 取 消 注 册 即 注 销 的 操 作 放 在 Activity 的 onpause() 方 法 下, 这 样 就 可 以 使 传 感 器 的 资 源 得 到 合 理 的 使 用 和 释 放, 方 法 如 下 : protected void onresume() { super.onresume(); msensormanager.registerlistener(this, morientation, SensorManager.SENSOR_DELAY_UI); } protected void onpause() { super.onpause(); msensormanager.unregisterlistener(this); }
利 用 传 感 器 实 现 指 南 针 功 能 指 南 针 使 用 ImageView 来 实 现, 而 指 南 针 旋 转 则 使 用 了 RotateAnimation 类, 该 类 专 用 于 定 义 旋 转 图 像 操 作, 它 的 一 个 构 造 方 法 如 下 : RotateAnimation(float fromdegrees, float todegrees, int pivotxtype, float pivotxvalue, int pivotytype, float pivotyvalue) 构 造 方 法 包 含 了 六 个 参 数, 它 们 的 含 义 分 别 如 下 : fromdegrees: 即 该 段 旋 转 动 画 的 起 始 度 数 ; todegrees: 旋 转 的 终 点 度 数 ; pivotxtype: 这 个 参 数 用 于 指 定 其 后 的 pivotxvalue 的 类 型, 即 说 明 按 何 种 规 则 来 解 析 pivotxvalue 数 值, 目 前 包 括 三 种 类 型 即 Animation.ABSOLUTE( 绝 对 数 值, 即 pivotxvalue 为 坐 标 值 ) Animation.RELATIVE_TO_SELF( 相 对 于 自 身 的 位 置, 如 本 示 例 中 的 ImageView, 当 pivotxvalue 为 0.5 时 表 示 旋 转 的 轴 心 X 坐 标 在 图 形 的 X 边 的 中 点 ) Animation.RELATIVE_TO_PARENT( 相 对 于 父 视 图 的 位 置 ); pivotxvalue: 即 动 画 旋 转 的 轴 心 的 值, 对 它 的 解 析 依 赖 于 前 面 的 pivotxtype 指 定 的 类 型 ; pivotytype: 类 似 于 pivotxtype, 只 是 这 个 参 数 代 表 的 为 Y 轴 ; pivotyvalue: 类 似 于 pivotxvalue, 只 是 这 个 参 数 代 表 的 为 Y 轴
利 用 传 感 器 实 现 指 南 针 功 能 构 造 本 例 中 的 RotateAnimation 对 象 : 1. RotateAnimation ra; 2. ra = new RotateAnimation(currentDegree, targetdegree, 3. Animation.RELATIVE_TO_SELF, 0.5f, 4. Animation.RELATIVE_TO_SELF, 0.5f); 5. ra.setduration(200); // 在 200 毫 秒 之 内 完 成 旋 转 动 作 如 上 段 代 码, 第 02~04 行 定 义 了 该 旋 转 动 画 的 属 性, 即 以 执 行 该 动 画 的 对 象 的 正 中 心 为 旋 转 轴 进 行 旋 转, 第 05 行 则 设 定 了 完 成 整 个 旋 转 动 作 这 个 过 程 的 时 间 有 了 这 个 ra 对 象,ImageView 对 象 通 过 方 法 : ImageView.startAnimation(ra);
利 用 传 感 器 实 现 指 南 针 功 能 需 要 找 一 张 图 片 用 于 指 定 各 个 方 向, 为 了 美 观 和 便 于 使 用, 示 例 使 用 了 一 张 矩 形 图 片, 如 右 图, 关 于 自 身 中 心 显 得 对 称, 并 且 该 图 片 中 指 示 北 极 的 箭 头 是 朝 正 上 方 的, 即 可 以 设 定 原 始 图 片 的 旋 转 度 数 为 0, 如 果 原 始 图 片 的 北 极 不 是 指 向 正 上 方 也 可 以 使 用, 但 是 会 为 之 后 的 编 码 引 入 额 外 的 工 作 量 准 备 好 了 图 片 资 源, 将 其 放 入 到 工 程 的 drawable 目 录 下, 并 在 Activity 的 oncreate() 方 法 中 绑 定 compass = (ImageView)findViewById(R.id.compass);
利 用 传 感 器 实 现 指 南 针 功 能 有 了 compass 这 个 ImageView, 就 只 需 要 在 onsensorchanged() 方 法 中 通 过 传 感 器 传 回 的 数 值 来 定 义 出 需 要 执 行 的 RotateAnimation ra, 并 执 行 compass.startanimation(ra) 就 可 以 实 现 在 传 感 器 每 次 传 回 数 值 时 对 指 南 针 进 行 转 动, 从 而 实 现 了 指 南 针 的 功 能 onsensorchanged() 的 完 整 代 码 如 下 : public void onsensorchanged(sensorevent event) { switch(event.sensor.gettype()){ case Sensor.TYPE_ORIENTATION: { // 处 理 传 感 器 传 回 的 数 值 并 反 映 到 图 像 的 旋 转 上, // 需 要 注 意 的 是 由 于 指 南 针 图 像 的 旋 转 是 与 手 机 ( 传 感 器 ) 相 反 的, // 因 此 需 要 旋 转 的 角 度 为 负 的 角 度 (-event.values[0]) float targetdegree =-event.values[0]; rotatecompass(currentdegree, targetdegree); currentdegree = targetdegree; break; } default: break; } } // 后 页 续
利 用 传 感 器 实 现 指 南 针 功 能 有 了 compass 这 个 ImageView, 就 只 需 要 在 onsensorchanged() 方 法 中 通 过 传 感 器 传 回 的 数 值 来 定 义 出 需 要 执 行 的 RotateAnimation ra, 并 执 行 compass.startanimation(ra) 就 可 以 实 现 在 传 感 器 每 次 传 回 数 值 时 对 指 南 针 进 行 转 动, 从 而 实 现 了 指 南 针 的 功 能 onsensorchanged() 的 完 整 代 码 如 下 : // 接 上 页 /** * 以 指 南 针 图 像 中 心 为 轴 旋 转, 从 起 始 度 数 currentdegree 旋 转 至 targetdegree */ private void rotatecompass(float currentdegree, float targetdegree){ RotateAnimation ra; ra = new RotateAnimation(currentDegree, targetdegree, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setduration(200); // 在 200 毫 秒 之 内 完 成 旋 转 动 作 compass.startanimation(ra); // 开 始 旋 转 图 像 }
指 南 针 实 现 效 果
在 模 拟 器 上 开 发 传 感 器 应 用 SensorSimulator SensorSimulator 能 够 仅 仅 通 过 鼠 标 和 键 盘 就 能 够 实 时 的 仿 真 出 各 种 传 感 器 的 数 据, 在 最 新 的 SensorSimulator 版 本 中 甚 至 还 支 持 了 仿 真 电 池 电 量 状 态 仿 真 GPS 位 置 的 功 能, 还 能 够 录 制 真 机 的 传 感 器 在 一 段 时 间 内 的 变 化 情 况, 以 便 于 为 开 发 者 分 析 和 测 试 提 供 材 料 OpenIntents 项 目 的 下 载 地 址 在 http://code.google.com/p/openintents/do wnloads/list
在 模 拟 器 上 开 发 传 感 器 应 用 在 模 拟 器 上 安 装 和 设 置 SensorSimulatorSettings 通 过 在 命 令 提 示 符 下 键 入 如 下 命 令 来 完 成 安 装 : adb install SensorSimulatorSettings-2.0-rc1.apk SensorSimulatorSettings 界 面
在 模 拟 器 上 开 发 传 感 器 应 用 SensorSimulator PC 端 应 用 程 序
在 模 拟 器 上 开 发 传 感 器 应 用 SensorSimulator 连 接 模 拟 器 成 功
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 1. 加 载 感 应 器 模 拟 库 2. 引 用 感 应 器 模 拟 类 库
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 (2) 引 用 感 应 器 模 拟 类 库 import org.openintents.sensorsimulator.hardware.sensor; import org.openintents.sensorsimulator.hardware.sensorevent; import org.openintents.sensorsimulator.hardware.sensoreventlistener; import org.openintents.sensorsimulator.hardware.sensormanagersimulator; 需 要 注 意 的 是, 其 中 第 01~03 行 所 导 入 的 类 与 原 本 的 : import android.hardware.sensor; import android.hardware.sensorevent; import android.hardware.sensoreventlistener; 这 三 条 是 相 冲 突 的, 也 正 因 为 如 此, 模 拟 器 才 能 够 接 收 到 相 应 的 数 据, 而 新 导 入 的 SensorManagerSimulator 包 与 原 有 的 SensorManager 却 是 可 以 并 存 的, 也 可 以 说 SensorManager 包 仍 然 是 新 版 本 项 目 所 需 要 的 包, 这 是 因 为 它 还 提 供 了 可 供 使 用 的 一 些 具 名 常 量 因 此, 在 导 入 了 四 个 新 的 类 之 后, 删 除 与 之 冲 突 的 三 个 类 的 导 入 就 可 以 了
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 (3) 修 改 AndroidManifest.xml 由 于 手 机 需 要 通 过 网 络 连 接 到 SensorSimulator, 因 此 需 要 在 AndroidManifest.xml 加 入 对 网 络 的 使 用 权 限 : <uses-permission android:name="android.permission.internet"></uses-permission>
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 (4) 修 改 SensorManager 相 关 代 码 另 外 还 需 要 替 换 的 是 获 取 SensorManager 实 例 的 代 码, 因 为 SensorManager 是 用 于 管 理 传 感 器 的, 而 原 有 的 获 取 其 实 例 的 方 法 显 然 是 不 能 够 是 用 于 仿 真 出 来 的 传 感 器 的, 因 此, 替 换 : msensormanager = (SensorManager) getsystemservice(sensor_service); 为 如 下 代 码 : msensormanager = SensorManagerSimulator.getSystemService(this, SENSOR_SERVICE); 从 而 获 取 到 用 于 管 理 仿 真 出 来 的 传 感 器 的 SensorManager, 之 后, 还 需 要 通 过 如 下 方 法 使 得 该 应 用 程 序 连 接 到 SensorSimulator: msensormanager.connectsimulator();// 连 接 到 仿 真 器
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 (5) 运 行 测 试, 状 态 1
在 模 拟 器 上 开 发 传 感 器 应 用 修 改 代 码 使 指 南 针 工 作 在 模 拟 器 上 (5) 运 行 测 试, 状 态 2
计 步 器 计 步 器 介 绍 什 么 是 计 步 器 呢? 顾 名 思 义, 计 步 器 就 是 用 于 计 算 一 个 人 所 走 过 的 步 数, 市 面 上 销 售 的 一 些 计 步 器 往 往 还 带 有 其 他 一 些 非 常 丰 富 的 功 能, 如 估 算 一 个 人 所 消 耗 的 能 量 估 算 所 走 过 的 距 离 等 等 但 这 些 功 能 都 是 建 立 在 准 确 的 测 定 了 人 所 走 的 步 数 之 上 的, 那 么 如 何 准 确 的 测 定 步 数 呢? 这 就 需 要 借 助 于 传 感 器 了, 如 何 处 理 统 计 传 感 器 的 数 据, 就 决 定 了 测 定 步 数 的 准 确 性 下 面 就 在 Android 平 台 上 来 实 现 一 个 简 易 的 计 步 器 应 用
计 步 器 所 需 传 感 器 分 析 (1) 加 速 度 传 感 器 Accelerometer 加 速 度 传 感 器 所 测 量 的 是 所 有 施 加 在 设 备 上 的 力 所 产 生 的 加 速 度 ( 包 括 了 重 力 加 速 度 ) 的 负 值 ( 这 个 负 值 是 参 照 世 界 坐 标 系 而 言 的, 因 为 默 认 手 机 的 朝 向 是 向 上, 而 重 力 加 速 度 则 朝 下, 这 里 所 取 为 负 值 可 以 与 大 部 分 人 的 认 知 观 念 相 符 即 手 机 朝 上 时, 传 感 器 的 数 值 为 正 ) 加 速 度 所 使 用 的 单 位 是 m/s², 其 更 新 时 所 返 回 的 SensorEvent.values[] 数 组 的 各 值 含 义 分 别 为 : SensorEvent.values[0]: 加 速 度 在 X 轴 的 负 值 ; SensorEvent.values[1]: 加 速 度 在 Y 轴 的 负 值 ; SensorEvent.values[2]: 加 速 度 在 Z 轴 的 负 值
计 步 器 所 需 传 感 器 分 析 (2) 重 力 加 速 度 传 感 器 Gravity 重 力 加 速 度 传 感 器, 其 单 位 也 是 m/s², 其 坐 标 系 与 加 速 度 传 感 器 一 致 当 手 机 静 止 时, 重 力 加 速 度 传 感 器 的 值 和 加 速 度 传 感 器 的 值 是 一 致 的, 从 SensorSimulator 上 很 容 易 观 察 到 这 一 点
计 步 器 所 需 传 感 器 分 析 (3) 线 性 加 速 度 传 感 器 Linear-Acceleration 这 个 传 感 器 所 传 回 的 数 值 可 以 通 过 如 下 一 个 公 式 清 楚 的 了 解 : accelerometer = gravity + linear-acceleration 如 上 所 述, 可 知 Accelerometer 和 Linear-Accerleration 这 两 类 传 感 器 在 本 例 中 几 乎 可 以 发 挥 相 同 的 作 用, 本 例 中 决 定 使 用 Accerlerometer 传 感 器 来 实 现 计 步 器 的 功 能, 其 实, 如 果 某 一 款 手 机 不 支 持 Accerlerometer 而 是 支 持 Linear-Accerleration 传 感 器, 只 需 要 通 过 少 量 的 修 改 也 可 使 计 步 器 程 序 变 为 使 用 Linear-Accerleration 的 版 本
计 步 器 计 步 器 功 能 实 现 (1) 实 现 判 断 走 一 步 的 逻 辑 private static final float GRAVITY = 9.80665f; private static final float GRAVITY_RANGE = 0.001f; // 存 储 一 步 的 过 程 中 传 感 器 传 回 值 的 数 组 便 于 分 析 private ArrayList<Float> dataofonestep = new ArrayList<Float>(); 第 01 02 行 代 码 定 义 了 两 个 常 量,GRAVITY 代 表 了 标 准 的 重 力 加 速 度 值, 而 GRAVITY_RANGE 是 一 个 用 于 忽 略 极 小 的 加 速 度 变 化 的 常 量, 即 只 要 与 GRAVITY 值 相 差 在 该 值 的 范 围 内 时, 就 认 为 还 是 处 于 标 准 的 重 力 加 速 度 状 态 下, 可 以 认 为 是 一 种 防 抖 动 措 施 ; 第 04 行 定 义 了 一 个 ArrayList 类 型 的 对 象 dataofonestep 用 于 存 储 一 段 连 续 的 传 感 器 数 值 以 供 分 析 使 用
计 步 器 计 步 器 功 能 实 现 1. 实 现 判 断 走 一 步 的 逻 辑 对 于 走 路 情 景 进 行 简 化, 走 路 过 程 中 手 机 保 持 在 标 准 姿 态, 将 手 机 运 动 简 化 为 在 竖 直 方 向 来 回 运 动, 则 Value[2] 将 随 着 每 一 步 发 生 周 期 性 的 变 化 2. 注 册 和 使 用 加 速 度 传 感 器 3. 将 计 步 结 果 显 示 到 用 户 界 面
位 置 服 务 位 置 服 务 (Location-Based Services,LBS), 又 称 定 位 服 务 或 基 于 位 置 的 服 务, 融 合 了 GPS 定 位 移 动 通 信 导 航 等 多 种 技 术, 提 供 了 与 空 间 位 置 相 关 的 综 合 应 用 服 务 位 置 服 务 首 先 在 日 本 得 到 商 业 化 的 应 用 2001 年 7 月,DoCoMo 发 布 了 第 一 款 具 有 三 角 定 位 功 能 的 手 持 设 备 2001 年 12 月,KDDI 发 布 第 一 款 具 有 GPS 功 能 的 手 机 基 于 位 置 的 服 务 发 展 迅 速, 已 涉 及 到 商 务 医 疗 工 作 和 生 活 的 各 个 方 面, 为 用 户 提 供 定 位 追 踪 和 敏 感 区 域 警 告 等 一 系 列 服 务
位 置 服 务 Android 平 台 支 持 提 供 位 置 服 务 的 API, 在 开 发 过 程 中 主 要 用 到 LocationManager 和 LocationProviders 对 象 LocationManager 可 以 用 来 获 取 当 前 的 位 置, 追 踪 设 备 的 移 动 路 线 或 设 定 敏 感 区 域, 在 进 入 或 离 开 敏 感 区 域 时 设 备 会 发 出 特 定 警 报 LocationProviders 是 能 够 提 供 定 位 功 能 的 组 件 集 合, 集 合 中 的 每 种 组 件 以 不 同 的 技 术 提 供 设 备 的 当 前 位 置, 区 别 在 于 定 位 的 精 度 速 度 和 成 本 等 方 面
位 置 服 务 提 供 位 置 服 务, 首 先 需 要 获 得 LocationManager 对 象 获 取 LocationManager 可 以 通 过 调 用 android.app.activity.getsystemservice() 函 数 实 现 android.app.activity.getsystemservice() 函 数 代 码 如 下 1. String servicestring = Context.LOCATION_SERVICE; 2. LocationManager LocationManager = (LocationManager)getSystemService(serviceString); 代 码 第 1 行 的 Context.LOCATION_SERVICE 指 明 获 取 的 服 务 是 位 置 服 务 代 码 第 2 行 的 getsystemservice() 函 数, 可 以 根 据 服 务 名 称 获 取 Android 提 供 的 系 统 级 服 务
位 置 服 务 Android 支 持 的 系 统 级 服 务 表 Context 类 的 静 态 常 量 值 返 回 对 象 说 明 LOCATION_SERVICE location LocationManager 控 制 位 置 等 设 备 的 更 新 WINDOW_SERVICE window WindowManager 最 顶 层 的 窗 口 管 理 器 LAYOUT_INFLATER_SERVICE layout_inflater LayoutInflater 将 XML 资 源 实 例 化 为 View POWER_SERVICE power PowerManager 电 源 管 理 ALARM_SERVICE alarm AlarmManager 在 指 定 时 间 接 受 Intent NOTIFICATION_SERVICE notification NotificationManager 后 台 事 件 通 知 KEYGUARD_SERVICE keyguard KeyguardManager 锁 定 或 解 锁 键 盘 SEARCH_SERVICE search SearchManager 访 问 系 统 的 搜 索 服 务 VIBRATOR_SERVICE vibrator Vibrator 访 问 支 持 振 动 的 硬 件 CONNECTIVITY_SERVICE connection ConnectivityManager 网 络 连 接 管 理 WIFI_SERVICE wifi WifiManager Wi-Fi 连 接 管 理 INPUT_METHOD_SERVICE input_method InputMethodManager 输 入 法 管 理
位 置 服 务 在 获 取 到 LocationManager 后, 还 需 要 指 定 LocationManager 的 定 位 方 法, 然 后 才 能 够 调 用 LocationManager getlastknowlocation() 方 法 获 取 当 前 位 置 LocationManager 支 持 的 定 位 方 法 有 两 种 1. GPS 定 位 : 可 以 提 供 更 加 精 确 的 位 置 信 息, 但 定 位 速 度 和 质 量 受 到 卫 星 数 量 和 环 境 情 况 的 影 响 2. 网 络 定 位 : 提 供 的 位 置 信 息 精 度 差, 但 速 度 较 GPS 定 位 快
位 置 服 务 LocationManager 支 持 定 位 方 法 LocationManag er 类 的 静 态 常 量 GPS_PROVIDER NETWORK_PROVIDE R 值 说 明 gps netw ork 使 用 GPS 定 位, 利 用 卫 星 提 供 精 确 的 位 置 信 息, 需 要 android.permissions.access_fine_locatio N 用 户 权 限 使 用 网 络 定 位, 利 用 基 站 或 Wi-Fi 提 供 近 似 的 位 置 信 息, 需 要 具 有 如 下 权 限 : android.permission.access_coarse_locat ION 或 android.permission.access_fine_location. 在 指 定 LocationManager 的 定 位 方 法 后, 则 可 以 调 用 getlastknowlocation() 方 法 获 取 当 前 的 位 置 信 息
位 置 服 务 以 使 用 GPS 定 位 为 例, 获 取 位 置 信 息 的 代 码 如 下 1. String provider = LocationManager.GPS_PROVIDER; 2. Location location = locationmanager.getlastknownlocation(provider); 代 码 第 2 行 返 回 的 Location 对 象 中, 包 含 了 可 以 确 定 位 置 的 信 息, 如 经 度 纬 度 和 速 度 等 通 过 调 用 Location 中 的 getlatitude() 和 getlonggitude() 方 法 可 以 分 别 获 取 位 置 信 息 中 的 纬 度 和 经 度, 示 例 代 码 如 下 1. double lat = location.getlatitude(); 2. double lng = location.getlongitude();
位 置 服 务 LocationManager 提 供 了 一 种 便 捷 高 效 的 位 置 监 视 方 法 requestlocationupdates(), 可 以 根 据 位 置 的 距 离 变 化 和 时 间 间 隔 设 定 产 生 位 置 改 变 事 件 的 条 件, 这 样 可 以 避 免 因 微 小 的 距 离 变 化 而 产 生 大 量 的 位 置 改 变 事 件 LocationManager 中 设 定 监 听 位 置 变 化 的 代 码 如 下 locationmanager.requestlocationupdates(provider, 2000, 10, locationlistener); 第 1 个 参 数 是 定 位 的 方 法,GPS 定 位 或 网 络 定 位 第 2 个 参 数 是 产 生 位 置 改 变 事 件 的 时 间 间 隔, 单 位 为 微 秒 第 3 个 参 数 是 距 离 条 件, 单 位 是 米 第 4 个 参 数 是 回 调 函 数, 在 满 足 条 件 后 的 位 置 改 变 事 件 的 处 理 函 数
位 置 服 务 代 码 将 产 生 位 置 改 变 事 件 的 条 件 设 定 为 距 离 改 变 10 米, 时 间 间 隔 为 2 秒 实 现 locationlistener 的 代 码 如 下 1. LocationListener locationlistener = new LocationListener(){ 2. public void onlocationchanged(location location) { 3. } 4. public void onproviderdisabled(string provider) { 5. } 6. public void onproviderenabled(string provider) { 7. } 8. public void onstatuschanged(string provider, int status, Bundle extras) { 9. } 10. };
位 置 服 务 第 2 行 代 码 onlocationchanged() 在 设 备 的 位 置 改 变 时 被 调 用 第 4 行 的 onproviderdisabled() 在 用 户 禁 用 具 有 定 位 功 能 的 硬 件 时 被 调 用 第 6 行 的 onproviderenabled() 在 用 户 启 用 具 有 定 位 功 能 的 硬 件 时 被 调 用 第 8 行 的 onstatuschanged() 在 提 供 定 位 功 能 的 硬 件 的 状 态 改 变 时 被 调 用, 如 从 不 可 获 取 位 置 信 息 状 态 到 可 以 获 取 位 置 信 息 的 状 态, 反 之 亦 然
位 置 服 务 为 了 使 GPS 定 位 功 能 生 效, 还 需 要 在 AndroidManifest.xml 文 件 中 加 入 用 户 许 可 实 现 代 码 如 下 <uses-permission android:name="android.permission.access_fine_location"/>
位 置 服 务 CurrentLocationDemo 是 一 个 提 供 位 置 服 务 的 基 本 示 例, 提 供 了 显 示 当 前 位 置 新 的 功 能, 并 能 够 监 视 设 备 的 位 置 变 化
位 置 服 务 位 置 服 务 一 般 都 需 要 使 用 设 备 上 的 硬 件, 最 理 想 的 调 试 方 式 是 将 程 序 上 传 到 物 理 设 备 上 运 行, 但 在 没 有 物 理 设 备 的 情 况 下, 也 可 以 使 用 Android 模 拟 器 提 供 的 虚 拟 方 式 模 拟 设 备 的 位 置 变 化, 调 试 具 有 位 置 服 务 的 应 用 程 序 打 开 DDMS 中 的 模 拟 器 控 制, 在 Location Controls 中 的 Longitude 和 Latitude 部 分 输 入 设 备 当 前 的 经 度 和 纬 度, 然 后 点 击 Send 按 钮, 就 将 虚 拟 的 位 置 信 息 发 送 到 Android 模 拟 器 中
位 置 服 务 在 程 序 运 行 过 程 中, 可 以 在 模 拟 器 控 制 器 中 改 变 经 度 和 纬 度 坐 标 值, 程 序 在 检 测 到 位 置 的 变 化 后, 会 将 最 新 的 位 置 信 息 显 示 在 界 面 上.
Questions?