安卓可穿戴设备高级教程(五)
十五、可穿戴应用测试:在 Android Studio 中使用硬件设备
现在,您已经完成了 watch faces 应用的大部分编码和设计,您需要开始在真实硬件设备 上测试您的应用,这可能是一个非常复杂的工作过程。
第一步是让电脑、智能手机和智能手表硬件协同工作,这也是本章的主要目标,在软件开发环境(Android SDK 和 IntelliJ IDE)和硬件设备环境之间架起桥梁。我已经讨论过只使用电脑(带 AVD),现在我将讨论使用电脑和带 AVD 的智能手机,最后我将讨论同时使用电脑、智能手机和智能手表。
这将涉及到使用你制造商的 USB 驱动软件,除非你使用谷歌硬件设备,这也是模拟器使用的设备。如果你的硬件没有 USB 驱动程序,你将学习如何使用谷歌的 USB 驱动程序来让你的 Android 智能手表设备与电脑接口。你还将在你的智能手机上安装谷歌穿戴应用,并学习如何为配对和调试进行配置。
之后,您将了解 Android 调试桥 ,或 ADB ,以及如何使用该命令行工具在您的计算机和 USB 或蓝牙连接设备之间建立通信端口。然后,您将了解如何让 Android Studio IDE 使用 IntelliJ 及其 Gradle 构建系统 中的特性来识别和构建硬件设备。我们开始吧!
将设备与计算机连接:USB 驱动程序
除非你使用的是谷歌 Nexus 设备(在这种情况下,你可以使用 USB 驱动程序,即你安装 Android Studio 时为你安装的 SDK 管理器,否则你首先要做的就是访问 Android 开发者网站上的 OEM USB 驱动程序页面,网址如下:
http://developer.android.com/tools/extras/oem-usb.html
到达该页面后,右键单击 Android 设备的制造商驱动程序 URL。这将打开一个上下文相关菜单,在图 15-1 的右上角用红色圈出。选择第一个上下文菜单选项**,在新标签**中打开链接,并在浏览器的第二个标签中打开您的 Android 设备制造商网站 (我使用的是谷歌 Chrome 浏览器)。
图 15-1 。去 developer.android.com/tools/extras/oem-usb.html,右键点击并打开制造商的网站
因为我目前使用的是一台三星 Galaxy Note 3 运行 Android 4.4 来自 T-Mobile 我会在接下来的几张截图中展示我的三星 Note 3 工作流程,应该和你们厂商的工作流程 差不多。
如果 Android 链接没有带你去你的制造商网站上的支持部分,就像我的情况一样。单击您的设备类型,在我的例子中,它被标记为“手机”在图 15-2 的左下方可以看到我点击的链接被红色圈出。
图 15-2 。找到制造商网站上与您正在使用的 Android 设备类型相匹配的部分
这应该会带你到一个页面,在那里你可以找到你的智能手机产品,通常使用某种搜索应用对话框,或者可能使用一系列页面的优化过程来找到你的设备。
在三星网站 上,这是一系列下拉(微调)UI 控件元素,允许您从流派(手机、预设)到硬件设备(手机、预设)细化搜索,以选择手机运营商。
我的运营商是流行的 T-Mobile 服务,因此,我选择了 T-Mobile 作为该选项,如左下方的图 15-3 所示。T-Mobile 是一个用于 Android 开发和测试的优秀网络,因为它们支持各种各样的 Android 硬件,并具有现代、快速的 4G LTE,以及最近的宽带 4G LTE 网络。T-Mobile 现在到处都安装了 4G LTE 技术,甚至在这里的 Point Conception 半岛,旁边是一家著名的太空技术公司(Space-X)和范登堡空军基地。
图 15-3 。找到你的产品;在三星网站上,这是在移动手机
T-移动手机下拉框下
正如你在图 15-4 中看到的,一旦我指定 T-Mobile 为运营商,我就可以访问第四个下拉微调 UI 元素,其中列出了 T-Mobile 支持的所有三星手机。找到了 SM-N900T,代表三星制造 Note 900 电话(我猜的)。
图 15-4 。在你的设备上找到型号 ,找到确切的产品,并下载 USB 驱动程序
请注意,有一个 W(白色)和一个 K(黑色,对于那些不熟悉印刷和 CMYK 颜色模型的人来说)版本。因为外壳的颜色不会影响司机,我可以选择这两个选项中的任何一个,但我选择了技术上正确的黑色版本,这样我就可以在图 15-4 所示的截图中展示我的智能手机的图像。如图 15-4 右侧所示(不要让漂亮的硬件设备分散你的注意力),一旦你选择了一个硬件型号,你将会得到一个“获取下载”(或类似的)按钮。单击下载按钮,打开驱动程序软件下载页面。
寻找下载(。EXE)或类似按钮,并单击它开始下载过程。一旦你这样做了,在浏览器的底部应该有一个进度标签,显示在图 15-5 的底部。下载完成后,使用下载文件的下拉选项菜单并选择文件夹中的显示选项,这将使您在文件管理工具中拥有最大的控制权。
图 15-5 。下载 USB 驱动(上);下载完成后,从下拉菜单中选择“在文件夹中显示”
正如你在图 15-6 中看到的,一旦你进入文件管理工具,你可以右击这个下载的文件,再次得到一个上下文相关的菜单,菜单中有很多选项,其中一个是以管理员身份运行选项,它允许你使用完整的操作系统(读写)权限运行文件。
图 15-6 。右击驱动安装程序可执行文件,选择以管理员身份运行菜单选项 ??
完成安装过程。正如你在图 15-7 中看到的,我选择了美国英语并接受了一个默认的C:/Program Files/SAMSUNG/USB Drivers作为我的安装目录。然后我使用安装按钮,在我的 64 位 Windows 8.1 AMD-64 系统上安装驱动程序,如图图 15-7 所示。
图 15-7 。使用下一步按钮浏览安装配置对话框;然后单击安装按钮
需要注意的是,此时您并没有真正地将 USB 驱动程序安装到您的操作系统配置中;您只需在硬盘上安装 USB 驱动程序软件,以便计算机管理对话框可以找到它,并使其成为您当前操作系统硬件配置的一部分。
正如你在图 15-8 中看到的,你访问这个对话框的方法是右击你的电脑、我的电脑,或者在 Windows 8.1 的情况下,右击名为这台电脑的图标。在上下文菜单上,您会发现一个管理选项,该选项将打开计算机(硬件)管理对话框 。
图 15-8 。右键单击这台 PC(计算机)图标;选择管理选项,打开计算机管理对话框
Windows 8.1 计算机管理对话框应该更准确地命名为计算机硬件设备管理器工具,因为这就是它的用途。如果您想了解您的计算机设置,您可以单击左窗格中的向右箭头,打开系统工具列表中的所有区域。点击设备管理器条目 ??,显示所有连接到您电脑的硬件设备,如图图 15-9 所示。
这应该包括智能手机,您应该使用 USB 充电线将智能手机连接到 USB 端口。我一直把我的电脑连接在电脑上,所以我总是充满电。你可以在中间的窗格看到,它被高亮显示,上面写着:华莱士·杰克逊(SM-N9) ,代表车主姓名和车型名称的前几个字母。如果您的智能手机没有连接,现在插入它,它应该会被检测到并出现。
图 15-9 。在左窗格中选择设备管理器;找到 USB 驱动程序;右键单击并选择更新驱动程序软件
再次使用右键访问上下文菜单,并选择更新驱动程序软件菜单选项。这将打开你的更新驱动软件对话框,如图图 15-10 所示。点击自动搜索更新的驱动软件,确保您拥有最新版本的 USB 驱动。
图 15-10 。选择自动搜索获取最新的驱动程序版本,以确保您拥有最新的驱动程序版本
现在你已经确保你有最新的 USB 驱动程序版本,选择另一个选项,浏览 我的电脑寻找驱动软件。然后你的操作系统会找到你下载的最新的 USB 驱动软件,并开始安装过程,如图图 15-11 所示的一系列对话框。现在,您的计算机可以将数据传输到您的智能手机,您的智能手机将对 IntelliJ IDEA 可见。
图 15-11 。在您的计算机上浏览 USB 驱动程序软件,并在您的操作系统上安装 USB 驱动程序
现在当你查看你的文件浏览器(文件管理)工具 时,你将能够看到一个 Android 硬件设备,如图图 15-12 所示。
图 15-12 。显示我的 Galaxy Note 3 智能手机使用 USB 驱动程序安装到我的 PC 上
安装 Wear API:将智能手表与手机链接
现在,您已经用正确的软件设置了 Wear 开发工作站,下一步是确保您将在移动设备上安装 Android Wear,以便与您的可穿戴硬件配合使用。
这包括您将用来测试各种 Pro Android 可穿戴设备应用的智能手机(或平板电脑)和智能手表。这将包括你的手表表面应用,你将在现实世界的硬件设备上测试。
因为你的智能手表已经安装了 Android 5.0 和 Wear,这相当于在你的智能手机上安装了这些 Wear APIs,然后将智能手表与智能手机连接起来。这就是你在本章这一节要做的事情,这样你就可以设置好你的移动硬件。
下载和安装 Wear API:谷歌 Play 商店
你下载和安装 Wear API 的方式是在智能手机上,通过服务提供商(就我而言,就是 T-Mobile 的 4G LTE 服务)。在智能手机上找到您的谷歌 Play 商店图标,您将使用它来测试您的应用并启动 Play Store。在你的谷歌 Play 商店搜索栏中,输入“wear”这个词,你就可以找到与 Android Wear 相关的软件。
首先出现的结果之一将是 Android Wear 应用本身。该应用将显示您可以免费下载。你的 Android 设备的下载部分应该看起来类似于图 15-13 所示,当然,统计数据反映了当前的使用情况。
图 15-13 。安装后的 Android Wear(打开 Wear 前)
Android Wear 应用本质上是将你一直在学习的可穿戴 API 安装到任何最终用户的智能手机上,这样他们就可以运行穿戴应用。Wear 应用使智能手机能够通过使用蓝牙 4.x、NFC 或 Wi-Fi 等技术与任何兼容 Wear 的智能手表硬件“配对”,如果智能手表硬件支持的话。
因为 Apple Watch 支持 Wi-Fi,所以用不了多久 Android Wear 智能手表产品也会支持它。其实索尼智能手表 3 已经支持了。有趣的是,当我在 Note 3 上安装 Android Wear 后,谷歌应用(主要的谷歌应用,包括所有谷歌的东西/应用)也想更新自己,所以我也更新了这个应用。
现在,您已经升级了智能手机,可以使用 Android Wear 智能手表,是时候设置智能手表本身并将其与智能手机配对,以便您可以开始设置 IntelliJ 来使用它们。
设置智能手表:索尼智能手表 3
接下来,我将设置我的索尼智能手表 3 ,它是我刚刚收到的,用于这本书的佩戴开发。我按照指示插上 SW3 充电 30 分钟,然后在与 Galaxy Note 3 配对之前打开它,Galaxy Note 3 现在已经安装了 Wear 应用。
有趣的是,我得到了与 AVD 模拟器完全相同的启动动画(旋转谷歌彩色点),然后是语言菜单选择器。我选择了英语(美国),然后选择了“在您的手机上安装 Android Wear”通知。
接下来,我启动了 Android Wear 应用,出现了“让我们为您设置”屏幕,在这里,我点击了继续(蓝色圆圈中的右箭头)图标,以便我可以继续智能手表配对过程。
下一个屏幕有关于 Google 定位服务、Google Fit 服务以及接受选项的信息。一旦您选择此选项,即表明(同意)您接受隐私政策和服务条款。
我看到的下一个屏幕是“打开蓝牙”屏幕,所以我向下滑动屏幕顶部,点击蓝牙按钮,为我的 Note 3 打开该功能。我选择(检查)了我的设备(华莱士杰克逊(SM-N9)。
这个蓝牙对话框还显示智能手表 3 804D 是一个可用的设备。接下来我选择了扫描按钮,只是为了确保一切设置正确。
当我回到 Wear 应用时,我能够选择智能手表 3 804D 选项,并得到一个“配对”对话框,给我一个 224433 配对代码。
在我的智能手表 3 上,我选择(触摸)了复选标记 UI 选项,然后在两个设备配对时出现了一个下载屏幕。
这个过程花了很长时间,因为我当时正在使用 2G 网络。如果你有 3G 或 4G 连接,速度会快得多。关键是,更新过程是通过谷歌移动(GMS)网络进行的,因此速度将取决于当时的连接速度。
在我的智能手机上,我看到了一个“打开手表通知”屏幕,我被告知要前往智能手表通知设置,并选择 Android Wear 旁边的复选框,所以我点击了这个通知,它将我带到了一个屏幕,我可以在这个选项旁边打上复选标记。然后,我使用屏幕底部的后退按钮完成了设置。
需要注意的是,打开手表通知是 Wear 应用的一部分,而不是智能手表 UI 的一部分,所以请确保您没有在那里寻找它,因为您不会找到它!(我犯了这个耗时的错误。)
当我在 Wear update(下载)后第一次使用智能手表时,它有一系列的操作屏幕,与 AVD 中看到的完全一致。接下来让我们来看看如何将所有这些硬件与 Android Studio 连接起来。
使用 ADB:将智能手机与 AVD 连接起来
在本章的这一节,我将解释如何将 IntelliJ AVD 仿真器用作智能手表。你可以通过使用 USB 电缆将其连接到智能手机上,并对其进行设置,以便 AVD 充当你的智能手表。
ADB 或 Android 调试桥 的主要用途是提供 Android 设备硬件的实时连接。这个桥允许您将您的设备硬件作为 Android Studio (IntelliJ)的扩展,这将允许开发系统(在本例中为 Android Studio)和用于测试的设备硬件之间的无缝交互。
这种数据连接将允许 AVD 仿真器和物理 Android 设备使用 USB(通用串行总线)端口双向“看到”彼此,以便运行和调试应用。
首先,让我们看看如何实现硬件想法方向,这样你就可以将你的 Wear AVD 用作智能手表,然后我将开始使用 Android 设备硬件而不是 AVD 进行测试,这将等同于想法
硬件方向。
要使 Android 硬件能够“看到”USB 硬件,您需要在智能手机上启用开发者设置选项。一旦完成,您将能够选择启用 USB 调试设置,允许您的手机与您的工作站通信,并最终与您的 IDE 通信。
为此,进入智能手机的应用区(一个标有应用的 16 方形网格图标),点击标有“设置”的齿轮图标点击顶部的常规选项卡,向下滚动到关于选项,然后点击。在关于部分,您将找到一个构建编号条目,您将连续点击该条目七次。这将为智能手机解锁一个 Android 开发者模式,一个新的开发者选项部分将出现在您的常规选项卡下。在这一部分中有大量的开发人员选项。
选择 USB 调试选项,在检测到智能手机和工作站之间的 USB 连接处于活动状态(就位或插入)时启用调试(与 Android Studio 通信)。现在,您已经在计算机上安装了 USB 驱动程序,并在您的智能手机上启用了 USB,您剩下要做的就是在您的工作站上配置软件,使用称为 ADB 的东西来管理此连接。
接下来,让我们详细了解一下 Android 调试桥的功能。这一点很重要,因为 ADB 是开发工作站 Android Studio IDEA 和任何 Android 设备硬件之间的实时网络(数据连接)链接,您可能想用它来测试您的应用,以查看它的外观和功能。IntelliJ 可以访问连接硬件的许多高级功能,允许您对应用的 CPU、系统内存、屏幕空间和类似信息的使用情况进行基准测试。
Android 调试桥: 联网软硬件
ADB 是一个命令行工具 ,可以让你与 AVD 仿真器实例或连接的 Android 驱动设备进行通信。你可以通过使用你的文件管理器搜索功能在你的硬盘上找到它。
为此,请打开您的文件管理器(在 Windows 8.1 中,它被称为资源管理器),在左侧窗格中,单击最顶层的 OS 级别(这台 PC、我的电脑、计算机等)。)在您的文件管理工具中。这将向搜索工具显示您想要从哪个级别(向下)搜索。
接下来,在搜索栏中输入你要找的adb.exe可执行文件,如截图右上角的图 15-14 所示,红色包围。一旦你按下键盘上的回车键“启动”搜索,文件管理工具将搜索你的整个硬盘驱动器,这样你就可以找到文件。更重要的是,这将向您显示一个您需要使用的路径(下一步),以便使用命令提示符工具访问和运行这个 ADB 文件。在搜索结果的右侧可以看到路径(文件夹地址),如图 15-14 中用蓝色突出显示的。
图 15-14 。使用带有 adb.exe 搜索规范的文件资源管理器的搜索结果
ADB.exe 是客户端-服务器体系结构的客户端部分,包括三个主要组件,包括在开发机器上运行的客户端和作为后台进程在开发机器上运行的服务器。该服务器将管理您的客户端和 ADB 守护进程之间的所有通信,该守护进程将运行在您的仿真器和/或设备上,这取决于您正在做的事情和您在开发(IDEA 设备或设备
AVD)过程中的发展方向。
您可以从 shell 中调用客户机,在 Windows 中,这是 DOS 命令行工具,您很快就会用到它。要发出 adb 命令,您应该调用 ADB 可执行文件,并使用命令行提示符为其提供一系列开关和命令,以及可选的数据输入选项。
其他 Android 工具,如 ADT 插件或 DDMS,也将自动创建 adb 客户端,以便 AVDs 和硬件等模块可以作为一个无缝的开发环境与之通信。这就是为什么 ADB 代表 Android 设备桥的原因,因为它允许你将东西连接或桥接到 IDE 中。
第三个组件是 ADB 守护程序,它作为后台进程在每个 AVD 仿真器上运行,并在每个硬件设备实例上活动。
你可以在**/platform-tools/文件夹中找到 adb 工具,但这通常是一个隐藏文件夹,至少在 Windows 中是这样的。正如你在图 15-14 中看到的,搜索工具在 /AppData/ 文件夹中找到了adb.exe**,这在左侧显示的文件夹层次窗格中是不可见的。
需要注意的是,如果您仍在使用 Eclipse IDE 并且安装了 ADT 插件,那么您不需要直接使用 adb 在模拟器或设备上安装应用,因为 ADT 插件会处理应用的打包和安装。然而,Eclipse 在一年多前就停止了 Android Studio 开发,所以您可能希望尽快切换到 IntelliJ IDE 版本 14 (Android Studio)和 Gradle。
在 Android Studio 内部使用 AVD:ADB****端口转发
为了在你的智能手机硬件和 AVD 仿真器之间发送数据,你需要设置一个叫做 ADB 端口转发的东西。这可以通过使用 adb -d forward 命令行条目并指定您的 TCP 端口来完成。
让我们详细回顾一下这个过程,以便您可以连接您的硬件设备。启动 Android Studio,进入运行编辑配置并指定一个穿戴模块??,不启动活动选项, Android 穿戴轮 AVD 仿真器,如图图 15-15 所示,点击应用按钮,然后点击确定。
图 15-15 。设置磨损模块和磨损轮模拟器
接下来,确保在工具安卓子菜单中勾选了启用 ADB 集成选项,如图 15-16 中的突出显示。
图 15-16 。确保工具安卓
启用亚行整合子菜单项目已被选中
接下来,确保您的智能手机安装了 Wear 应用,并通过 USB 连接到您的工作站,并且 Wear 应用已在手机上启动,然后单击 IntelliJ 顶部的 Play 图标,或使用 Run Run Wear 启动 AVD 模拟器。您也可以使用 Run
Debug Wear 在调试模式下启动仿真器。对于这个例子来说,这两种方法都应该是可行的(我对这两种方法都进行了测试,结果都是可行的)。
等到 Wear AVD 模拟器初始化,显示一个 Android Wear 主屏幕,然后你就可以将智能手机与 AVD 模拟器“配对”了。这是通过使用以下命令序列将 AVD 通信端口转发到所连接的手持设备来完成的:
adb -d forward tcp:5601 tcp:5601
需要注意的是,每次您通过 USB 端口将智能手机连接到工作站时(或者如果您关闭工作站或拔掉智能手机),您都需要执行此步骤。
在 Windows 8.1 下这样做的方法是在右键单击的开始菜单(看起来像一个窗格),然后从上下文菜单中选择**命令提示符(管理)**选项,如图 15-17 中的突出显示。
这将打开命令提示符(Windows Shell 或命令行)工具,您将使用它来运行adb.exe工具,并向它发送开关、命令和参数,就像上面概述的 adb -d forward tcp:5601 tcp:5601 命令一样。-d 是交换机(d 表示设备),forward 是命令,tcp:5601 是参数(tcp 是传输控制协议或互联网协议,5601 是端口位置或“地址”)。这些 TCP 端口地址有两个,网络连接“等式”的每一端(工作站和设备)各有一个,该等式是通过使用 ADB 设备转发命令行序列在内存中创建的。
图 15-17 。右键单击开始菜单,并选择命令提示符(管理)
当您的管理员:命令提示符窗口出现时,命令提示符将显示这个cmd.exe工具“所在”的目录,因此您将知道您“所在”的计算机硬盘驱动器的位置这将是你在左上角看到的C:\ WINDOWS \ system32>??,如图图 15-18 所示。键入一个 *cd* 命令,意思是“更改目录:根目录”并点击回车**。现在,提示符将显示为 C:\ > ,您可以使用 CD (或 CD)命令将目录(文件夹)更改为您位于图 15-14 中的平台工具文件夹。更改目录 (cd)命令使用 cd 命令,然后是用户\默认。default-PC \ AppData \ Local \ Android \ SDK \ platform-tools路径,它指定了硬盘上您想要“站立”的文件夹。**
图 15-18 。导航到平台-工具文件夹,列出连接的设备,转发 adb 端口,并列出更多连接的设备
提示符现在显示您在平台工具文件夹中,可以运行 adb.exe 文件,因为它在您现在所在的同一个文件夹中。您现在可以使用 adb devices 命令行条目列出连接到工作站的所有设备。这将输出一个连接了的设备列表,正如你在图 15-18 中看到的,我的 AVD 还没有启动,所以只显示了我的 Note 3。
在我的例子中,智能手机设备被列为 4d4f4baf ,这很可能是一个内存位置。我输入了一个 adb -d forward tcp:5601 tcp:5601 命令,然后一旦 AVD 完成加载到内存中,我再次运行 adb devices 命令,正如你在底部的图 15-18 中看到的,一个 AVD 现在在附加设备列表中可见,指定为 emulator-5554 。
下一步是在您的 Android 设备上启动 Android Wear 应用并连接到仿真器,这也可能很困难,因为您需要找到的菜单项在 Android Wear 设置菜单上并不直接可见,并且工作流程在互联网上的太多地方都没有概述,所以请密切关注过程中的这一步!值得注意的是,Android Wear 应用可能会在未来改变 UI 设计,以使这个“与仿真器配对”选项更容易定位。
选择 Android Wear 的功能菜单,这是通过我的 Note 3 智能手机硬件左下角的菜单按钮访问的。这将看起来像一个正方形图标,里面有两个水平条,因此看起来像一个下拉菜单。点击它,屏幕上会出现一个菜单。
在菜单的顶部有一个“与新的可穿戴设备配对”的选项。选择这个,会出现一个“选择一个设备”屏幕,其中根本没有列出 AVD,只有配对的智能手表设备,在我的例子中,这是索尼智能手表 3。一旦该屏幕可见,再次点击硬件菜单按钮,然后您将看到您需要选择的“与仿真器配对”选项。
为了测试 ADB 连接并将数据发送到 AVD,再次访问佩戴功能菜单(在我的 Note 3 上,这是使用菜单硬件键)。在这个菜单的中间,你会看到一个选择演示卡功能的选项。
您可以使用此功能来测试设置为智能手表的 AVD。只需选择一些演示卡,并确保它们作为 Wear Round AVD 模拟器主屏幕上的通知显示在您的 AVD 上。我选择了体育、酒店和股票演示卡来测试工作站到设备的接口,该接口是通过 USB 总线(端口)使用 ADB 连接协议建立的,如图图 15-19 所示。
图 15-19 。测试智能手机到 AVD(通过 Android Studio,在工作站上)的 ADB 连接链接
接下来,这个过程将变得更加复杂,你还将连接智能手表硬件,这样你的工作站就可以通过智能手机与智能手表进行对话。
蓝牙调试 :链接到智能手表
我之所以先介绍如何从智能手机链接到 AVD,是因为需要以同样的顺序执行这些步骤,以将您的 IDE 连接到硬件设备,从另一个方向进行。你将需要能够通过 USB 电缆将你的应用从 Android Studio 发送到你的智能手机,然后再发送到智能手表。让我们来看看将智能手表与智能手机配对的步骤,然后通过 USB 建立从 Android Studio 到智能手机再到智能手表的实时链接。
值得注意的是,如果您希望将智能手表和智能手机都插入工作站上的 USB 端口,则无需执行所有这些操作。一些智能手表,如 MOTO 360,不允许 USB 连接,因为所有智能手表都有蓝牙调试,我将展示一种更复杂的方法,在没有智能手表 USB 连接的情况下让一切正常工作。
智能手表设置:配对并启用蓝牙调试
你需要做的三个主要步骤是将智能手表与智能手机配对,为智能手表启用蓝牙调试,然后在智能手机上启用蓝牙调试。第一个是通过智能手机上的 Wear 应用完成的,第二个是在智能手表上完成的,第三个是在智能手机上完成的。完成所有这些工作后,您将使用 ADB forward 并连接命令序列,以使 ADB 守护进程可以看到所有内容。
启动智能手机上的 Wear 应用,并确保它与您的智能手表配对,或者使用 Wear functions 菜单上的与新的可穿戴设备配对,这是您在上一节中使用的。第一次进行配对时,Android Wear companion 应用会建议您参加一个介绍可穿戴 UI 及其基本功能的简短教程。之后,你将能够访问一个标准的穿戴 UI,在那里你可以选择表盘,启用语音操作,并浏览谷歌 Play 商店中建议的穿戴应用。
下一步是为智能手表设备启用蓝牙调试。所有可穿戴设备都将禁用 USB 调试作为默认设置,因此您必须在智能手表上手动启用它。启用蓝牙调试的选项将被隐藏,就像它在智能手机上一样。这是为了“正常”的最终用户不会意外地启用调试模式。
您需要打开“设置”,选择“关于”,然后连续七次点按“构件编号”。这个新的设置菜单包括开发者选项,在这里你可以通过蓝牙进行调试。在我的智能手表 3(索尼)上,通过蓝牙调试选项是灰色的(禁用),直到我首先选择了 ADB 调试选项。因此,对于每个智能手表硬件设备,通过蓝牙打开调试所需的序列可能不同。
下一步是返回到您的智能手机设备,在那里您可以启动“设备调试会话”这是通过再次打开 Android Wear 应用并转到应用右上角的穿戴设置(齿轮)图标来完成的。
点击设置图标打开设置菜单,滚动到底部,找到通过蓝牙调试选项,并在其旁边放置一个复选标记以启用此功能。
在调试蓝牙功能标题下面应该有一些较小的字体文本,表明主机(您运行 ADB 连接到 Android Studio 的工作站)与断开,而目标(您的智能手表)与连接。
下一步是使用命令提示符工具访问 ADB 守护程序,并将其配置为使用蓝牙链接查看智能手表。这可以通过在 DOS 命令提示符下输入两个命令来完成,一个是 forward,另一个是 connect。第一个亚行前进命令应该是这样的:
adb forward tcp:4444 localabstract:/adb-hub
第二个 adb connect 命令更简单,应该如下所示:
adb connect localhost:4444
正如你在图 15-20 中看到的,我仍然在运行 AVD 仿真器,所以我得到了一个错误。
图 15-20 。调用 adb forward 和 adb connect 命令,连接智能手表
一旦成功,你将得到一个“允许 USB 调试?”在你的 Wear app 上留言,旁边还有一条这台电脑的 RSA 加密密钥指纹是:<密钥串在这里> 留言。点击 OK 按钮完成设置。还有一个“总是允许来自这台计算机”的选项,这是我选择的。
执行此操作后,Wear 应用设置中的“通过蓝牙调试”选项下的较小字体文本将更改为显示以下内容:
Host: connected
Target: connected
现在,您已经将所有东西“连接”在一起,您应该能够从工作站访问您的智能手机和智能手表。现在,您已经开始测试本书中到目前为止构建的 Watch Faces API 类和功能。
在你开始在 Android Studio 中测试和调试之前,我想介绍一个额外的话题,Java Singleton 设计模式。您将向 ProWatchFaceUtility.java 类添加最后一个私有构造方法,然后您将准备好测试和调试您的新应用。
Java Singleton:prowatchface utility()构造函数
在 Java 软件开发中,单例模式是一种设计模式,它将一个类的实例化限制在一个对象上。当只需要一个对象来协调整个系统的操作时,这很有用,就像在 ProWatchFaceUtility 类中一样。这个概念通常被推广到只有一个对象存在时操作更有效的场景,例如资源有限的穿戴(穿戴或智能手表端)组件。
这样做的第一步是将类的默认构造函数方法创建为私有方法。这将防止其他类直接实例化该对象。在你的 ProWatchFaceUtility.java 类的末尾添加空的private ProWatchFaceUtility( ){ }构造函数方法,如图 15-21 中底部高亮显示的。
图 15-21 。在 ProWatchFaceUtility 类的末尾添加一个私有的 ProWatchFaceUtility()构造函数方法
这使得这个私有方法成为一个类级别的方法,这意味着您的 ProWatchFaceUtility 可以被静态访问,而无需创建对象。正如您可能想象的那样,这是一种内存和 CPU 优化技术。
事实上,你会看到这个 IntelliJ 建议**通过创意左侧的一个黄色灯泡为' com . pro . Android . wearable . proandroidwearables . prowatchface utility '**添加按需静态导入,如图图 15-22 所示。
图 15-22 。使用 ProWatchFaceUtility . overwritekeysinconfigdatamap()进行静态访问(prowatchface utility)
通过在这里使用单例模式,你现在将能够使用 ProWatchFaceUtility . overwritekeysinconfigdatamap()方法访问你的 prowatchface utility 类中的方法(就像你在你的 ProWatchFaceConfigListenerService.java 类中的 onMessageReceived()方法结构中所做的那样),没有双关的意思,正如在图 15-22 的底部突出显示的那样。
接下来,让我们开始测试和调试您的 Watch Faces 应用!
测试和调试:创建您的。APK 档案
为了使用外部硬件设备在 Android Studio 中测试和调试您的 wear 应用,您需要生成**。APK** 档案。您还可以使用您的 avd 测试这些调试和发布“构建”。
您使用调试构建版本来测试您连接的硬件设备,使用 AVD 仿真器,并且您使用发布构建版本来分发您的应用,一旦您“签署”(序列化)它。
Android Studio 构建系统:概述
如前所述,Android Studio 的构建系统建立在高级的 Gradle 构建系统之上。这是一个集成的工具包,你将利用它来构建、测试、运行并最终打包(发布)一个应用。
Gradle build 系统可以使用 Android Studio 菜单系统作为集成工具包运行,也可以独立于命令行运行。您可以使用这个构建系统的特性来配置、定制和扩展这个梯度构建过程,以满足您特定的应用开发需求。
使用同一项目及其模块中的不同功能,可以为您的应用创建多个 APK 版本。您将跨不同的应用源“集”重用代码素材和资源 Android 的 Gradle build 系统的灵活性使开发人员能够实现所有这些优化特权,而无需修改应用的核心源文件。
Android 构建过程涉及许多工具和过程,它们会生成大量的“中间”文件,比如。java,。类,。德克斯还有。apk,沿途产生一个签名,内存优化。你可以把 apk 放在谷歌 Play 商店。如果您正在使用 Android Studio 开发应用,那么每次您为项目及其模块运行 Gradle 构建任务时,都会执行一个完整的构建过程。理解过程的各个阶段发生了什么是有用的,因为构建过程的大部分是可配置的,甚至是可扩展的。
为此,我将详细介绍 Gradle build 系统中涉及的各种组件,然后解释如何在 Android Studio 项目中创建构建,这是一个相当复杂的工作过程。
构建系统的组件:AAPT、AIDL、德克斯、CLASS 和 APK
Gradle 构建过程的工作方式是, APPT (Android 素材打包工具 ) 将收集您的应用的所有资源文件,例如 UI 设计所需的 XML 文件、应用清单和新媒体素材。对所有这些非编程逻辑素材进行编译,并生成 Java 模块,您将在 Java 代码中将该模块引用为 r,它实际上是通过这个 Java 文件到素材的点符号路径,如以下代码所示:
watchFaceDrawable=watchFaceResources.getDrawable(R.drawable.prowatchfacelow); //ProWatchFaceService
这将从您的项目 /res 资源文件夹中的适当分辨率密度文件夹(/res/drawable-hdpi)中访问prowatchfacelow.pngPNG BitmapDrawable 素材,在那里您的 R.java 资源被组织为 AAPT 编译成可以在运行时使用的格式。
AIDL(Android 界面定义语言 ??)工具 ?? 将你的。aidl 接口,用于将 IPC(进程间通信)实现为 Java 接口。IPC 在磨损应用中不常用,也不在本书的讨论范围之内,但是如果您需要使用它,您可以从下面的开发人员网站 URL 获得更多信息:
http://developer.android.com/guide/components/aidl.html
在图 15-23 中可以看到,所有定制的 Java 代码,包括 Java 生成的 AAPT 和 AIDL 生成的。aidl 文件,被一个 Java 编译器编译成中间**。类**文件,你也在你的 AndroidManifest 中引用了它。XML 应用定义。
图 15-23 。Android 构建过程,从 AAPT 到。爪哇,到。上课去。德克斯去。apk,致署名 APK
构建过程的下一步是在。类文件转换成优化的。dex 文件格式,使用 Dalvik VM 工具。所有第三方库和。包含在项目模块构建中的类文件也将被转换成。德克斯文件。这是为了将它们打包到最终版本中。apk 文件。
所有未编译的资源,通常放在项目的 /res/raw 文件夹中,以及所有已编译的资源(R.java)和您的。然后,dex 文件被发送到 apkbuilder 工具,打包到您的 APK 中。
一旦你。apk 建立后,必须使用调试或发布密钥对其进行签名,然后才能安装在 Android 硬件设备上进行测试(调试)或使用(发布)。我将在下一章讨论等式的发布部分,在那里我将解释一个梯度构建过程的最后一行(步骤),如图 15-23 所示。
最后解释一下构建过程,如果您的应用是以发布模式签名的,您必须对齐这个。使用 zipalign 工具进行 apk。如果你想知道,调整你的期末考试。当你的应用在 Android 硬件设备上运行时,apk 会减少内存使用。
Android 应用 Java 代码限制 : 64 千字节的方法
Android 应用分配给方法引用的代码限制是 64kb——64kb 代表 65,536 个字符的代码。如果您的应用达到了这个限制,Gradle 构建过程将无法通过。dex 转换。
随着开发人员可以用来创建应用的 Android API 库的规模不断膨胀,使用这些 Java 类或方法创建的 Android 应用的规模也随之膨胀。当应用和它们引用的库达到一定大小时,您将会遇到构建错误,指示应用已经达到 64 KB Android 应用构建限制。
Android 4 构建系统的早期版本报告了如下错误:
Conversion to Dalvik format failed:
Unable to execute dex: method ID not in [0, 0xffff]: 65536
Android 5(Android Studio)Gradle build 系统的最新版本可能会显示不同的错误,这表明存在相同的问题:
Trouble writing output:
Too many field references: 128000; max is 65536.
You may try using --multi-dex option.
这两种错误情况都显示 64 KB 的十进制等效值:65,536。这个数字表示在一个 Dalvik 可执行(DEX)字节码文件中,Java 代码可以调用的引用总数。如果您构建的 Android Wear 应用会“抛出”这一错误,那么您可能有过多的 Java 代码,并且可能想要查看代码优化。
有一种方法可以绕过这个限制,这就是本章的这一节所解释的。我把这个包括在内,以防你的应用需要复杂。Android 应用包(或 APK)文件包含可执行字节码文件。这些将采用 Dalvik 可执行文件 (DEX)文件的形式,其中包含运行应用所需的 Dalvik VM 优化 Java 字节码。
当前的 Dalvik 可执行优化规范限制了单个。dex 文件到 65,536。这是一个均匀的“2 的幂”内存边界,可以包括您的 Android API 框架方法、库方法和您为应用功能创建的自定义方法。
通过“链接”可以超过这个 64 KB 的限制。德克斯的文件放在一起。这要求您配置应用的梯度构建过程,以生成多个。dex 文件。这在 Android 中通常被称为 multidex 应用 分发配置。
在 Android 5 之前的 Android 平台版本使用 Dalvik VM 运行时来执行应用代码,而版本 5 和更高版本使用为 Android 定制的 ART (Android 运行时)。Dalvik VM 限制每个应用只能有一个 classes.dex 字节码文件。apk 文件。为了避开这个限制,你可以使用多指数支持库。该库将成为主库的一部分。dex 文件,然后将管理对您的附加。dex 文件,有效地链接到它们包含的字节码。
Android 5 及更高版本使用 Android 运行时(ART),它原生支持加载多个。dex 文件,使用单个。apk 文件。这是因为 ART 在用户安装应用时进行预编译,所以 ART 可以扫描多个 classes.dex 文件,并将它们编译成一个单独的**。由 Android 设备执行的 oat** 文件。安。oat 文件存储了为新的 Android 运行时 (ART) 设计的应用的原生 C++ 代码,该运行时在 Android 4.4 和更高版本中可用。
在将应用配置为使用超过 65,536 个方法引用之前,您应该尝试优化应用的 Java 代码调用的引用总数。这包括在应用的 Java 代码中定义的方法,或者更有可能是通过减少 API 库包导入的数量。
要做到这一点,通过确保应用中包含的任何大型库的使用方式超过添加到应用中的代码量,来优化应用的直接和可传递依赖关系。
开发人员有时会犯的一个错误是,在很少使用一些实用方法的情况下包含大型库。减少 Java 代码依赖性通常可以避免这 64 KB。dex 方法参考限制。
您也可以使用 ProGuard 删除未使用的代码。为此,请为运行 ProGuard 的应用配置 ProGuard 设置,并确保您已经为您的 APK 版本 Gradle builds 启用了收缩。启用收缩将确保 APK 中不包含任何未使用的 Java 类或方法。
使用这些优化技术可能有助于避免在应用中允许更多方法引用所需的构建配置更改。优化还可以减小 APK 的大小。这对于那些带宽成本高的市场来说尤其重要,因为这样可以降低应用的运行成本!
配置梯度构建:创建不同的 APK 类型
Gradle build 将生成一个特定的。应用/构建文件夹中每个构建变体的 apk 文件。一般来说,这将是一个调试变体,用于您的测试工作流程,以及一个发布变体,用于将您的应用发布到谷歌 Play 商店进行分发。
您可以为您的 Wear 应用发布工作创建您需要的任何其他“风格”的应用。例如,您可以在一个 /src/demo 文件夹中创建一个“有限功能演示”版本,并指示 Gradle 使用该文件夹的内容为您创建一个pro watch face-demo-release . apk文件。
生成到 app/build/outputs/apk/ 目录中的 apk 文件将包含使用以下 APK 文件命名约定命名的包:
<application name>-<flavor>-<buildtype>.apk
例如,ProWatchFace-full-release.apk 将是您的发布 apk,或者 ProWatchFace-full-debug.apk 将是您的完整 WatchFace 应用演示版本的调试版本。
接下来,在我开始讨论 ProGuard 和 Gradle build 系统之前,让我们检查一下,确保您有最新版本的 Android Studio。在你这样做之后,你实际上可以使用 Android Studio 来生成一个构建,你可以开始查看构建和测试你的 Watch Face 应用的过程。
启动 Android Studio,使用帮助检查更新菜单序列,确保没有新的 Android 组件已经发布。希望你会看到“你已经安装了最新版本的 Android Studio”对话框,如图图 15-24 所示,以及帮助
检查更新菜单序列。如果需要,请在继续之前更新 Android Studio!
图 15-24 。在开始构建、调试和测试阶段之前,总是使用 IDE 的检查来更新特性
接下来,让我们仔细看看移动模块(组件)的 Gradle build 配置文件,并了解 build.gradle 文件中的其他部分(除了 Android 和依赖部分,我已经详细介绍过了)。
配置 构建??:解剖一个 构建.配置
首先,让我们深入了解一下应用的移动模块的 gradle.build 文件。打开你的 app 的 Gradle Scripts 部分,右击build . Gradle(Module:mobile),选择 Jump to Source (或按 F4 功能键),在编辑页签中打开该 Gradle script,如图图 15-25 所示。
图 15-25 。打开移动模块 build.gradle 文件,并使用“立即同步”功能确保它是最新的
如果在 build.gradle 编辑窗格的顶部出现黄色的“Gradle 文件已更改”消息,请单击右侧的立即同步链接选项。这将同步您的项目,您总是需要在构建之前这样做。
第一个 apply 插件语句允许构建配置的 android {}部分引用 Google 的 Android Maven 存储库中的 com.android.application 定义。这允许文件的 android {…}部分存在(也就是说,有意义),并因此被正确解析。
正如你已经知道的那样, android 部分定义了你的版本和包命名约定,而你的依赖项部分引用了外部 API 库,Gradle 需要将这些 API 库引入到你的应用编译过程中。请注意,有一个 wearApp 项目条目,它连接应用的 wear 模块,还有一个编译文件树条目,它将包括您可能放在项目的/ExternalJarFiles 目录中的任何第三方 JAR 文件(即物理或 3D 渲染库)。
在构建时,buildTypes{}部分是主要关注的内容。图 15-25 中的 buildTypes{}部分显示了 build types { }部分的嵌套发布{} 子部分。如果您想知道 build.gradle 文件使用的是哪种编码格式,它是一种叫做 Groovy 的编程语言。
您可能想知道为什么没有 debug{}子部分,因为总是会生成两种主要的构建类型。这是因为调试构建规范是自动生成的(默认),而不必实现显式的构建配置规范。也就是说,如果您愿意,可以使用 debug{}子部分。
例如,您可以添加“.”的应用 id 后缀。debug”来进一步确定您的调试文件版本,如果您愿意,可以使用下面的 Groovy 代码:
debug {
applicationIdSuffix ".debug"
}
buildTypes{}部分的 release{}部分将优化您的。APK 文件发布版,使用了 ProGuard 工具和 minification 标志,通过使用下面的 Groovy 代码,其中没有使用分号字符来终止其语句!这可以在图 15-25 的中看到:
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
接下来,让我们来详细了解一下 ProGuard 工具和 minification 标志,这样您就可以确切地知道它们是什么,以及为什么要在您的发布 APK 文件构建中使用它们。
使用 程序 :压缩、优化、混淆代码
ProGuard 工具优化了您的代码,使其更加紧凑,同时也使代码更难逆向工程,这一过程称为“混淆 ”它通过移除未使用的代码并使用晦涩的名称重命名类、字段和方法来实现这一点,从而使代码难以逆向工程。
结果是一个更紧凑的版本。apk 文件,逆向工程难度更大。因为 ProGuard 使您的应用更难被逆向工程,所以当应用利用对安全性敏感的特性时,例如当您正在许可一个应用或当它包含专有或有价值的 IP 时,实现 ProGuard 是很重要的。
ProGuard 被集成到 Android build 系统中,如图图 15-25 所示,这样你就不用手动编码调用来实现它,使用 Groovy。只有在发布模式下构建应用时,才应该调用 ProGuard。这样,当您使用调试模式构建应用时,就不必使用混乱的代码进行调试,至少可以说这是令人困惑的!
运行 ProGuard 进程是可选的,但是强烈建议这样做。要打开 ProGuard,将 minifyEnabled 标志设置为等于 true 值,要禁用(关闭)ProGuard,将 minifyEnabled 标志设置为 false。此 minifyEnabled 属性是 release{}子部分中 buildTypes{}部分的一部分,它控制应用于发布版本的设置。当您准备好压缩(压缩)和混淆 Java 代码时,将 minifyEnabled 属性设置为 true 以启用 ProGuard。
需要注意的是,尽管 Android 希望您使用 ProGuard,这也是 Android Studio 为您安装这两个 Groovy 语句的原因,但 Android 通过将 minifyEnabled 设置为 false 值来停止为您实现这两个语句,这在一开始就关闭了 ProGuard。
getDefaultProguardFile( ) 方法 设置一个“ProGuard-Android . txt”ProGuard 配置定义,在图 15-25 中高亮显示。这是你默认的 ProGuard 配置设置,这个文件可以在 Android/tools/ProGuard/文件夹中找到。
还有一个proguard-Android-optimize . txt文件,在 Android**/tools/proguard/**文件夹中也有。该文件实现了相同的规则,但是它也支持“字节码级别”的优化。这些优化将在 Java 字节码级别执行额外的优化分析。这是在方法内部和方法之间完成的,当 Android RunTime (ART)引擎以 Java 字节码的形式运行应用时,这有助于使应用更小、运行更快。
最后,还要注意在图 15-25 中突出显示的 Groovy 代码行中,Android Studio 在 proguardFiles 条目的末尾使用了一个逗号,并在该模块的根目录添加了**‘proguard-rules . pro’**文件引用。这样,如果需要,您可以轻松地添加您自己的、定制的 ProGuard 规则,这些规则应该是特定于发布模块的,您可以将它们添加到该文件中,这样它们将确保生效。
接下来,让我们看看你的**build . grad le(Module:wear)**并确保它在你构建应用之前不需要同步。
右键单击build . gradle(Module:mobile),选择跳转到源代码(或按 F4 功能键),在编辑页签中打开该 Gradle 脚本,如图图 15-26 所示。如果在 build.gradle 编辑窗格的顶部出现黄色的“Gradle 文件已更改”消息,请单击立即同步。
图 15-26 。打开磨损模块的 build.gradle 文件,并使用“立即同步”链接同步到您的项目
现在是时候看看 Gradle 的构建过程并创建调试 APK 了,这样你就可以开始漫长的测试、调试和发布过程,这将贯穿本章的剩余部分以及下一章。
构建你的项目:使用 Gradle 构建引擎
虽然您可以使用 AVD 模拟器在内部测试项目组件,但是为了在下一个级别真正测试您的项目组件,您需要将它们“构建”到 Android 包中,或者。简称 APK,文件格式。这种格式也可以用 AVD 来测试。更重要的是,它可以在现实世界的硬件上进行测试,通常是在应用开发过程的最后。
运行 Make 项目工具 :使用 Gradle Build 控制台
在 Android Studio 中打开你的项目,使用 Build Make Project 菜单序列,调用 Gradle build 过程,如图图 15-27 所示。
图 15-27 。使用 Build Make Project 为 ProAndroidWearable 项目创建 Android 包 APK 文件
正如你在图 15-27 所示的菜单中看到的,你可以只构建移动模块,但是因为这是一本穿戴书籍,你将构建项目,该项目将构建移动(电话)和穿戴(智能手表)组件。
要查看 Gradle 在项目的移动和穿戴部分的构建过程中做了什么,请单击位于 Android Studio 右下角的 Gradle 控制台选项卡。正如你在图 15-28 中看到的,我不得不使用两个屏幕(在一个图中)来显示 24 个移动构建步骤和 24 个磨损构建步骤,从而在 29 秒内成功构建了 APK。
图 15-28 。单击右下角的 Gradle 控制台选项卡,查看 Gradle 正在执行的构建任务
既然您已经构建了项目,下一步就是运行项目模块,通过 USB 连接的 Android 硬件设备来查看它们是如何工作的。
运行您的 APK:使用一个 USB 设备目标设备设置
当您将一个模块作为 Android 应用(APK)运行时,Android Studio 会自动创建您的运行配置。默认运行配置将启动默认项目活动,并使用自动目标模式进行设备选择。自动目标设备模式将选择仿真器,选择(首选)AVDs 的无(空下拉菜单区域)。
一个手动目标设备模式是你在本书中迄今为止一直使用的,在这里你选择了 Nexus 或 Wear 你想要启动的 AVDs。现在您将在运行/调试配置对话框中为常规选项卡的目标设备部分选择 USB 设备选项,如图图 15-29 所示(左侧为移动模块,右侧为磨损模块)。
图 15-29 。使用运行/调试配置对话框设置移动和磨损模块使用 USB 设备
我必须通过 USB 重新建立硬件接口,所以我在图 15-30 中包含了我的 DOS 命令提示符窗口,以向您展示我如何使用 adb 设备来查看是否有设备连接,以及一旦我看到设备,我如何使用 forward 和 connect 命令来访问智能手机和智能手表。
图 15-30 。使用 ADB 命令设置 USB 智能手机连接和智能手表蓝牙
设置好之后,我使用运行项目(不是运行 wear)来运行移动模块和磨损模块,这样我可以一起测试它们。我在我的设备上收到了允许谷歌检查设备病毒和 Wear 未连接的消息,尽管 Wear 应用正在运行。我在 LogCat 窗格中得到一些错误和警告,如图 15-31 所示。
图 15-31 。设备和 LogCat 窗格将在 Gradle 控制台旁边打开,显示警告和错误
我首先使用谷歌搜索解决了红色的错误消息,看看是否有其他开发人员得到了这个senduractionevent()mView = = null错误消息。原来这是三星硬件的问题,因为我目前正在使用 Galaxy Note 3,所以我排除了这个问题,我需要在我的代码库中寻找解决方案。
我想解决另一个警告,即没有 epolicy 文件来找出什么是 epolicy 文件,所以我也在谷歌上搜索了一下,发现这个错误与运行多个构建会话有关,与智能手表上没有手表表面无关。
在这种情况下,接下来要尝试的是通过 USB 电缆直接连接智能手表,这样智能手机和智能手表都可以直接连接,并且可以关闭蓝牙调试(这比较慢,可能也是问题所在),从而消除一层复杂性。需要注意的是,没有 USB 端口的智能手表(如 MOTO360)必须使用蓝牙调试,这也是我详细介绍它的原因。
硬连线 USB 连接 :设置智能手表 USB 驱动
因为我找不到专用的索尼智能手表 3 USB 驱动程序,这将是一个很好的机会,向您展示如何使用谷歌 USB 驱动程序,您使用 Android SDK 管理器安装该驱动程序来完成连接。
因为你已经安装了谷歌 USB 驱动,你唯一需要做的就是在你的AppData/Local/Android/SDK文件夹中找到它。它不在/platform-tools 文件夹中,而是在一个不同的目录中,名为**/extras/Google/USB _ driver**,名为 android_winusb 。
对智能手机 USB 驱动程序执行与之前相同的步骤,这可以在图 15-8 到 15-10 中看到,除了这一次,指定您刚刚找到的谷歌 Windows USB 驱动程序。需要注意的是,如果你使用的是 Linux 或者 Macintosh,你不需要安装任何 USB 驱动。
现在 adb 命令序列变得更容易,因为你不必使用 adb 转发和 ADB 连接蓝牙序列;您只需使用 adb devices 命令来查看硬件设备是否已连接。您也不需要ADB-d forward TCP:5601 TCP:5601命令来启用通过智能手机到智能手表的端口转发。
正如你在图 15-32 中看到的,新的 ADB 命令行序列要短得多,因为你不需要设置一个蓝牙端口,然后连接到它。
图 15-32 。当两个硬件设备都通过 USB 连接时,ADB 命令行序列要短得多
当你进入 Android Studio 并查看 Gradle 控制台窗格旁边的 Android 窗格时,你会看到现在有两个硬件设备,如图 15-33 中屏幕左侧突出显示的下拉菜单所示。
图 15-33 。在 Android 选项卡中,在 IntelliJ 的底部,您会在下拉菜单中找到这两种硬件设备
当您使用 Run 项目、Run
Wear 或者 Run
Mobile sequence 时,会弹出选择 设备对话框,如图图 15-34 所示,这样您就可以选择要将该构建推送到的硬件设备。
图 15-34 。当您选择运行 wear 或运行
mobile 时,您会看到一个选择设备对话框,其中列出了硬件
然而,尽管我的配套应用在智能手机上运行良好,但我的表盘组件却没有在智能手表上显示出来。心血来潮,查了一下更新,得知 Android 5.2 刚刚发布。
事实证明,5.2 版本是一个重要的版本,对 API 进行了重大的修改。这影响了 ProWatchFaceService 类和我正在使用的方法。所以我决定在这里结束这一章,并添加另一章关于如何处理这些重大的操作系统更新变化,这样你就可以看到整个过程,以防它发生在你身上,这总是会发生的,因为 Android 是一个“移动的目标”。
摘要
在本章中,您学习了如何让您的电脑、智能手机和智能手表硬件协同工作,在软件开发环境(Android Studio)和您的硬件设备环境之间架起桥梁。
这包括获得一个制造商的 USB 驱动程序软件,并学习如何使用谷歌的 USB 驱动程序,如果你需要让你的 Android 智能手表设备与电脑接口。
你学会了如何确保在你的手机上安装一个 Google Wear 应用,以及如何配置它用于配对和调试目的。
您学习了Android Debug Bridge(ADB)命令行工具,以及如何使用 DOS 命令提示符来访问它,以便在您的计算机、USB 或蓝牙连接设备之间建立通信端口。然后,您开始使用 Android Studio IDE 来识别和构建您的硬件设备,使用 IntelliJ 及其 Gradle 构建系统中的各种窗格和对话框功能。
在下一章中,你将升级到 Android 5.2,从你的 BitmapDrawable 代码中取出一个不推荐使用的方法调用,并学习在 Android 中开发如何成为一个移动的目标,以及如何最好地处理这个问题!
十六、Wear API 弃用:更新应用以使用新的类或方法
在第十五章中,你设置了硬件设备,这样它们就可以通过使用 Android 调试桥与 Android Studio 对话。然后,您尝试让 wear 组件显示在智能手表上,以便测试配置伴侣活动。我在工作过程中尝试的一件事就是检查 Android Studio 和 Android SDK 的更新。
有一个重要的操作系统更新,Android Studio 1.2(Android 5.2),已经发布了!所以我决定将这个更新和不推荐的代码更新的过程放在它自己的一章中。本章将介绍更新该项目的 wear 组件的过程,该组件目前尚未在智能手表设备硬件上按预期运行。我将介绍整个过程,从处理意外的重大 SDK 升级到重新编码任何不赞成使用的类或方法。在这种情况下,这些将涉及 ProWatchFaceService.java 类。
因此,在本章中,您将了解更多关于日历和公历日历类的信息,它们将用于取代 Android 5.2 中不推荐使用的时间类。您还将实现一个不同版本的**。getDrawable( )** 方法,作为该方法调用的两个版本之一,在本次 Android 5.2 API (SDK)升级中被弃用。
当我完成代码升级时,一个Android Studio 1.2.1.1升级也发布了,这给 Gradle build 系统与 IntelliJ (Android Studio)的集成带来了一些问题。所以我会解释更多关于 Gradle 和 IntelliJ 的内容来帮助你学习如何解决这个问题。
应对突发更新:Android 5.2
当我检查更新时,我得到了一系列对话框,如图图 16-1 所示。然后我继续绕过如图图 16-1 所示的对话框来更新 Android。我点击了更新和重启按钮,我得到了下载补丁文件和更新进度条对话框,最后,我选择了我想从以前版本导入我的设置单选按钮,和确定按钮来完成这个过程。几个星期后,1.2.1 出来了,一周后又是 1.2.2,所以我不得不从头再做一遍!
图 16-1 。更新对话框,显示一个主要的 71MB 更新可用于更新到 Android Studio 1.2
正如你在图 16-2 中看到的,这次更新是一次重大更新,需要安装 28 个 API SDK 包。我点击了安装 28 包按钮,并更新。
图 16-2 。此安装会自动选择 28 个 SDK 包、库和系统映像来安装或更新
Android SDK 管理器日志显示了 Android SDK 工具修订版 24.1.2 和 Android SDK 平台工具修订版 22 的下载和安装,如您所知,其中包括 ADB 服务器和工具。如果 ADB 服务器正在运行,安装程序可以停止它,它确实停止了,然后安装程序试图重命名当前的**/平台工具**文件夹以便备份它。这失败了,因为我打开了一个命令提示符,所以安装程序停止并产生一个错误信息,在图 16-3 中显示为红色。
图 16-3 。为了继续安装,我必须关闭命令提示符工具
一旦我关闭命令提示符,安装就完成了,如图图 16-4 所示。
图 16-4 。选择最新的 Android SDK 构建工具;更新英特尔 x86 仿真器,看看它是否能在 AMD 上工作
如你所见,最新版本的 Android Build Tools (22.0.1)没有被选择安装。我也选择了这一点,因为我试图解决我的项目的手表表面(佩戴)侧不在智能手表上显示的问题,解决方案可能在这个新的 Build Tools 22 代码中。
我还选择了英特尔 x86 模拟器加速器(HAXM)的更新,以查看是否添加了对 AMD64 系列处理器的支持。接下来,我单击了 Install 2 packages 按钮,安装了这些在第一次操作系统平台更新时没有安装的软件包,为了在 IDE 中安装所有需要的东西,您经常需要这样做。
现在我已经更新到了 Android 的下一个主要版本(5.2),是时候看看 ProWatchFaceService.java 文件(类)了,看看代码中是否有任何东西可能会阻止应用的手表表面(佩戴)侧在智能手表设备硬件上运行。
处理折旧:。getDrawable()和时间
正如你在图 16-5 中看到的,现在你的代码中有了在最新版本更新之前没有的亮点。被弃用的代码被排了出来(这使用了删除线字体),这可能有些令人不安,但它直观地通知开发者,他们正在使用的代码是安卓 5.x 平台不再支持的**,这就是被弃用的意思。你可以将鼠标放在突出显示的代码上,你会得到一个弹出提示,告诉你这个**。getDrawable(int)** 方法调用已被否决。这意味着你需要到开发者的网站上查看 API。**
**
图 16-5 。打开在智能手表上不工作的 ProWatchFaceService 类来查看代码
你可以在 Gradle 控制台中看到颜色突出的注释,显示在图 16-5 的底部,它建议你如果想要使用不推荐使用的代码,你需要使用名为 -Xlint:deprecation 的编译开关。我想在这本书里使用 100%干净的(无 bug 和最新的)代码,所以我将在这里采取更困难的方法,重新编写 Java 代码。
Android 5.2 (Android Studio 1.2)中有两个主要的弃用之处会影响到你一直在写的代码。一个是时间类,另一个是。getDrawable(int)方法。在本章的这一节,我将讨论可以用来代替你一直在使用的不赞成使用的类和方法的类和方法。值得注意的是,您仍然可以使用您在本书前面添加的代码,但是,随着时间的推移,不推荐使用的代码最终会变成停止使用的代码,所以最好立即升级(替换)不推荐使用的 Java 语句!
Android 的资源类:两个。getDrawable()方法
我已经解释了 Android Resources 类,所以我在这里不再重复。我将只介绍适用于必要的 Java 代码升级的内容,这将消除 IntelliJ (Android Studio 1.2)中删除的代码。
为了升级已弃用的。getDrawable(int)方法调用,你将需要在开发者的网站上查看 Android 的 Resources 类。你需要这样做来确定是否有这些的其他版本。getDrawable( ) 方法调用将允许您从/res/drawable-hdpi/文件夹中检索背景图像可绘制素材。可以在以下 URL 找到资源类技术信息页面:
http://developer.android.com/reference/android/content/res/Resources.html
注意有两个。Resources 类中列出的 getDrawable()方法,其中一个现在已被否决,所以您必须使用较新的方法,这是在线文档中建议的。关于这些的技术信息。在线的 getDrawable()方法结构应该是这样的:
Drawable getDrawable(int id)
This method was deprecated in API level 22. Use getDrawable(int, Theme) instead.
Drawable getDrawable(int id, Resources.Theme theme)
Return Drawable object associated with a particular resource ID and styled for the specified theme.
因此,您对此 Android 5.2 升级弃用的解决方案是使用不同版本的。getDrawable(),它使用了一个资源。主题对象名为主题。如果你想继续使用你当前指定的主题,使用一个空值**。让我们来看看参考资料。下一个主题嵌套类。**
资源。主题嵌套类:主题属性
Resources 类有一个嵌套的公共最终资源。 主题 类,该类扩展了 java.lang.Object 主类,具有以下层次结构:
java.lang.Object
> android.content.res.Resources.Theme
这个嵌套的助手类被创建来保存特定主题对象定义的当前属性值。众所周知,主题是一组使用资源属性定义用户界面外观和感觉的值。
主题对象封装了一个保存这些主题属性的 TypedArray 对象。使用 int[ ] 数组和 AttributeSet ,可以利用 TypedArray 来解析属性的最终值。你通常会使用**。获取样式属性(AttributeSet,int[ ],int,int)** API 来检索 XML 定义的主题属性,并使用父用户界面和子用户界面属性定义标签应用样式和主题信息。Wear 应用通常不会改变主题,至少你正在编写的 Watch Face 应用不会。
当您想要保留一个默认的或者当前的主题时,您将为资源使用一个空值。. getDrawable()方法调用中的主题对象。
主题对象的属性以两种方式发挥作用。第一种是通过 styled 属性,它可以通过在 XML 标记参数中使用themeParameterName="?themeAttribute"语法显式引用主题中的任何值。
引用主题对象属性的第二种方法是在 Java 代码中使用**。获取样式属性(AttributeSet,int[ ],int,int)** API 方法调用来检索 XML 定义的主题属性。如果想保持的向后兼容性,还有一个 ResourcesCompat 类。
接下来让我们看看 ResourcesCompat 类,因为添加向后兼容特性可以防止这种情况再次发生。这个类也有一个. getDrawable()方法,允许你在一个方法调用中传递一个资源 R 引用、一个可绘制索引整数和一个主题。
ResourcesCompat 类:向后兼容性
Android 的public****Resources compatclass 也扩展了 java.lang.Object,因此被临时编码以提供资源的向后兼容性。该类的 Java 类层次结构类似于下面的代码:
java.lang.Object
> android.support.v4.content.res.ResourcesCompat
这个类是作为一个助手类创建的,开发人员可以利用它来访问 API level 4 之后引入的资源中的特性。这是以一种向后兼容的方式完成的,因此 Android 开发者可以避免在这本书的过程中发生的事情。你不需要在 wear 开发中使用它,因为 Wear 是在 4.4 中引入的,并且正在快速发展到主要利用 5.0 到 5.2(到目前为止)。
这个类有一个公共构造函数方法, ResourcesCompat( ) ,用于创建一个对象。这个类中还有两个公共方法调用。一个是**。getDrawable(Resources res,int id,Resources。Theme theme)** ,返回与引用的资源 ID 相关联的可绘制对象,并将使用指定的主题对象进行样式化。
另一个是getDrawableForDensity(Resources RES,int id,int density,Resources。主题主题)方法调用。这可用于访问不同密度的可提取素材。大多数智能手表产品的像素范围是 320 到 400 像素(我希望到 2016 年可以增加到 480 到 640 像素),所以你现在不需要使用这个版本的方法调用,它为密度(文件夹)添加了一个变量来访问可绘制的素材。
因为 Resources 类是 Wear 应用中更常用的标准类,也是您已经在使用的类,所以我将使用它。接下来我们来看看另一个主要的弃用,整整一节课!
处理废弃的类:时间类
您可能还注意到,在 ProWatchFaceService 类的顶部,Time 类(对象)引用在代码中被删除了,这意味着它也不被推荐使用。这个类仍然可以使用,至少到 2038 年,当它覆盖的日期(时间)范围用完时。这很可能是这个类被弃用的主要原因,尽管 Android 开发者的网站上没有给出具体的原因。
这是这次 Android 5.2 更新中的另一个主要反对意见,它影响了 ProWatchFaceService 类的 Java 代码,这意味着您必须重新编码来解决这个问题。
这一次,需要使用日历或公历类或它们的组合来替换整个类,即 time 类。您很快就会了解到,这些类是紧密相关的,并且与 Android 的日期和时区类相关。
Android Calendar 类是一个抽象类,用于创建 GregorianCalendar 具体类,这个 Calendar 抽象类和 GregorianCalendar 具体类可以访问(利用)日期和时区对象。您将直接使用 Calendar 类(对象)和。getInstance()方法调用,您将在接下来学习它。
日历类:日期和时间的抽象类
Android 公共 抽象日历类 扩展了 java.lang.Object,实现了可序列化可克隆可比<日历> Java 接口。这个日历类的 Java 类层次结构如下所示:
java.lang.Object
> java.util.Calendar
Calendar 类有一个已知的直接子类, GregorianCalendar ,我将在下一节介绍它。Calendar 类是一个抽象类,用于创建 GregorianCalendar 类。它提供了方法调用,可用于从一个日期对象和该日期对象包含的一组整数字段中提取数据。
其中包括年、月、日、小时、秒、分钟和毫秒。Date 对象表示时间中的一个瞬间,如果需要的话,它可以使用毫秒级的精度。您很快就会在新的代码库中使用这种数据提取功能,所以我将在这里详细介绍这个类及其相关方法。
与其他 Android 5 位置敏感类类似,这个 Calendar 类提供了一个名为的方法调用。getInstance( ) 。这可用于创建此日历类的实例以供一般用途。getInstance()方法将返回一个 Calendar 对象,其位置的微调基于应用用户的系统设置。该对象的时间数据字段将使用用户的当前系统日期和系统时间进行初始化。
对象声明和实例化可以在一个统一的语句中完成,这可以通过使用下面的 Java 语句来完成:
Calendar calendar = Calendar.getInstance(); // Declare a Calendar object named calendar and load it
您将在新代码中使用一个 Calendar 对象,使用下面的 Java 代码会有所不同:
Calendar watchFaceTime = Calendar.getInstance(); // Create/Load Calendar object named watchFaceTime
然后,您将使用 Calendar 访问日历对象的属性。通过属性常量。get() 方法调用,使用以下 Java 语句:
int hour = watchFaceTime.get(Calendar.HOUR);
int minute = watchFaceTime.get(Calendar.MINUTE);
int second = watchFaceTime.get(Calendar.SECOND);
日历对象可以定义为宽松或非宽松。宽松的日历对象接受的字段值范围比它生成的范围更广。例如,如果您使用宽松的 GregorianCalendar 对象,如果您使用 MONTH == APRIL,DAY_OF_MONTH == 31,它会将这一天解释为 5 月 1 日。
在这种情况下,非宽松的 GregorianCalendar 会抛出一个异常,原因是试图设置一个超出范围的数据字段值。当 Calendar 对象作为. get()方法调用的结果重新计算要返回的字段值时,您的 Calendar 对象将“规范化”它。例如,Android GregorianCalendar 将始终生成一个介于 1 和当前月份长度之间的 DAY_OF_MONTH 值,同时考虑闰年规则。Calendar 对象使用两个参数定义特定于位置的每周七天。第一个是一周的第一天,第二个是第一周的“最小天数”(1 到 7)。这些数字是在实例化日历对象时从位置资源数据中获取的。
位置特定的数据参数也可以由 Android 开发者通过利用该日历 API 中的方法来明确指定。如果您想更深入地了解日历对象(类)的所有细节,请使用以下 URL 阅读 Android 开发者页面:
http://developer.android.com/reference/java/util/Calendar.html
我想指出的最后一点是,这个 Calendar 类有两个构造函数方法: Calendar( ) 和 Calendar(时区区域设置)。如果抽象类不能实例化,为什么它会有构造函数方法?抽象类不仅可以有一个构造函数方法,而且它总是会有一个。如果你不指定一个构造函数,这个类将会有一个默认的,没有参数的对象构造函数,就像其他的类类型一样,比如嵌套类和匿名类。在匿名类的情况下,不可能指定一个构造函数,所以你总是得到默认的构造函数。构造函数方法总是使用子类来访问,所以您不能说Calendar calendar = new Calendar();,但是您可以通过使用Calendar calendar = Calendar.getInstance(); Java 语句来创建一个日历对象。
这个 Calendar 类是一个拥有构造函数方法的抽象类的优秀例子。您将通过调用 Calendar.getInstance()来创建您的 Calendar 对象,但是 Calendar 具有受保护的构造函数。
日历构造函数受到保护(不是私有的)的原因是它可以被子类扩展,比如 GregorianCalendar。因为 Calendar 的构造函数是受保护的,所以只有它们包中的其他类可以扩展 Calendar。从用于 Android 5 的 Java 7 开始,GregorianCalendar 类是唯一可以访问这两个日历构造函数的子类。
接下来,是时候仔细看看 Calendar 类的 GregorianCalendar 子类,以便您对这两个可行的 Calendar 类有完整的了解。您将在新代码中使用顶级 Calendar 类来消除 ProWatchFaceService 中不推荐使用的代码,但是,建议使用 GregorianCalendar 类(object)来代替 Time 类(object ),因此我将包含下一节以提供完整的主题范围。这样,您将对可以在应用中使用的两个 Android (Java 7)日历工具类有一个全面的了解。
GregorianCalendar 类:日期和时间的具体类
public****Gregorian Calendarclass 是 Calendar 的一个具体子类,它提供了一个在世界上大多数地方使用的标准日历表示。它包含在一个 java.util 包中,因此它的 java 类层次结构如下所示:
java.lang.Object
> java.util.Calendar
> java.util.GregorianCalendar
如果您想知道什么是具体类,它与抽象类有什么不同,那么将使用 Java new 关键字和构造函数方法实例化具体类,而抽象类不能使用 Java new (instance)关键字实例化,正如您现在所知道的。
我在 2014 ApressBeginning Java 8 Games Development标题中使用抽象类来创建游戏角色类,如果你想更详细地回顾这个概念的话。在 Java 中,具体的类被设计成子类,就像抽象类一样,但是它也可以被实例化,不像抽象类,它不能直接在你编译的(最终的)代码库中使用。
标准的公历支持两个“纪元”,公元前和公元。Android 实现处理单个不连续性,默认情况下,在大多数国家,该不连续性对应于公历的实施日期,即 1582 年 10 月 15 日,尽管在其他国家这可能会更晚。在 Android 中,开发者可以通过调用来更改这个“交接日期”。setGregorianChange( )** 方法。在最先采用公历的国家,1582 年 10 月 4 日将是 1582 年 10 月 15 日。因此,这个 Calendar 子类将正确地模拟这个日期异常。**
在这个公历切换日期之前,Android GregorianCalendar 类将实现儒略历日历。公历和儒略历的区别在于其闰年规则**。无论如何,儒略历每四年都会指定一个闰年。
对于那些不能被 400 整除的世纪年,公历会忽略每个偶数世纪年的闰年。
Android GregorianCalendar 类同时实现了公历和儒略历。通过使用指定的截止日期向前和向后推断当前规则来计算日期。
由于这个事实,GregorianCalendar 类可以用于所有年份,为 watch faces 应用生成有意义且一致的日期结果,还可以用于访问系统时间,精确到毫秒。
通过访问 GregorianCalendar 对象获得的日期只有从公元 4 年 3 月 1 日起才是“历史上准确的”。这是现代儒略历规则被采用的时候。在此日期之前,闰年规则是不定期适用的。请注意,在公元前 45 年之前,儒略历并不存在。在公历诞生之前,元旦是 3 月 25 日!
为了避免混淆,Calendar 子类将总是使用 1 月 1 日。如果需要,开发人员可以对公历 1 月 1 日到 3 月 24 日之间的日期进行手动调整。
GregorianCalendar 类从其 Calendar 超类中访问数据字段(属性或特性),我将在下面讨论。它们包括常量名称,如月、日、周、小时、小时、分钟、秒、毫秒、日、日、时、年、年、月、周、月。
从某种意义上说,您可以利用这种弃用,从使用 Time 类到使用 Calendar 类中的一个。通过一个日历对象访问系统时间,你将在基础设施中允许在你的表盘设计中显示一个很酷的日期,如果需要的话。
现在是时候开始在 ProWatchFaceService Java 代码中使用 Calendar 类了。
升级您的代码:日历和。getDrawable( )
要去掉删除线字体(删除代码),需要用 Calendar.getInstance()对象替换时间对象实例化,并升级。getDrawable(int)与。getDrawable(int,Theme)方法调用。
您将首先进行类替换,因为这是主要的更改,然后向。getDrawable()方法调用。这将与您之前的方法调用做同样的事情,但是它不会生成不推荐使用的代码突出显示。如您所知,null 告诉这个方法使用当前的主题对象定义。您在前面使用 XML 定义对此进行了定义。
升级时间类代码:使用日历类
在图 16-6 中可以看到,Android 时间类已经停止使用(已弃用),在 API 等级 22。首先,您需要将鼠标悬停在上面,看看是否有任何关于如何使您的 Java 代码完全更新的建议。正如你所看到的,在图 16-6 中,即使你点击了更多链接,建议工具提示中也没有太多的信息,这与弹出的黄色工具提示陈述的内容完全相同。这意味着你必须查看你的 Android 时间类文档。
图 16-6 。您可以在私有引擎类的顶部看到一个不推荐使用的时间类声明(引用)
将Time watchFaceTime; Java 对象声明语句改为使用 Calendar 类。这将使它成为一个Calendar watchFaceTime; Java 语句。
正如你所看到的,在图 16-7 中间突出显示的,你将需要使用 Alt+Enter 击键工作过程,并让 Android Studio 在你的 ProWatchFaceService 类的顶部为你编写导入语句。请确保删除时间类导入语句。
图 16-7 。在 watchFaceTime 声明中将 Time 类引用更改为 Calendar 类引用
接下来您需要做的是在 onCreate()方法中加载这个 Calendar 对象,使用您在上一节中学到的 Calendar.getInstance()结构。使用下面的 Java 语句,可以看到它在图 16-8 的中间以淡黄色突出显示:
watchFaceTime = Calendar.getInstance();
图 16-8 。在 onCreate()方法内将 watchFaceTime 日历对象设置为 Calendar.getInstance()
这将创建一个 watchFaceTime 日历对象,并加载一个有效的日历对象,在本例中,它将是一个 GregorianCalendar 子类。
通过这种方式,您可以设置您的代码,这样您就不必将Gregorian Calendar 转换为 Calendar,反之亦然,您可以在代码中使用 Calendar。因为 GregorianCalendar 是具体的类,所以这就是将要创建的内容(因为 Calendar 是静态类),这也是 Time 类中的一个建议用来替换 Time 的内容。
现在已经有了替换 watchFaceTime 时间对象的 watchFaceTime GregorianCalendar 对象,您需要更改。clear()方法调用和。setToNow()方法调用 Time 类,一些方法调用使用 GregorianCalendar 和 Calendar 类。其中包括一个. setTimeInMillis()方法调用、一个. get()方法调用和一个. setTimeZone()方法调用。现在让我们为时区接收器广播接收器这样做。
升级时区接收器。setTimeZone()方法
单击左边的加号(+)图标,打开您的 timeZoneReceiver 对象 结构。注释掉。清除( )和。setToNow()方法调用结构,如图图 16-9 所示,这样你就可以在以后使用不推荐使用的代码(如果你想使用的话,Time 类仍然可以工作)。
图 16-9 。在 BroadcastReceiver onReceive()方法中,使用。setTimeZone()方法,而不是。清除()
要更换这些,请使用**。setTimeZone( )** 方法,调用时区类**。getDefault( )** 方法,来替换.clear(intent.getStringExtra("time-zone")然后调用 invalidate( ) 方法来更新表盘时间 onDraw 逻辑。这将通过使用以下更新的 Java 结构来完成:
public void onReceive(Context context, Intent intent) {
watchFaceTime.setTimeZone( TimeZone.getDefault() );
invalidate();
}
接下来,让我们升级 onDraw()方法中的代码,因为这是下一个最重要的代码。使用新的日历,您将在方法的顶部获得当前时间。setTimeInMillis()方法调用。
升级 onDraw()方法:使用。setTimeInMillis( )
首先,让我们注释掉super.onDraw(watchface, rect);,因为您要完全替换 onDraw()逻辑,以及您的watchFaceTime.setToNow( ); Java 语句,因为您要用一个不同的 Calendar 类方法调用来替换它。键入 watchFaceTime GregorianCalendar 对象并按下句点键,然后开始键入”。setTi”并双击.setTimeInMillis(long milliseconds)选项,如图 16-10 中的下拉方法选择帮助器所示。
图 16-10 。在 onDraw()方法中,替换。带有. setTimeInMillis()方法调用的 setToNow()方法调用
在方法参数区内,输入系统类和句点,然后双击 currentTimeMillis( ) 选项,将其插入到您的 Java 语句中,如图图 16-11 所示。生成的 Java 语句应该如下所示:
watchFaceTime.setTimeInMillis(System.currentTimeMillis()); // Load Calendar object with current time
图 16-11 。在里面。setTimeInMillis()方法,访问 System.currentTimeMillis()方法来设置时间
现在,您的 GregorianCalendar 对象已经使用 system . current time millis()getter 方法加载了当前时间值,您将升级 hour、minute 和 second 整数变量,以便从日历常量中提取时间值,您在介绍 Calendar 类的章节中已经了解了这些常量。
加载时间变量:使用。get()方法
要从 watchFaceTime GregorianCalendar 对象中提取系统时间值,您将使用**。get( )** 方法调用并在日历中传递。您想要的数据的值常量,在本例中为小时、**分钟、和秒、**秒,这将为您提供其他 onDraw()逻辑分别定位时针、分针和秒针所需的值。
替换 watchFaceTime 时间对象的简单方法的 Java 语句调用时间对象的。小时( ),。分钟( ),以及。second()方法调用在图 16-12 的中突出显示,应该类似于以下三个 Java 编程语句:
int hours = watchFaceTime.get(Calendar.HOUR);
int minutes = watchFaceTime.get(Calendar.MINUTE);
int seconds = watchFaceTime.get(Calendar.SECOND);
图 16-12 。转换小时、分钟和秒整数以使用. get(日历。TIME_UNIT)方法调用
这里的一个优点是您还可以使用。get()用于其他日期或时区数据!
现在,您的 onDraw()方法已经更新为最新的代码,您可以继续升级 onVisibilityChanged()方法来使用。setTimeZone()。
升级 onVisibilityChanged()方法:。setTimeZone()
单击左边的加号(+)图标打开 onVisibilityChanged()方法结构并注释掉。清除( )和。setToNow()方法调用结构,如图图 16-13 所示,这样你就可以在以后使用不推荐使用的代码,如果你愿意的话。请注意,这与您在 BroadcastReceiver 对象的 onReceive()方法中所做的修改相同。
图 16-13 。在 onVisibilityChanged()方法中,更改。清除()和。将 ToNow()设置为。setTimeZone()
需要注意的是,您不需要包含 invalidate()方法调用,因为这已经在 onReceive()方法更新中完成了。
升级代码:使用。getDrawable(int,Theme)
让我们回到 onDraw()方法,升级 BitmapDrawable 代码以使用一个非预先声明的。getDrawable(int,Theme)方法版本通过在方法调用参数区域内添加一个逗号和一个空值。这是一个相当基本的 Java 语句升级,可以在图 16-14 中看到突出显示。新的 Java 语句应该如下所示:
if(firstDraw) {
if (roundFlag) {
watchFaceDrawable = watchFaceResources.getDrawable(R.drawable.round_face_test, null);
} else {
watchFaceDrawable = watchFaceResources.getDrawable(R.drawable.square_face_test, null);
}
watchFaceBitmap = ((BitmapDrawable) watchFaceDrawable).getBitmap();
firstDraw = false;
}
图 16-14 。升级。getDrawable()方法调用使用空值来指示 Android 继续使用当前主题
正如您在图 16-15 中看到的,您也需要对进行完全相同的升级。ensureModeSupport()方法中的 getDrawable(int)方法调用,需要该方法将此方法转换为仍然受支持的。getDrawable(int,Theme)版本。
图 16-15 。升级。getDrawable()方法调用 ensureModeSupport()方法也使用空值
对于用于 prowatchfacelow.png、prowatchfacebur.png、prowatchfaceamb.png 和 prowatchfaceint.png watchface resources 对象素材加载器 Java 语句的四个 BitmapDrawable 素材,也需要这样做。
这就完成了旧时间类以及旧时间类的不推荐使用的代码升级。getDrawable(int)方法调用。下一个合乎逻辑的步骤是测试这段代码,但是 Android Studio 扔给我们一个 1.2.1.1 升级曲线球!
解决由 SDK 升级引入的 IDE 问题
就在我准备开始测试的时候,我检查了更新,在我开始任何严肃的应用测试之前,我总是这样做。我发现 Android Studio 1.2.1.1 更新可用,如图图 16-16 所示。我再次经历了如图 16-1 到 16-4 所示的步骤。
图 16-16 。另一个火速 Android Studio 从 1.2.0 升级到 1.2.1.1 需要再次升级过程
我将补丁应用到 Android Studio (IntelliJ 加上 Android SDK 插件),然后使用 Android SDK 管理器来确保我将所有需要的 API、工具、文档、系统映像等升级到位。然后我重启了 Android Studio,推出了新的 1.2.1.1 版本。
正如你在图 16-17 中看到的,我遇到了一个相当大的问题。这显然不是我的错,因为我只修改了 Java 代码,其他什么都没做。我在 IntelliJ 的右上角收到一条消息,问我是否想**将项目迁移到 Gradle?**因为这个项目一直是一个 Gradle build 系统项目,我需要找出是什么导致了这个问题。这促使我将这一部分添加到我如何发现这一点的章节中,因为这很可能在某个时候发生在你身上。因此,在这里我将深入探讨 Gradle 构建系统,IntelliJ 中集成的项目,以及如何使用 Invalidate 和 Restart,导入项目,以及最激进的解决方案,如何从头开始创建您的项目。在我解释了如何解决这个问题,并把这个项目变成 Gradle build 系统兼容性,1.2.1.1 升级似乎已经改变了。
图 16-17 。升级后重新启动时,项目不再认为它正在使用 Gradle 构建系统
我将向您展示我尝试事情的顺序,从必要的 Gradle build 定义升级,到使用 Invalidate and Restart ,到导入项目工作流程,到完全重新创建一个 Android Wear 项目。
升级梯度文件 :添加构建定义节
我尝试修复 Migrate Project to Gradle warning 的第一件合乎逻辑的事情是升级 build.gradle (wear、mobile 和 Project)构建定义文件。
正如你在图 16-18 中看到的,我添加了一个 buildscript 定义部分,包含存储库和依赖项的子部分,显示在 wear 定义文件的顶部,以及指定 Java 7 的编译选项,和指定 Java 和资源位置的源集,显示在底部。
图 16-18 。升级 wear gradle.build 定义以包括 buildscript、compileOptions 和 sourceSets 部分
接下来,我将这些相同的部分添加到移动 gradle.build 文件中,如图图 16-19 所示。我升级了我的编译依赖项并增加了几个。
图 16-19 。升级 mobile gradle.build 定义以包括 buildscript、compileOptions 和 sourceSets 部分
因为我不知道 WatchFaces API 应该使用哪些编译依赖项,所以我使用了https://github.com/googlesamples/android-WatchFace作为谷歌内部开发团队发现适用于 1.2.1.1 版本的指南。这些编译依赖项将适应您决定添加到 WatchFace API 设计中的任何特性。需要注意的是,如果不使用未使用的编译依赖项,它不会导致任何问题。
GitHub WatchFace 代码不再包含根(ProAndroidWearable)Gradle . build 文件,所以我简单地使用下面的语句将我的从 Gradle 1.0 类路径升级到 1.2.3 类路径,如图 16-20 所示:
buildscript {
repositories { jcenter() }
dependencies { classpath 'com.android.tools.build:gradle:1.2.3' }
}
图 16-20 。升级根 gradle.build 的类路径依赖项以使用 com.android.tools.gradle:1.2.3
新的 gradle.settings 文件引用了 Wearable 和 Application 文件夹:
include ':Application', ':Wearable'
在我重启 Android Studio 后,我打开了 AndroidManifest,正如你在截图左侧的图 16-21 中看到的,引用错误仍然存在。这些错误导致运行/调试配置对话框无法运行(构建、执行)项目,因此无法对其进行测试,正如你在图 16-21 右侧看到的。
图 16-21 。升级 Gradle 构建系统定义没有修复 AndroidManifest 引用问题
由于升级 Gradle 配置文件没有解决这个问题,我尝试的下一件事,也是下一个最简单的解决方案,是使用 Invalidate 函数,它位于 File 菜单下。
如果这不起作用,尝试下一个最困难的解决方案,即导入项目,然后看看它是否可以构建和运行。如果这不起作用,您将不得不从头重新创建项目,这将修复任何 Android Studio (IntelliJ 14)文件引用问题。
使用无效并重启:重建项目结构
在 Android Studio 中点击文件菜单,如图图 16-22 所示。选择失效缓存/重启菜单选项,点击失效重启。
图 16-22 。使用文件修复项目引用使缓存失效并重启工具
这个想法将会消失并重新启动。打开 AndroidManifest,您将看到红色引用错误是否已经消失。我的 AndroidManifest.xml 仍然显示红色的错误高亮,这可以在图 16-21 中看到。
下一个最困难的工作过程包括将项目移动到备份文件夹,像第一次一样启动 IntelliJ,没有新项目,并使用 Import Project 特性将代码和 XML 从一个已经损坏的项目导入到一个没有这些引用错误的新 IntelliJ 文件和项目层次结构中。
使用导入项目
我用来导入这个项目的工作流程是备份项目,使用剪切和粘贴,如图图 16-23 所示。我右键单击项目文件夹,并使用剪切将其从 AndroidStudioProjects 文件夹中删除,然后右键单击C:/Back-Up/Android studio projects文件夹,并使用粘贴将整个项目层次结构文件夹位置移动到我的 C:\驱动器上。
图 16-23 。使用剪切和粘贴清空 AndroidStudioProjects 文件夹,将项目移动到 C:\Back-Up
这将使 Android Studio 认为当前没有项目在使用,因为 AndroidStudioProjects 文件夹中什么也没有。
这将产生一个包含导入项目选项的 IntelliJ 对话框。这就是我需要用来创建一个新的 IntelliJ 项目基础设施的东西,它将有望修复这个素材引用问题。
图 16-24 显示了备份到我的 c 盘的 ProAndroidWearable 项目。
图 16-24 。我使用粘贴创建了一个备份\AndroidStudioProjects 文件夹,将 ProAndroidWearable 移动到那里
一旦您的项目文件夹层次结构被备份(并对 IntelliJ 隐藏),启动 Android Studio,您将获得原始菜单,允许您启动一个新项目,打开现有项目,导入代码示例,从版本控制中签出项目,并导入项目。
选择导入项目选项,如图图 16-25 所示,然后选择C:/Back-Up/androidstudio projects/ProAndroidWearable/gradle . build文件,点击确定按钮。你会看到一个构建项目进度条,新项目最终会在一个空的 Android Studio IntelliJ IDEA 中打开。
图 16-25 。启动没有项目的 Android Studio,使用导入项目,并选择 build.gradle,重建项目
右键单击项目层次结构的磨损组件(文件夹)中的 AndroidManifest.xml 文件,并使用跳转到源代码选项来检查该文件。
正如你在图 16-26 中看到的,我的 AndroidManifest XML 文件中仍然有引用错误高亮显示。它们与我之前遇到的引用错误不同,我还在 IDE 的右上角发现了一个新的框架检测到的警告,以及一个配置链接。这将打开一个名为设置框架 的对话框,在图 16-26 中突出显示,这是最初破坏我的项目的地方。无论您选择这些下拉菜单选项中的哪一个,类型还是目录,最终结果都是一样的。在我的例子中,这等同于 XML 文件中不同的 AndroidManifest 引用错误,所以看起来我将重新创建项目!
图 16-26 。在 Android Studio 第二次启动时,我收到了框架检测警告,这改变了项目
正如你在图 16-27 中看到的,这个新项目现在有着我导入的项目所具有的相同问题,所以我需要创建一个新的 Android Wear 项目,并将我所有的 Java 代码、XML 标记和素材复制到其中。
图 16-27 。AndroidManifest 现在有同样的引用错误我以前有过,所以这是什么打破了这个项目
因为最初的项目是在 Android Studio 1.0 下创建的,IDE 现在在 1.2.1.1,所以可能会有一些新功能,可能与 WatchFaces API 有关,可以用来简化 Java 编码或 XML 标记任务。我将保持本书前 15 章的代码不变,因为它们向您展示了如何从头开始创建 Watch Faces 应用,因此您在学习如何修复代码方面拥有最大的学习经验。
从头开始重新创建项目:复制代码和素材
剪切并粘贴 AndroidStudioProjects 文件夹下的任何子文件夹,就像你在上一节和图 16-25 所示的启动菜单中所做的那样,然后选择开始一个新的 Android Studio 项目选项。它将给出如图图 4-16 所示的对话框,在这里您将使用相同的 ProAndroidWearable 和wearables.android.pro.com条目。确保该项目位于用户文件夹和 AndroidStudioProjects 子文件夹中。点击下一个按钮后,会出现一个目标 Android 设备对话框,如图图 16-28 所示。该对话框也可以在图 4-17 中看到,使用旧的磨损 API 等级。
图 16-28 。为手机和平板电脑选择 API 等级 18,为磨损组件选择 API 等级 21
为手机和平板电脑应用选择 Android 4.3 API 18 ,为 Wear 应用组件选择 Android 5.0 API 21 。然后点击下一步按钮,进入添加活动穿对话框,如图图 16-29 所示。如果您想查看该对话框的旧版本,请参考图 4-19 。
图 16-29 。选择 WatchFace 选项,让 Android Studio 编写您的 WatchFace API 代码基础架构
注意,这个对话框中有两个选项是 Android Studio 1.0 中没有的:显示通知和 WatchFace API。我将选择 WatchFace API 选项,向您展示 Android Studio 将为您编写 WatchFace API 代码,因为您将很快替换它。
在服务名数据字段中,输入 ProWatchFaceService Java 类名,在下拉菜单中选择您的模拟 WatchFace 样式选项,如图 16-30 所示,然后点击完成创建您的项目。
图 16-30 。将您的服务命名为 ProWatchFaceService ,选择模拟 WatchFace 样式,然后单击 Finish
构建完新项目后,IntelliJ IDEA 将会打开,使用标准的 bootstrap WatchFace API 代码,该代码远没有您在本书过程中开发的代码那么详细或复杂。我还使用了更具描述性的对象和变量名称,这样您就可以直观地看到这些对象和数据字段在整体上对 WatchFace API 代码库做了什么。
需要注意的是,这些代码都不会用到!我在这里做的是使用这个新的项目结构,主要是新的**。IML** ,或者 IntelliJ 标记语言项目结构定义,来解决我遇到的问题。所有的 Java 代码、XML 和素材都将被复制过来。
我注意到在 bootstrap 代码库中,不赞成使用的 Time 类还没有被 Calendar 类代码替换,你可以看到在图 16-31 顶部附近用黄色突出显示。我猜他们会在 Android Studio 1.3 更新中实现这一点,预计会在 2015 年晚些时候发布,希望在你看到这本书的时候。
图 16-31 。Android Studio 为您创建了基本的模拟 WatchFace 服务类和所有的基本方法
这些快速更新真的越来越让人受不了了!。
我做的第一件事是重新启动 IDE,重新构建项目,并确保一切都在 Gradle 控制台选项卡中。我很高兴我采取了这一步,因为正如你在图 16-32 中看到的,这个引导项目结构的 Gradle 控制台中存在一个错误!让我们点击打开文件编码设置链接并立即修复它。在项目编码下拉列表中,选择 UTF-8 ,点击确定按钮,为整个 Wear 项目设置一个建议的 UTF-8 项目编码格式。
图 16-32 。使用文件编码对话框(右)修复一个 Gradle sync 项目的编码问题(左)
正如你在图 16-33 中看到的,在我点击右上角显示的 Gradle 项目刷新图标后,我的 Gradle 控制台现在没有任何错误或警告信息。我还向您展示了如果您想再次回到图左侧的文件编码对话框,您将使用的菜单序列。这是使用文件设置
编辑器
文件编码完成的。
图 16-33 。打开(点击)Gradle 选项卡(右)并使用刷新 Gradle 项目图标清除 Gradle 控制台
我将按照您在本书中重建项目的顺序进行操作,因此您在第五章中做的下一件事就是为项目创建 AVD 仿真器基础设施。我查看了运行/调试配置对话框,我在第五章中创建的圆形和方形 AVD 仿真器仍然是 Android Studio 的一部分,这很有意义,因为它们独立于项目,所以让我们继续。
第七章介绍了 gradle.build 和 XML 定义文件,现在让我们把它们放在适当的位置。从 ProAndroidWearable 文件夹、wear 和 mobile 文件夹中复制 build.gradle 文件文本,并替换新引导项目的 build.gradle 文件文本。wear/RES/XML/watch _ face . XML文件已经就绪,所以将备份 wear/res/values 文件夹中的 strings.xml 文件中的值复制并粘贴到新项目wear/RES/values/strings . XML文件中,替换您的 bootstrap < string >值。对您的mobile/RES/values/strings.xml中的 strings . XML 值执行相同的操作,以便为 WatchFace Companion 应用准备好颜色数组和值。
接下来我们来转移一下活动 UI 设计。在你的 mobile/res 文件夹中创建 /layout 文件夹,然后创建一个activity _ pro _ watch _ face _ config . XML文件。复制并粘贴您的配置活动 UI 定义。在替换 AndroidManifest.xml 文件之前,您需要复制清单文件访问的 PNG 素材,否则您将得到错误高亮显示。
幸运的是,PNG 文件都在 wear/res/drawable-hdpi 文件夹中,所以接下来,您需要将这些文件复制并粘贴到您的新项目中,粘贴到 res/drawable-dpi 文件夹以进行缩放,或者复制到 res/drawable-nodpi 文件夹以供固定使用。
有趣的是,当我研究这些新的 Android 1.2.1 和 1.3 WatchFaces API 升级和更新时,我发现了一个新的推荐 WatchFaces 背景位图图像大小为 400 像素,并且建议图像放在**/wear/RES/drawable-nodpi/**文件夹中,因此我将我的位图素材粘贴到这个文件夹中。我的猜测是新的 400 像素推荐,因为新的华为智能手表采用了 400 像素的屏幕。这意味着,一旦 480 像素的智能手表问世,那将是在 2015 年或 2016 年,WatchFaces 位图的这一推荐 NODPI 分辨率将变为 480。
我注意到的另一件事是 res/drawable-dpi 文件夹已经被替换为 res/mipmap-dpi 文件夹。在 Android 4.3 中引入了 mipmap 功能用于图标,MIP map 起源于 3D。使用预先优化的 PNG32 图像预先计算这些图像以适合 Android DPI 图标分辨率,每个 png 32 图像都是从同一应用图标图像的最高分辨率版本重新采样的较低分辨率表示。我将只为你的应用图标使用这些文件夹,并为你在 Wear 应用中使用的 BitmapDrawable 素材使用/drawable 文件夹。
因为您的 AndroidManifest.xml 文件还引用了您已经创建的 Java 类,您将需要使用 IDEA New Java class 特性来创建这些 Java 类,然后将您的 Java 逻辑复制并粘贴到这些 Java 类中。
让我们先从你的ProWatchFaceService.java文件开始,因为这个 Java 类是由新项目系列对话框创建的。将代码复制并粘贴到 ProWatchFaceService 选项卡中,替换引导代码。接下来右键单击**/wear/Java/com . pro . Android . wearables . proandroidwearable文件夹,使用新建 Java 类对话框创建 config listenerProWatchFaceConfigListenerService.java**文件。然后将你在书中写的 Java 代码复制粘贴到你的 ProWatchFaceConfigListenerService 标签页,替换空的 Java 类代码。在创建 ProWatchFaceUtility.java 类文件之前会有一个错误,所以接下来让我们开始吧。
右键点击**/wear/Java/com . pro . Android . wearables . proandroidwearable文件夹,使用新建 Java 类对话框创建你的工具类ProWatchFaceUtility.java**文件。然后将您在本书中编写的 Java 代码复制并粘贴到 ProWatchFaceUtility 选项卡中,替换空的 Java 类代码。最后,让我们添加移动组件的 Java 代码。
右键点击**/mobile/Java/com . pro . Android . wearables . proandroidwearable文件夹,使用新建 Java 类对话框创建 ConfigActivity 类ProWatchFaceCompanionConfigActivity.java**文件。然后将该类的 Java 代码复制并粘贴到 prowatchfaceconnectionconfigactivity 选项卡中,替换空的 Java 类。现在,您可以复制并粘贴 wear 和 mobile AndroidManifest.xml 文件。将您的图标引用更改为使用带有这行代码的 mipmap:
android:icon="@mipmap/ic_launcher" // Replace the @drawable reference with an @mipmap reference
现在mobile Android manifest . XML已经被复制过来,只有一个引用更改,是时候复制更复杂的 wear AndroidManifest 了,它可能会有一些升级,因为它是在 Android Studio 1.0 下创建的。
除了 mipmap 引用更改之外, wear AndroidManifest.xml 是无错误的,我还添加了一个 < uses-sdk > 标签,在清单顶部的<清单>父标签内指定 API 级别 21 。这可以在图 16-34 的顶部看到,并使用了以下 XML 标记:
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
图 16-34 。添加一个指定 API 级别 21 的< uses-sdk >和另一个用于 Google Play 服务的<元数据>标签
我还添加了一个 <元数据> 子标签,就在</应用>结束标签之前,为这个应用定义一个谷歌移动服务(GMS)版本。这可以在图 16-34 底部用黄色突出显示,并使用以下 XML 标记:
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
接下来我做了一个 Run Run Wear,项目构建再次使用 Gradle build 系统工作,所以我又有了一个工作想法,尽管这需要一个极端的工作过程才能实现!
这个故事的寓意是:Android 不仅仅是 Java 或 XML
重要的是要记住,如今的编程是一个移动的目标,涉及多个集成的组件,如 IDE (IntelliJ)、构建系统(Gradle)、SDK (Android Studio)、编程语言(Java 7)、标记语言(XML)、新媒体编解码器(MPEG4、JPEG、PNG、MP3、GIF、WebM、WebP 等)。)、技术 API(WebKit、OpenGL、SQLite)和操作系统(Windows、Linux 和 Mac)平台,而这只是等式中 Android 应用开发的一面,我在本书中对此进行了介绍。
在设备方面,你也有一个 Dalvik 虚拟机(DVM)或 Android 运行时(ART)引擎、Android 操作系统和 Linux 64 内核,因此开发和发布任何类型的 Android 应用,无论是通用的 Android 还是更专业的 Android Wear(本书)、Android TV、Android Auto 或 Android Glass(ApressPro Android IoT本书),无论如何都不会是在公园里散步!
所有的组件都由数百名程序员维护,他们在多家公司(例如 Google 和 Oracle)和开源组织(例如 MPEG LA、Khronos、Apache 和 W3C)工作。我们甚至经历过一个全新的、100%由 Android Studio 生成的项目出现 Gradle build 系统错误,必须立即修复!
摘要
在本章中,您学习了如何升级不推荐使用的代码,以使用新的、推荐的类和更新的 API 类的方法。我还向您展示了如何修复非代码相关的问题,在本例中,IntelliJ IDEA 相关的问题将会由于 OS API 升级而不可避免地出现。
这需要您了解一个日历超类,及其子类 GregorianCalendar 类,以及您需要使用的新方法来替换 Time 类及其最初用于实现 Watch Faces API 的方法。如果你不介意在你的想法中删除代码,被否决的类和方法仍然可以工作。
您还学习了如何使用更高级的 getDrawable(int,Theme) 方法调用,Android 不赞成使用更简单的 getDrawable(int)版本,在我看来,这是为了迫使开发人员将主题融入他们的代码使用中。
在下一章中,您将了解其他 Android APIs,以及一些其他很酷的东西,如 GPS 位置感知和语音识别功能,您可以将它们添加到 Wear 应用中。****
十七、Android 物联网 API 的未来:Android 电视、眼镜、汽车和穿戴
因为不可能涵盖所有的 Android,或者任何可用于 Android 的利基硬件设备 SDK,所以我想我会给你留一章,给你一些关于在你的 Android 硬件设备开发之旅中接下来要看什么的想法。
Android 正在智能地组织这些 API,将 API 功能与硬件产品流派或类型相匹配,例如运行 Android TV 的互动电视集 (iTV 集),运行 Android Glass 的智能眼镜,虽然没有发布但显示在新项目对话框中(参见图 16-28 ,或者运行 Android Auto 的汽车仪表盘,还有运行 Android Wear 的智能手表
我将在明年写一本关于 Android IoT 的书,这本书将涵盖这些其他 API,以及同时可能实现的任何其他物联网 API。随着其他消费电子类型越来越受欢迎,并被主要硬件制造商采用,Android 将发布其他定制的 API。
例如,许多制造商都有虚拟现实耳机,可以运行 Android VR API。Android 驱动的机器人,甚至无人机,越来越受欢迎,所以一个 Android 机器人 API 将允许开发者创建一个定制他们的机器人或无人机的应用。另一个增长的领域是家用电器,所以看到一个 Android Home API 不要惊讶。在这一章中,我将讨论一些其他的 Android APIs,以及一些你应该实现的 Wear 的其他特性。
高清和 UHD 安卓电视:磨损的对立面
Android TV SDK 解决了与 Android Wear SDK 相反的消费电子产品尺寸范围,Android Wear SDK 针对小方形或圆形屏幕进行了优化。Android TV 旨在为大宽屏显示器开发应用,这些显示器具有真正的高清分辨率,或 1920 x 1080 分辨率,或更新的 ?? UHD 分辨率,或 4096 x 2160 ?? 分辨率。这些显示器的对角线尺寸从 60 到 80 英寸不等,而智能手表的对角线尺寸从 1 到 2 英寸不等!
合乎逻辑的 Android 电视应用类型包括 2D 和 3D 游戏、直播内容流、电视播放、互动电视和内容搜索。
Android TV 应用需要在 res/drawable-xhdpi 项目文件夹中有一个320 x 180像素的主屏幕横幅,并且应该包括识别应用的本地化文本。这个横幅在 AndroidManifest.xml 应用定义中声明和引用,使用以下参数:
<application android:banner="@drawable/png_banner_name" >
// Nested Tags for the TV Application will go in here
</application>
打算在 iTV set 设备上运行的 Android TV 应用将需要在 AndroidManifest 中为 Android TV API 声明一个 iTV 启动器活动,使用 <意图过滤器> 子标签中的CATEGORY _ LEANBACK _ Launcher常量。
该意图过滤器将用于识别与电视兼容的 iTV 应用。这是 Google Play 将 iTV set 应用正确分类到商店的 Android TV 应用部分所必需的。该意图还标识了当用户选择 iTV 主屏幕上的图标时要启动的活动。以下 XML 标记显示了如何在清单中编写意图过滤器:
<application android:banner="@drawable/banner" >
<activity android:name="com.example.android.MainActivity" android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.android.iTVsetActivity"
android:label="@string/itv_app_name"
android:theme="@style/Theme.Leanback">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
</application>
Android 有一个支持 iTV 用户界面设计的库,叫做 V17 后倾库 。这为 iTV 活动提供了标准主题,称为主题。正如你在上面的 XML 标记中看到的那样。
主题。Leanback android: theme 参数可以为 iTV set 应用实现一致的视觉 UI 风格。建议大多数 iTV 应用使用这种向后倾斜主题。主题。Leanback 应与来自 V17 Leanback 库的 iTV UI 设计类一起使用,该库也支持电视媒体播放类。
其他可用于 Android TV 开发的类包括 V7 RecyclerView 库 ,它提供了用于内存高效管理和显示长列表的类。V17 向后倾斜库中的许多类依赖于 V7 RecyclerView 库中的类。还有 V7 CardView 库 ,它为开发人员提供了额外的用户界面小部件,用于显示包含媒体项目图片和媒体项目文本描述的内容信息卡。V7 向后倾斜库也依赖于 V4 支持库,所以就像 Wear 应用一样,许多旧版本的支持库可能需要包含在 Android TV 应用的 build.gradle dependencies 部分中。
您还需要声明您的应用在 Android Manifest XML 文件的 < manifest > 级别使用了一个向后倾斜的用户界面。如果您将此必需的 <用途特征> 属性设置为真值,则 Android TV 应用将仅在实现 Android TV 向后倾斜 UI 的 iTV set 设备上运行。对此的 XML 标记如下所示:
<manifest>
<uses-feature android:name="android.software.leanback" android:required="true" />
// Other Manifest Child Tags will go in here
</manifest>
如果您正在开发运行在手机、可穿戴设备、平板电脑、电子书阅读器等设备上的应用,除了运行在 Android TV 上之外,您将使用以下标记将这个必需属性设置为一个 false 值:
<manifest>
<uses-feature android:name="android.software.leanback" android:required="false" />
// Other Manifest Child Tags will go in here
</manifest>
你打算在 iTV 上运行的 Android 电视应用使用遥控器,不依赖触摸屏进行输入,至少在主要制造商发布触摸屏 iTV 之前是这样,他们可能会在某个时间点发布触摸屏 iTV。
为了向您的用户阐明触摸的使用,您的 iTV 应用清单需要声明此Android . hardware . touch功能不是必需的。这是通过使用 < uses-feature > 标签内的 false 设置来完成的。下面的 XML 标记显示了如何将它包含在 Android 清单应用设置和特权声明文件中:
<manifest>
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
// Other Manifest Child Tags will go in here
</manifest>
此设置会将您的 iTV 应用识别为能够与 Android TV 设备配合使用,并且该应用需要被视为 Android TV 应用并在 Google Play 中的正确 iTV 区域列出。
需要注意的是,目前必须以这种方式声明 iTV 应用,也就是说,在您的应用清单中不需要触摸屏支持,如本示例代码所示,否则您的应用无法出现在电视设备下的谷歌 Play 商店中。
除了互动电视节目,最受欢迎的互动电视应用之一肯定是互动电视游戏。与为纵向设计的智能手机应用或为方形和圆形屏幕设计的智能手表应用不同,Android TV 应用是横向设计的。高清电视(1920×1080)的正常纵横比是 16:9,但具有 2160×1080 分辨率的超宽 16:8 WHD 屏幕也出现了。
与大多数通过网络共享的多人游戏(使用自己的显示器、系统内存和处理器)不同,iTV 游戏不需要任何网络,从而减少了延迟,但它们也共享相同的屏幕、系统内存和多核处理器,因此它们需要精心设计和优化。共享屏幕也可能带来一些独特的多人游戏设计挑战,因为所有玩家都可以看到一切,这在设计依赖玩家专有(未公开)游戏策略信息的纸牌游戏和类似策略游戏时尤其困难。
一个可能的解决方案是一个配套应用,也称为第二屏幕显示应用。这将在蓝牙手机或平板电脑上运行。这将使玩家能够隐藏游戏策略信息,只有他们可以查看,使用第二个屏幕蓝牙连接的应用。
Android TV 主屏幕列出的游戏与常规的 iTV 应用不同。要使一个游戏出现在游戏列表中,请在 Manifest 标签中将 android:isGame 属性设置为“true ”,使用以下标记:
<application android:isGame="true" >
为了告知用户游戏需要或支持游戏控制器,您必须在清单文件中包含以下条目:
<uses-feature android:name="android.hardware.gamepad" />
如果你的 iTV 游戏使用,但不是绝对需要游戏控制器,你将额外包括一个 android:required="false" 参数在< uses-feature >标签中。这个 XML 标记看起来如下所示:
<uses-feature android:name="android.hardware.gamepad" android:required="false" />
Android Auto:汽车仪表盘的 Android 应用
Android Auto SDK (API)平台使您能够扩展您的应用,以便与使用 Android Auto 的汽车控制台系统一起工作。这些 Android 汽车控制台设备 为汽车应用提供基本的 Android 用户界面。这些汽车应用将允许用户在上班、购物、娱乐、约会或公路旅行的路上随身携带应用功能。
就像 Android Wear 一样,适用于 Android 自动控制台的应用可以在蓝牙设备上运行,比如手机或平板电脑。该应用通过特定的 API 与仪表板的 Android 控制台进行通信,该控制台为专为汽车环境内使用而设计的联网 Android Auto 应用提供 Android Auto 用户界面。
Android Auto 应用用户通过语音识别调用的操作和车辆输入控制(如仪表板内的触摸屏,甚至是物理仪表板硬件按钮)与应用和服务进行交互。
Android Auto SDK 目前支持两种类型的应用:音频应用,允许用户在汽车立体声环境中浏览、预览和播放音乐以及语音音频内容,如有声读物;或者消息应用,接收来电通知,使用文本到语音合成大声朗读消息,或者使用汽车或仪表板内置的麦克风通过汽车中的语音输入发送回复。
您可以配置当前为手机和平板电脑开发的音频或消息应用 ,使其在 Android Auto 下工作,而不必适应特定车辆的硬件差异。要使这些应用能够使用 Android Auto,应用必须使用 Android 5.0 API 级别 21 或更高的 targetSdk 设置。应用清单必须声明它使用的汽车功能,如音频播放或消息服务。这与您在 Android Wear 中为 Watch Faces API 执行此操作的方式非常相似。
在应用清单中,您应该提供对 Android Auto XML 配置文件automotive _ app _ desc . XML的引用,您将在 /res/xml 文件夹中创建该文件,就像您对 res/xml/watch_face.xml 文件所做的那样。
为此,您将在<应用>父标签中使用一个 <元数据> 子标签。这个<元数据>标签通过使用以下 xml 标记引用了设置为“com . Google . Android . GMS . car . application”的 android:name 参数和设置为“@xml/automotive_app_desc”的 android:resource 参数:
<application>
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
// Other Application Child Tags will be nested inside of the parent <application> tag
</application>
您将使用放置在项目 XML 资源目录中的 XML 文件来指定汽车应用使用的 Android Auto 功能,您可能需要创建(res/xml)该文件,就像您为 Wear 所做的一样。
要声明一个用于 Android Auto 的音频应用,创建名为 automotive_app_desc.xml 的文件,将其保存在 project res/xml 文件夹下,并确保 xml 定义包含 < automotiveApp > 和 <使用> 标签:
<automotiveApp>
<uses name="media" />
</automotiveApp>
子标签声明了一个应用打算使用的 Android Auto 特性。如果您的应用需要使用多个 Android Auto SDK 功能,将会添加多个标签。name= " "属性用于指定应用将要利用的功能。
支持的常量包括媒体,用于在车内播放音乐(启用音频应用),以及通知,用于通过汽车概览屏幕显示消息通知,允许用户选择要大声朗读的消息,并允许用户通过语音输入对消息做出响应(启用 Android 自动消息应用)。
对于这个媒体常量,Android 自动控制台设备期望连接到媒体浏览器服务来浏览音轨列表。您应该在清单中声明这个 MediaBrowserService 子类。这将允许汽车的仪表板设备硬件发现服务并连接到应用。
声明 MediaBrowserService 对象以及用于启动它的 Intent 对象所需的 XML 标记看起来很像下面这样:
<application>
<service android:name=".ProAutoMediaBrowserService" android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
// Other Application Child Tags will be nested inside of the parent <application> tag
<application>
正如你所看到的,应用提供的用于浏览音轨的ProAutoMediaBrowserService对象必须扩展 AndroidMediaBrowserService类,这将成为 ProAutoMediaBrowserService 类的超类。
Android 汽车硬件设备也使用 Intent 对象作为通知常量,以表明用户已经阅读或回复了应用提供的消息。应用定义阅读或回复消息的意图类型,并将此信息添加到消息通知中,以便仪表板系统可以在用户采取这些操作之一时通知应用。
您需要为应用定义一个 heard 动作意图和一个 reply 动作意图。这些由 BroadcastReceiver 类使用,这些类处理应用清单定义文件中定义的意图。实现这些意图的 XML 标记示例及其关联的 BroadcastReceiver 对象应该如下所示:
<application>
<receiver android:name=".ProAutoMessageHeardReceiver">
<intent-filter>
<action android:name="com.myapp.messagingservice.PRO_AUTO_ACTION_MESSAGE_HEARD"/>
</intent-filter>
</receiver>
<receiver android:name=".ProAutoMessageReplyReceiver">
<intent-filter>
<action android:name="com.myapp.messagingservice.PRO_AUTO_ACTION_MESSAGE_REPLY"/>
</intent-filter>
</receiver>
</application>
在这个 XML 中,“ProAutoMessageReadReceiver”和“ProAutoMessageReplyReceiver”是您编写来处理您的意图的 BroadcastReceiver 子类的名称。您可以选择将任何您喜欢的常量定义为操作对象名称。确保所有操作名称都是完全唯一的。
构建用于 Android 自动控制台设备的通知将需要 Android V4 支持库中的类。使用 Android SDK 管理器将 Extras > Android 支持库更新到版本 9 或更高版本,并将 Extras > Android 支持库更新到版本 21.0.2 或更高版本(如果有更高版本可用)。
在更新了这些 Android 支持库之后,使用下面的 Groovy 代码,通过将这个依赖项添加到 Android Auto 应用的 build.gradle 文件中,将这些库导入到 Android Studio 开发项目中:
dependencies { compile 'com.android.support:support-v4:21.0.2' }
Android Auto SDK 使用标准的用户界面和用户交互模型,可在所有控制台上工作,因此您无需担心不同的仪表板硬件。Android 非常重视司机分心的问题,它有特定的设计要求,以使汽车应用有资格在谷歌 Play 商店销售。
当用户连接到 Android Auto 时,他们首先会遇到一个概览屏幕,该屏幕根据用户的位置和时间显示上下文卡片。用户可以使用这个屏幕来查看来自消息应用的通知,并选择消息来通过语音输入发送响应。点击活动栏中的耳机图标,查看安装在手持设备上的音频应用。在用户选择音频应用之后,显示器显示该主要应用 UI。主应用 UI 中的媒体控制卡最多支持四个主操作,以及四个辅助操作(在溢出栏上)和返回操作。
Android Auto 使用抽屉 UI 范例进行列表浏览操作,汽车控制台的显示器将使用抽屉转换显示数据列表的内容。对于媒体(音频)应用,自定义的列表 UI 显示应用中媒体服务提供的媒体容器和音频文件。您可以使用列表项目的图标来自定义抽屉中的数据条目。
标准的 Android Auto 用户界面描述了白天和夜间使用的不同配色方案。Android Auto 平台提供状态(白天或夜间)变量,并自动设置该状态。
就 Android 自动颜色主题而言,你的应用可以使用材质主题的调色板中的颜色。材质调色板包含 500 种原色和强调色,可用于插图或开发您的应用颜色方案。它们被设计成彼此和谐地工作,可以在下面的 Google URL 上看到:
http://www.google.com/design/spec/style/color.html
该调色板从 20 种原色开始,即白色、红色、绿色、蓝色、紫色、粉色、靛蓝、青色、蓝绿色、石灰、黄色、琥珀色、橙色、灰色、蓝灰色、棕色、深橙色、深紫色、浅绿色和浅蓝色。如果你认为黑色是一种颜色,实际上总共有 21 种颜色。
其他 480 种颜色填充这个光谱,为 Android 或 WebKit 创建一个完整且可用的调色板。谷歌建议使用 500 种颜色作为你的应用的主要颜色,然后使用其他自定义颜色作为你的强调色。您的 Android Auto 应用将被允许为系统调色板指定两种颜色。这些是在 Android 操作系统中使用 colorPrimaryDark 和colorcentnext数据字段常量定义的。
Android Auto 平台旨在最大限度地提高安全性,减少任何干扰,这个调色板只是这个过程的一小部分。
Android Auto 应用的用户界面需要快速且易于导航,每个 Android Auto 应用都必须通过正式审查,并满足最低安全和驾驶员注意力分散的要求和法规。Android 汽车应用需要完全可预测,并具有内在的直观性,以确保司机始终关注道路,因为生命可能受到威胁。
您的应用需要为 Android Auto 定制。如果没有针对驾驶体验对用户界面、可用性和设计进行调整,就不要在 Android 清单 XML 文件中指定 Android 自动兼容性。复杂的操作,如创建帐户、登录,甚至创建播放列表,都应该在手机或平板电脑上进行,而不是在自动显示器上进行。
Android 汽车应用设计应符合本平台在其汽车平台 UI 中实现的原则,包括简明的 UI 设计和可预测的应用功能,具有持续连接的用户体验,并为用户提供集成的应用环境。
谷歌眼镜:为智能眼镜开发应用
谷歌眼镜开发套件 ,也被称为 GDK,是 Android SDK 的附加软件,可以让你构建直接在谷歌眼镜上运行的玻璃器皿(眼镜应用)。截至本书撰写之时,谷歌眼镜 1 已经停产;然而,谷歌眼镜 2 计划在 2015 年的某个时候发布。如果谷歌聪明的话,它不会让 Glass 2 成为 Android 的外部 API,而是做同样的事情,让它成为一个 Android Glass API 和 SDK,与 Android OS 更加集成,可供所有智能眼镜制造商使用,如 Luxottica、LGE、索尼、six15、Vuzix、三星、GlassUp、PivotHead、Meta AR 和许多其他制造商。
谷歌眼镜 1 的屏幕分辨率为 640 x360。这是四分之一伪高清,因为 1280×720 的屏幕有四个 640×360 的矩形区域。像 Android TV 或 Auto 一样,Glass 有一个独特的 UI 范式,专门适合你的硬件设备。这是围绕时间轴 UI 范例设计的。
该时间线是呈现给用户的主要用户界面。它由 640 x 360 分辨率的卡组成。Glass UI 提供了一些线性功能,例如查看动画和静态卡片、调用语音识别命令以及启动 Android Glass 应用的通用方式。
Android Glass 用户可以在这个时间轴 UI 的不同部分之间线性滚动,显示来自过去、现在和未来的卡片 UI 元素,这些元素等同于屏幕上(现在)、以前查看的(过去)和尚未查看的(未来)。最近查看的(过去的)项目将保持最接近家庭卡。这是用户恢复使用 Android Glass 或者第一次使用时看到的默认卡。
除了导航时间轴卡片,这款 Android Glass UI 还能对用户输入做出响应。用户使用触摸板浏览时间轴 UI,并可以使用语音命令启动 Android Glass 应用。卡片还允许显示菜单项,因此 Android Glass 应用将能够将控制权交给用户,以便他们可以完成操作,例如回复收到的短信,甚至分享照片或视频。
Android Glass 时间轴 UI 及其卡片被组织成多个不同的功能部分,包括首页、过去、现在和未来。一个默认的家庭卡上有一个安卓玻璃时钟。这张 Home 卡占据了时间轴用户界面的中心,每当用户开始使用 Android Glass 设备时,它就会出现。此主页卡保留在时间轴 UI 的中心区域,因为它提供了对 UI 其余部分的访问。
Android Glass 提供语音或触摸命令,允许用户启动 Android Glass 的其他操作系统组件或定制应用。语音命令允许 Android Glass 的免提操作。
Android Glass 主屏幕(时钟)右侧是历史部分,代表过去,显示静态数据卡片。这样做的原因是因为活卡总是被认为是在当下,所以它们永远不会出现在 Android Glass UI 的这个历史部分。
如果不通过重新访问来刷新静态卡,它们会在历史部分自然“衰退”。随着较新的卡片在过去的部分结束,它们将被放置在最靠近主屏幕(时钟)的位置。安卓眼镜会把最老的卡放在最右边。Glass OS 将移除任何超过七天的卡,或者达到 200 张卡的限制。
在 Android Glass 主屏幕(时钟)的左侧是现在和未来部分,其中包含静态和动态卡片。实时卡片总是显示与用户相关的实时信息。活卡应该总是出现在现在和未来的版块。当一张活动卡拥有焦点并且 Android Glass 进入睡眠状态时,这张卡将成为 Android Glass 重新开机时出现的默认卡。包含未来“时间戳”或“固定”的静态卡也将出现在当前和未来部分。
例如,Google Now 天气卡可能会自动显示当前和未来部分的相关信息,即使它是一张静态卡。静态信息可以在预定义的时间动态更新。
时间线 UI 的最左侧是设置卡片。有了这些,你就可以配置 Android Glass 操作系统的设置,比如音量或者你正在连接的 Wi-Fi 网络。
Live cards 显然是 Android Glass 的核心功能,因为这些内容总是包含丰富的实时内容,或者用户要求定期更新并保留在屏幕当前区域的内容。Live cards 应该使用自定义图形经常更新,以显示用户引人注目的实时信息。对于需要根据一些用户数据或用户使用的外部数据不断更新的动画用户界面来说,该功能是必需的。
活动卡可以访问加速度计和 GPS 等低级传感器数据。这允许尖端类型的用户交互和特征,这是静态卡所不可能的,因为这样的传感器实时流出动态数据,因此需要动态卡格式。
Live cards 能够在 Android Glass timeline UI 中运行。当这些实时卡中的每一个运行时,用户可以向左或向右滚动以查看其他实时卡并与之交互。这使得用户可以进行多任务处理,并在后台无缝维护每个 live 卡的运行时状态。
静态卡只能显示文本、图像和视频内容,这些内容可以一次性加载到内存中(静态),并且包含不变的数据(非动态)。视频是动画,但它是一系列图像。因此,虽然数字视频看起来是动态的,但实际上不是,因为它不会随着时间的推移而改变,并且每次播放时都是相同的图像系列!静态卡片包含可以用 HTML、文本、图像或视频构建的信息。静态卡不经常更新数据,如果有的话,它们应该为内容显示和快速通知而设计。
静态卡片允许有一个共享菜单项,这允许你的用户与其他人,称为联系人,甚至与另一个 Android Glass 应用共享卡片。您可以将这些 Android Glass timeline UI 卡声明为“可共享”,还可以为 Android Glass 应用定义一个联系人,该联系人可以接受共享的 timeline UI 静态卡项目。
当你需要对用户体验进行全面的用户界面控制时,Android Glass 有一种叫做“immersions ”的东西这些将在典型的 Android Glass timeline 用户界面或用户体验之外运行。
沉浸可以让你呈现自己的用户界面,处理 Android Glass 应用编程逻辑内部的所有用户输入。Android Glass 应用需要沉浸感,这些应用不能在时间轴用户界面范式的严格线性约束下运行,需要自由形式、非线性或面向对象的 GUI 方法。
值得注意的是,时间线卡片和沉浸都可以包含菜单项。它们执行相关的操作,比如回复、配置、删除、共享、数据输入以及更多的用户操作。
最初的 Google Glass 1 API(称为 Mirror API 和 Glassware GDK)并不是 100%特定于 Android 的,尽管它支持 Java 1.6,因此 32 位 Android 4.x. Glass Mirror 也支持 Python 和 PHP。Android Glass API 自然会成为新 Glass 2.0 的一部分,它将是 64 位 Android 5.x 甚至 6.x,并使用 Java 1.7 (Java 7)或 Java 1.8 (Java 8)甚至 Java 1.9 (Java 9)。
因为这个 API 目前正在开发中,还不可用,所以我将在本章的这一节中介绍谷歌眼镜 1 的基础知识,并在我的下一个 Pro Android 标题中介绍 Android 眼镜(或谷歌眼镜 2.0), Pro Android IoT (Apress,2016)。
Android Wear:探索有趣的 API 元素
在本章的其余部分,我将介绍 Android Wear 的一些其他重要功能,这些功能是我在本书前面没有介绍的。你可以在你的表盘代码基础设施上使用其中的大多数,这将允许你制作同时兼容表盘的 Android Wear 应用,这将成为 Android Wear 的一种趋势,因为智能手表硬件设备首先用于数字手表。这就是为什么我确保在本书中完整地介绍了 Watch Faces API。
检测位置:来自 Google Play 服务的 GPS 数据
一些穿戴应用 将需要知道它们的位置,以便能够计算行进的距离(健身和旅行应用),甚至确定用户在地球表面的哪个位置。一些用户,比如我自己,出于隐私原因,倾向于关闭智能手机上的 GPS 功能,除非有令人信服的理由允许自己被跟踪。在考虑使用 GPS 数据的穿戴应用时,也要记住这一点。
许多可穿戴设备包括 GPS 传感器,它可以检索位置数据,而无需绑定到另一个设备,如平板电脑或智能手机。幸运的是,当你在可穿戴应用中请求位置数据时,无需担心这些位置数据来自哪里。Android 可以确定位置数据,并在智能手机或智能手表上使用节能方法更新数据。
穿戴应用应当能够处理位置数据的任何丢失,以防穿戴硬件设备失去与配对设备的连接,并且不碰巧具有 GPS 传感器硬件。
可穿戴设备上的 GPS 位置数据将通过 Google Play 服务(location API)获得,您已经在本书中学习了如何利用该服务。对于 GPS,您将利用 FusedLocationProviderApi 及其附带的类来获取位置数据。要访问 GPS 定位服务,创建您的 GoogleApiClient 实例,这是任何 Google Play 服务 API 的主要入口点,就像您在本书中为 Android Wear Watch Faces API 实现所做的一样。
为了连接到 Google Play 服务,创建一个 GoogleApiClient 的实例,并创建一个活动来指定接口 ConnectionCallbacks 、OnConnectionFailedListener和 LocationListener 的实现。为了管理连接生命周期,在 onResume()方法中调用 connect(),在 onPause()方法中调用 disconnect(),类似于下面的 Java 代码:
public class WearableMainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private GoogleApiClient myGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addApi(Wearable.API) // used for the data layer API
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
@Override
protected void onResume() {
super.onResume();
mGoogleApiClient.connect();
}
@Override
protected void onPause() {
super.onPause();
mGoogleApiClient.disconnect();
}
}
应用连接到 Google Play 服务后,就可以接收位置更新了。当 Android 调用。在客户机的 Connected()回调中,您将通过创建 LocationRequest 对象并使用诸如之类的方法设置选项来构建位置数据请求。setPriority( ) 。您可以使用请求位置更新。onConnected()中的 requestLocationUpdates( ) 或使用删除位置更新。在 onPause()方法 中的 removeLocationUpdates( ) ,可以在下面实现的方法示例代码中看到:
@Override
public void onConnected(Bundle bundle) {
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL_MS)
.setFastestInterval(FASTEST_INTERVAL_MS);
LocationServices.FusedLocationApi
.requestLocationUpdates(myGoogleApiClient, locationRequest, this)
.setResultCallback(new ResultCallback() {
@Override
public void onResult(Status status) {
if (status.getStatus().isSuccess()) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Successfully requested location updates");
}
} else { Log.e(TAG, "Failed in requesting location updates, "
+ "status code: " + status.getStatusCode()
+ ", message: " + status.getStatusMessage());
}
}
});
}
@Override
protected void onPause() {
super.onPause();
if (myGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(myGoogleApiClient, this);
}
myGoogleApiClient.disconnect();
}
@Override
public void onConnectionSuspended(int i) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "connection to location client suspended");
}
}
一旦您启用位置更新,系统会调用一个**。onLocationChanged( )** 方法,使用通过指定的间隔值更新位置。setInterval( ) 方法调用。
并非所有智能手表硬件都配备 GPS 传感器。如果用户出去兜兜风,却把手机或平板电脑落在了身后,这款可穿戴应用就无法通过有线连接接收 GPS 定位数据。如果智能手表硬件没有 GPS 传感器,您可以检测到这种情况,并警告用户 GPS 定位功能当前不可用。这是通过使用。hasSystemFeature()方法调用。这个 Java 代码示例轮询一个设备,看它在开始活动时是否有 GPS:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
if ( !hasGpsData() ) {
// Fall-back functionality, for use without location data (Or warn user: No location
data!)
}
}
private boolean hasGpsData() {
return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
}
依靠有线连接获取位置数据的智能手表硬件设备也有可能突然失去连接。如果您的智能手表应用处理持续的 GPS 数据流,您将需要根据数据中断或变得不可用的位置来处理断开连接。在没有 GPS 传感器的智能手表硬件上,当智能手表失去其有线数据连接时,可能会丢失 GPS 位置数据。
如果您的应用依赖有线数据连接来获取位置数据,而穿戴设备没有 GPS 传感器,您应该检测连接丢失,警告用户,并更改应用的功能。
为了检测一个连接数据的丢失,你需要扩展一个 WearableListenerService。此服务将允许您处理数据层事件。为此,在 AndroidManifest 中声明一个,通知 Android 有关 WearableListenerService 的信息。此过滤器将允许操作系统在需要时绑定到您的 WearableListenerService。
定义 ListenerService 类的父标签和 BIND_LISTENER 子标签< intent-filter >的 XML 标记应该如下所示:
<service android:name=".MyNodeListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
在 WearableListenerService 的 MyNodeListenerService 子类中,您可以实现**。onPeerDisconnected( )** 方法 用于处理智能手表硬件设备是否内置 GPS 的情况。Java 代码如下所示:
public class MyNodeListenerService extends WearableListenerService {
@Override
public void onPeerDisconnected(Node peer) {
if( !hasGpsData() ) {
// Fall-back to functions that don't use location or notify user to bring their
handset
}
}
}
如果它丢失了 GPS 数据(信号),您应该使用。getLastLocation()方法调用。在无法获取 GPS 数据的情况下,或者智能手表没有内置 GPS 功能,并且与手机或平板电脑失去连接时,这种方法会很有帮助。下面是如何使用?getLastLocation()方法调用(记住在您的清单 XML 文件中请求 GPS 定位权限)以便检索最近已知的 GPS 定位数据(如果可用的话):
Location location = LocationServices.FusedLocationApi.getLastLocation(myGoogleApiClient);
如果您的智能手表应用使用手表上的 GPS 记录数据,您也可以将智能手表位置数据与智能手机位置数据同步。使用 LocationListener,您可以实现一个**。onLocationChanged( )** 方法
@Override
public void onLocationChanged(Location location) {
addLocationEntry(location.getLatitude(), location.getLongitude());
}
private void addLocationEntry(double latitude, double longitude) {
if (!mySavedGpsLocation || !myGoogleApiClient.isConnected()) { return; }
mCalendar.setTimeInMillis(System.currentTimeMillis());
String path = Constants.PATH + "/" + mCalendar.getTimeInMillis();
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(path);
putDataMapRequest.getDataMap().putDouble(Constants.KEY_LATITUDE, latitude);
putDataMapRequest.getDataMap().putDouble(Constants.KEY_LONGITUDE, longitude);
putDataMapRequest.getDataMap().putLong(Constants.KEY_TIME, mCalendar.getTimeInMillis());
PutDataRequest request = putDataMapRequest.asPutDataRequest();
Wearable.DataApi.putDataItem(myGoogleApiClient, request)
.setResultCallback(new ResultCallback() {
@Override
public void onResult(DataApi.DataItemResult dataItemResult) {
if (!dataItemResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to set the data, "
+ "status: " + dataItemResult.getStatus()
.getStatusCode());
}
}
});
}
另一个在 Wear 智能手表硬件中越来越受支持的主要功能是一个麦克风,接下来我们来看看语音识别!
语音动作:使用语音识别技术
我们都记得(或者我们记得吗?)先锋迪克·特雷西(什么时候会有人把这个翻拍成卖座片?)漫画系列,主人公迪克·特雷西能够对着他的智能手表说话,引发奇迹,总能化险为夷。
现在你也可以让你的用户与你的智能手表应用对话,让它为他们创造奇迹,因为语音动作已经成为 Android Wear 用户体验的一个不可或缺的部分,允许用户不用手就能相对快速地触发应用动作。
Android Wear 允许开发人员进行两种类型的语音操作。系统提供的语音动作基于操作系统任务,内置于 Wear 平台。当使用 Android 中的语音识别引擎调用特定的语音动作时,您可以使用 IntentFilter 对象为您希望启动的活动定义它们,我将在稍后讨论这一点。系统提供的语音操作的一些例子包括“记笔记”、“设置闹钟”或“叫出租车”,甚至“启动秒表”等等。
第二种语音动作是应用提供的语音动作。这些语音操作是基于应用的,您可以像启动器图标一样声明它们。为了利用这些动作,用户将声明“start”和一个动作(指定为标签),以便利用语音动作,并且您指定的活动子类将随后启动(Start)。
Android Wear 平台提供了许多基于用户动作的语音意图常量,允许用户说出他们想要做的事情,并让系统计算出要启动的最佳活动。这些包含在 android.speech 包的 RecognizerIntent 类中,如果您想研究它们,可以在下面的 android 开发人员网站 URL 中找到:
http://developer.android.com/reference/android/speech/RecognizerIntent.html
当用户调用语音操作时,您的应用可以过滤用于启动相关活动的意图,如您的清单中所定义的。
如果您想启动一个服务,将活动显示为可视提示,并在该活动中启动服务。务必打电话给**。当你想去掉活动(服务)的可视提示包装器时。**
例如,应该用来实现“Take a Note to Self”命令的 XML 标记块在将启动名为 SelfNote 的活动子类的父中声明了子,如下所示:
<activity android:name="SelfNoteActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="com.google.android.voicesearch.SELF_NOTE" />
</intent-filter>
</activity>
如果没有任何语音意图常量适用于您的应用,您可以使用自定义的“开始活动[此处输入名称]”语音操作直接启动您的应用。注册应用以使用自定义“开始”动作的方法与注册启动器图标的方法相同。不是在启动器 XML 结构中请求应用图标,而是一个应用将请求一个语音动作,使用 android:label 参数。要指定用户在“开始:”后使用的语音命令,请为您希望启动的活动指定标签属性。例如,这个<意图过滤器>构造识别“开始:语音控制应用”语音动作,启动 StartVoiceActivity:
<application>
<activity android:name="StartVoiceActivity" android:label="VoiceControlApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
除了结合 Android Wear 中的内置语音识别常量使用语音操作来启动活动,您还可以使用 SpeechRecognizer 类来处理“自由形式”或非标准的语音输入,该类访问识别服务类和识别意图类,后者访问前面提到的预定义语音操作常量。
这些只是 android.speech 包的部分组件。这个语音识别器类和相关类将被用来从用户那里获得免提语音输入,并处理该语音输入,提供一个结果。
这方面的一个例子可能需要发送短文本消息或为搜索引擎指定搜索项。值得注意的是,语音 API 并不打算用于连续语音识别,例如您可以使用专业语音软件包,如 Nuance Communications 的 Dragon Naturally Speaking Premium 软件。微软 Windows 8.1 还内置了语音识别功能。
你不想用 Android Wear 进行连续语音识别的原因是,尽管 Android 操作系统非常强大,但它仍然只是一个嵌入式设备操作系统,目前不具备执行连续语音识别和翻译的 CPU 内核、内存和时钟速度。
试图在 Wear 应用内完成这种级别的语音识别将消耗大量的电池寿命、处理开销和网络带宽。SpeechRecognizer 方法需要使用主应用线程来调用。您使用一个 ACTION_RECOGNIZE_SPEECH 操作调用 startActivityForResult( ) ,启动一个语音识别活动。然后,您将使用下面的 Java 结构在 onActivityResult()方法中处理结果:
private static final int SPEECH_REQUEST_CODE = 0;
private void displaySpeechRecognizer() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); // Create an Intent object
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
startActivityForResult(intent, SPEECH_REQUEST_CODE); // Start the Activity
}
@Override // The callback which is invoked when the Speech Recognizer returns
protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Process Intent if (requestCode == SPEECH_REQUEST_CODE && resultCode == RESULT_OK) {
List<String> results = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
String spokenWord = results.get(0);
// Process Voice Recognition Result
}
super.onActivityResult(requestCode, resultCode, data);
}
添加位置感知和语音识别可以让您的应用感知!
摘要
恭喜你,你已经完成了这本专业的 Android 可穿戴设备书籍,并获得了成功!您正在创建创新的穿戴应用,并准备好引发这场物联网革命!
在这最后一章中,除了 Wear 之外,您还了解了 Android OS 最近引入的一些额外的物联网 API。你看了一下 Android TV,它允许你为用户现在安装在他们客厅的 64 到 96 英寸的大屏幕创建应用。
接下来,您了解了新的 Android Auto API,它允许您创建在汽车仪表板环境中无缝工作的应用,并利用内置的汽车硬件,如音频扬声器。
你还看了一下谷歌眼镜 1,即将成为 Android 眼镜 2,以及 Android Wear 的其他一些你应该考虑使用的功能。
接下来,您看了一下使用 GPS 传感器硬件数据、Google 移动服务(GMS)和 Google Play 服务实现基于位置的服务。
本章最后介绍了最新语音识别技术的使用,以及 Android 提供的内部语音动作命令。