Android可穿戴设备世界之旅

avatar
作者
猴君
阅读量:1

人不走空

                                                                      

      🌈个人主页:人不走空      

💖系列专栏:算法专题

⏰诗词歌赋:斯是陋室,惟吾德馨

介绍

Android通过在电视、穿戴和汽车等各种电子模块中扩展下一代应用开发概念,扩展了其整个范围和可能性。本文简要总结和概述了 Android Wear(未来新兴的应用开发平台)中的应用开发。

本文介绍了有关Android可穿戴设备及其功能的明确概念。本文将详细介绍 Wear 平台中 Android 应用程序开发的高级概述。如果您是 Android 爱好者,喜欢玩代码并想用它制作令人惊叹的应用程序,那么让我们为我们的手表构建一些很酷的东西!

安卓健体

从技术上讲,它是专为可穿戴智能手表和计算机设计的 Android 操作系统版本。需要运行 Android 4.3 或更高版本的移动设备,或者 iOS 8.2 或更高版本的移动设备,并且支持有限,才能与这些手表配对。它是从 API 级别 20 开始引入的,代号是KITKAT_WATCH

图像 1

Android Wear(来源:tech.thaivisa.com)

历史

适用于 Android 的可穿戴平台于 2014 年 3 月 18 日随着开发者预览版的发布而首次推出。让我们回滚历史记录以获取有关该平台的一些关键点。

  • Samsung Gear Live 和 LG G Watch 于 2014 年 6 月 25 日在 Google I/O 上发布。
  • 摩托罗拉的 Moto 360 于 2014 年 9 月 5 日发布。
  • 2014 年 12 月 10 日,有关 Android 5.0 棒棒糖的更新开始推出。
  • Google 于 2015 年 8 月 31 日推出了适用于 iOS 8.2 或更高版本的配对应用程序。

目前,摩托罗拉、三星、LG、HTC和华硕正在生产适用于Android的可穿戴智能手表。

功能一览

谷歌为这个智能手表平台引入了一些很酷的功能,而这些功能在其移动平台上仍然不存在。一起来看看——

  • Google Now :就智能手表而言,这可能是最重要的功能。当你问“OK Google,我的心率是多少”或“最近的消防站在哪里?”时,从手表上得到答案真是太好了,有点像《钢铁侠》电影中的J.A.R.V.I.S.。
  • 通知:与手表保持联系,一目了然地查看消息。
  • 天气更新:不时获取更新的天气报告。
  • 旅行:一目了然地接收您的旅行信息。
  • 提醒:千万不要错过任何事情。获取日历和其他提醒。
  • 与移动设备的交互:从手表播放手机的音乐!
  • Google Fit:支持骑行和跑步跟踪。只需说“Ok Google,开始跑步”。
  • 支持谷歌地图、睡眠跟踪、查找你的手机功能等!

开始之前

本文简要介绍了针对磨损平台的应用开发过程。因此,无论是开发还是对代码结构有扎实的了解,您都需要对 Android 应用程序开发方面有一定的了解,还需要具备 JAVA 方面的知识。如果你觉得自己没有足够的知识,没问题,花点时间学习JAVAOOP。为了制作应用程序,我们将使用 Android Studio。如果您的计算机有 4GB 内存和 JDK 7 或更高版本,您就可以开始了。要与工作室一起正确设置所有开发环境,您可以关注此 YouTube 视频。请注意操作系统和 JDK 之间的版本(32/64 位)匹配。

Wear App 的设计原则

由于手表的屏幕比移动设备更小,因此该平台的设计原则与传统的 Android 应用程序有很大不同。在官方网站上进行简要说明之前,您可以先看一下关键设计指南-

  • 遵循 5 秒规则,这意味着应用中的任何内容都应使用此典型时间与其用户进行交互。您的用户不应将他/她的注意力保持超过此时间。如果超过这个时间,你应该重新考虑你的应用程序功能和设计!
  • 设计记住你的大拇指法则!想想看,当你走路或吃饭时,很难放慢这些活动的速度,集中精力在手表上做工作。因此,在设计时,请在屏幕上留出足够的空间让您的拇指完成这项工作。不要以项目过于相邻的方式设计应用,始终为大手势而设计。
  • 如果要在应用中显示的内容太多,请将它们拆分为多个页面(卡片)。
  • 避免使用用户的传统输入系统,一目了然,将其保持在最低限度,一目了然,为您的手表使用更智能的解决方案,向“Google Now”问好。

构建您的首款 Wear 应用程序

首先,我们将集中精力制作一个“Hello Wear”应用程序,该应用程序将演示制作基本磨损应用程序并将应用程序运行到磨损模拟器中的步骤。接下来,我们将打磨应用程序并制作一些很酷的东西!

SDK 要求

在构建可穿戴应用程序之前,请先检查两件事。你必须——

  • 将您的 Android SDK 工具更新到 23.0.0 或更高版本 &
  • 使用 Android 4.4W.2 (API 20) 或更高版本更新您的 Android SDK。

从 SDK 管理器中选择提到的工具,并将其更新到最新版本。

图像 2

图 1:Android SDK 工具

           

图像 3

图 2:可穿戴应用所需的最低 Android SDK 版本

如果您没有真正的 Android 手表,请不要忘记安装列出的 Android Wear 系统映像,它们需要构建 Wear 模拟器。

创建新项目

打开Android Studio,然后选择“新建项目”选项。为您的应用程序命名,我们在这里使用“Hello Android Wear”作为应用程序名称以及公司域名。

图像 4

图 1:为 Android wear 创建一个新项目

为您的 wear 应用程序选择最低 SDK 版本,这里我们选择了代号为 KitKat Wear 的 API 20

图像 5

图 2:选择目标 SDK 版本

Wear 支持各种类型的专业活动,包括表盘、谷歌地图等。但是我们在本例中选择了“空白磨损活动”。

图像 6

图 3:选择毛坯磨损活动

现在设置您的活动和布局文件名,有不同的矩形和圆形布局文件以及主布局文件。保留默认名称到现在为止,我们稍后会讨论它们。单击“完成”按钮,然后等待一段时间以构建 Wear 应用的 Gradle 项目信息。

图像 7

图 4:设置布局和活动名称

当所有过程成功完成后,您将找到如下所示的工作室窗口。

图像 8

图 5:成功构建后的项目窗口

创建 Wear 虚拟设备

要创建磨损模拟器,请单击 Studio 窗口右上角的 AVD 管理器按钮。然后单击位于窗口左下角的 AVD 管理器窗口的“创建虚拟设备”按钮。

         

图像 9

图 1:选择 AVD 管理器

接下来,从左侧面板的类别列表中选择磨损。根据屏幕尺寸和形状(圆形/方形),右侧列出了一些设备,您可以根据自己的选择进行选择。目前,我们选择屏幕尺寸为1.65英寸,分辨率为320 * 320的圆形服装。

图像 10

图 2:为模拟器选择磨损

可用的系统映像将在下一个窗口中看到。我们选择了面向 Android 4.4 的 x86。始终优先选择 x86 模拟器而不是 armeabi-v7a 模拟器,因为性能很快。

图像 11

图 3:选择系统映像

但请记住,x86 模拟器需要 HAXM 加速器才能获得更好的性能。因此,请从 SDK 管理器窗口安装它。

图像 12

图 4:安装 HAXM 以提高仿真器性能

您可以使用“显示高级设置”按钮来编辑模拟器的配置,即内存、SD 卡等。

图像 13

图 5:AVD 配置窗口

当您的佩戴虚拟设备准备就绪时,它将出现在 AVD 管理器窗口中。单击红色标记的启动按钮以启动模拟器。

图像 14

图 6:AVD 列表

根据您的 PC 性能和可用 RAM,模拟器将在 15 秒到 1 分钟的时间范围内启动。准备就绪后,它将如下所示。

图像 15

 

图像 16

图像 17

 

图像 18

图像 19

 

图像 20

图7:Android Wear模拟器

将项目部署到 Wear Emulator

现在创建的磨损模拟器已准备好运行您的项目。按下工作室窗口顶部中间的绿色“运行”按钮。gradle 构建完成后,将出现一个名为“Device Choose r”的窗口,您将看到创建的磨损模拟器列在那里。单击“确定”按钮继续。

图像 21

图 1:设备选择器窗口

项目成功运行后,您将在模拟器中看到输出,如下图所示。

图像 22

图 2:部署项目后的输出

更改文本值

让我们更改文本值,使其类似于“Hello Round Android Wear!返回左侧面板上的项目树,然后在 values 文件夹下选择strings.xml。将标签为“hello_round”的字符串值更改为“Hello Round Android Wear!”。

图像 23

图 1:更改string.xml中的文本值

现在运行项目。您将找到如下输出。滑动屏幕退出应用程序。它完成了我们的“Hello Android Wear”应用程序。

图像 24

图 2:更改文本后的输出

相当多的事实

在进一步讨论之前,需要考虑一些重要因素。

在圆形和矩形形状之间切换

在创建项目时,我们发现了矩形和圆形磨损设备的 2 种不同的布局名称。在项目结构中,您将在布局文件夹下找到这 2 个布局文件以及一个主 xml 布局文件。名为“”的文件定义方形耐磨屏幕的布局,而“”定义圆形耐磨屏幕的布局。rect_activity_main.xmlround_activity_main.xml

当我们制作另一个针对方形屏幕的模拟器并运行我们之前所做的相同项目时,输出看起来相似,但文本值不是,因为我们没有更改文件中方形屏幕的 textview 字符串值。string.xml

图像 25

 

图像 26

图:圆形和方形磨损仿真器的输出比较

在为磨损应用创建布局时,需要考虑方形和圆形磨损设备的不同机制。因为相同的布局或设计可能会在设备屏幕的角落附近裁剪,或者可能看起来不好。有 2 种解决方案可以克服这种情况,一种是,另一种是.WatchViewStub BoxInsetLayout

WatchViewStub 简介

转到文件,您可能会找到具有名为 的开始和结束标记的 xml 代码,对吧?activity_main.xmlWatchViewStub

WatchViewStub 在运行时检测屏幕形状并充气矩形或圆形布局。您需要分别为矩形和圆形布局创建和填充 UI 视图。

<android.support.wearable.view.WatchViewStub      xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     xmlns:tools="http://schemas.android.com/tools"     ...      app:rectLayout="@layout/rect_activity_main"     app:roundLayout="@layout/round_activity_main"     ...>      </android.support.wearable.view.WatchViewStub>

XML 布局名称应与 app:rectLayout 和 .根据我们之前所做的示例,它们应分别命名为 和 。app:roundLayoutactivity_main.xmlrect_activity_main.xmlround_activity_main.xml

现在,从 JAVA 的角度来看,在膨胀完成之前,您无法访问任何子视图。您应该实现该接口以检测布局膨胀何时完成。当正确的视图膨胀时,将调用该方法,该方法使用 获取子视图的所需引用。OnLayoutInflatedListener WatchViewStub onLayoutInflated findViewById

final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);  stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {     @Override     public void onLayoutInflated(WatchViewStub stub) {         mTextView = (TextView) stub.findViewById(R.id.text);     } });

BoxInsetLayout

BoxInsetLayout 允许您定义适用于方形和圆形屏幕的单个布局。要在此区域内显示,布局中的子视图将指定具有顶部底部左侧右侧全部组合的属性。layout_box

                                                

图像 27

图:圆形屏幕上的 BoxInsetLayout

 

构建一些很酷的东西

让我们扩展我们的工作,做一些很酷的东西。我们将制作一个数学游戏,该游戏将在 60 秒的时间范围内生成随机方程,因此用户将获得分数结果。

设计

首先,我们需要设计适合圆形和方形设备的主布局文件。我们将使用 WatchViewStub 来完成这项工作。

我们将像下面这样设计我们的应用程序。让我们用 .xml

图像 28

图 1:应用布局

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:layout_width="match_parent"     android:layout_height="match_parent"     android:background="@drawable/back"     android:orientation="vertical">      <LinearLayout         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:layout_weight="2">          <TextView             android:id="@+id/textTimer"             android:layout_width="match_parent"             android:layout_height="match_parent"             android:fontFamily="sans-serif-condensed"             android:gravity="center"             android:text="0:59"             android:textColor="@android:color/holo_blue_bright"             android:textSize="22sp" />      </LinearLayout>      <LinearLayout         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:layout_weight="1.5"         android:orientation="vertical"         android:weightSum="2">          <LinearLayout             android:layout_width="fill_parent"             android:layout_height="fill_parent"             android:layout_weight="0.8">              <TextView                 android:id="@+id/gameEquation"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:fontFamily="sans-serif-light"                 android:gravity="center"                 android:text="22*82 = ?"                 android:textColor="@android:color/white"                 android:textSize="35sp" />          </LinearLayout>          <LinearLayout             android:layout_width="fill_parent"             android:layout_height="fill_parent"             android:layout_weight="1.2"             android:orientation="horizontal"             android:weightSum="3">              <EditText                 android:id="@+id/answer"                 android:layout_width="match_parent"                 android:layout_height="wrap_content"                 android:layout_marginLeft="20dp"                 android:layout_weight="1" />              <ImageView                 android:id="@+id/next"                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_gravity="center"                 android:layout_marginLeft="15dp"                 android:layout_marginRight="15dp"                 android:layout_weight="2"                 android:background="@drawable/next"                 android:scaleType="fitXY" />          </LinearLayout>      </LinearLayout>      <LinearLayout         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:layout_marginBottom="10dp"         android:layout_marginLeft="50dp"         android:layout_marginRight="50dp"         android:layout_weight="1.5"         android:orientation="vertical"         android:weightSum="3">          <LinearLayout             android:layout_width="match_parent"             android:layout_height="match_parent"             android:layout_weight="1"             android:orientation="horizontal"             android:weightSum="4">              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="1"                 android:textSize="18sp"                 android:onClick="onText1_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="2"                 android:textSize="18sp"                 android:onClick="onText2_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="3"                 android:textSize="18sp"                 android:onClick="onText3_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:background="@drawable/backspace"                 android:layout_margin="2dp"                 android:onClick="onTextBackSpace_Click"                 android:clickable="true"/>          </LinearLayout>          <LinearLayout             android:layout_width="fill_parent"             android:layout_height="fill_parent"             android:layout_weight="1"             android:orientation="horizontal"             android:weightSum="4">              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="4"                 android:textSize="18sp"                 android:onClick="onText4_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="5"                 android:textSize="18sp"                 android:onClick="onText5_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="6"                 android:textSize="18sp"                 android:onClick="onText6_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="-"                 android:textSize="18sp"                 android:onClick="onTextMinus_Click"                 android:clickable="true"/>          </LinearLayout>          <LinearLayout             android:layout_width="fill_parent"             android:layout_height="fill_parent"             android:layout_weight="1"             android:orientation="horizontal"             android:weightSum="4">              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="7"                 android:textSize="18sp"                 android:onClick="onText7_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="8"                 android:textSize="18sp"                 android:onClick="onText8_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="9"                 android:textSize="18sp"                 android:onClick="onText9_Click"                 android:clickable="true"/>              <TextView                 android:layout_width="match_parent"                 android:layout_height="match_parent"                 android:layout_weight="1"                 android:gravity="center"                 android:text="0"                 android:textSize="18sp"                 android:onClick="onText0_Click"                 android:clickable="true"/>          </LinearLayout>     </LinearLayout> </LinearLayout>

功能性

为了计算游戏时间,我们需要一个控件和一些变量来跟踪时间。CountDownTimer

private long timeRemaining = 0; private final int gameLengthInMillis = 60000; private final int countDownInterval = 1000;  public CountDownTimer timer;

现在我们将利用事件 ot ,并将剩余时间值打印到 textview。onTick CountDownTimer 

// Set countdown  timer = new CountDownTimer(gameLengthInMillis, countDownInterval) {     @Override     public void onTick(long millisUntilFinished) {          if (isPaused || isCanceled) {              timer.cancel();             Log.d("GameActivity:", "Timer >>1st timer cancled. remaining time:" + millisUntilFinished);          } else {              timeRemaining = millisUntilFinished;             mTextView.setText(Long.toString(timeRemaining / 1000));         }     }

为了生成随机方程,我们将使用一个单独的类来随机生成运算符和数字。 

private char[] operators = new char[] { '+', '-', '*', '/' };  // generate operator
int firstNumber = random.nextInt(10); // generate first random number int secondNumber = random.nextInt(10); // generate second random number

 在生成所有这 3 个随机事物后,我们将将它们连接起来生成一个方程式。

String equation = first + " " + operator + " " + second + " = ?" ;

 接下来,我们需要抛出一个按钮事件,该事件将在每次点击时刷新此随机方程。此外,我们还需要将用户输入的答案与其真实答案进行比较。此外,我们需要跟踪正确和错误的答案并计算它们的数量。为了求解数学方程,我们可以使用一个名为 的第三方开源项目。

buttonNext.setOnClickListener(new View.OnClickListener() {                              public void onClick(View v) {                                  if (editTextAns.getText().toString().isEmpty()) {                                     Toast.makeText(getApplicationContext(), "Please write some answer first", Toast.LENGTH_SHORT).show();                                 } else {                                     total += 1;                                     int ans = Integer.parseInt(editTextAns.getText().toString());                                     if (ans == randomEquation.answer) {                                         correct += 1;                                     } else {                                     }                                     editTextAns.setText("");                                     refreshEquation();                                 }                             }                         } );

计时器完成后,我们需要导航到“结果”页面以显示用户性能。因此,我们将使用 的方法。onFinish()CountDownTimer

@Override  public void onFinish() {      Intent intent = new Intent(MainActivity.this, ResultsActivity.class);     intent.putExtra("correct", correct);     intent.putExtra("total", total);     startActivity(intent);     finish();      Log.d("GameActivity:", "Timer >> finished 1 min"); }

在 中,我们将打印传递给此活动的值,并通过将其保存在 中来跟踪最高分。ResultsActivity.class SharedPreferences 

final SharedPreferences sharedPreferences = getSharedPreferences("prefs", 0); int currentHighScore = sharedPreferences.getInt("highscore", 0);  if (score > currentHighScore) {     isHighScore = true;     SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();     sharedPreferencesEditor.putInt("highscore", score);     sharedPreferencesEditor.commit();     highScoreTextView.setText("New High score !!!"); } else {  highScoreTextView.setText("High score of this level is " + currentHighScore); }

在成功设置所有这些组件后,当我们构建项目时,我们将获得一个很酷的数学应用程序,它一定会在您的空闲时间娱乐您!

Image 29

Image 30

Image 31

Image 32

图2:数学游戏的最终输出

此外

将磨损模拟器与 Android 设备连接

让我们将我们的磨损模拟器与我们真实的安卓设备(手机/平板电脑)连接起来。为此,请转到设备的“设置”,然后检查 USB 调试 来自 开发人员选项 如果之前没有选择。

Image 33

图1:保持USB调试开启

现在从 Google Play 下载 Android Wear 应用程序并将其安装到您的设备上。安装后,将设备连接到计算机并打开命令窗口。编写命令“adb devices

Image 34

图 2:adb 命令中可用的连接设备列表

接下来,编写此命令“adb -d forward tcp:5601 tcp:5601”以打开连接端口。

打开设备的蓝牙连接并将其与磨损模拟器配对。配对过程完成后,您将在设备佩戴应用程序上看到此窗口。

Image 35

图 3:与仿真器连接的设备。

要检查您的设备是否与磨损模拟器连接,您可以尝试多种方法,在这里我们正在检查手表通知。选择它,你会发现一个有几个选项的窗口。从那里选择“来电”选项,您将直接收到磨损模拟器的呼叫通知。瞧,您的设备和磨损模拟器现已连接。您可以从磨损模拟器等控制设备的音乐播放器。

Image 36

    

Image 37

图 4:从设备向 wear 模拟器发送呼叫通知。

兴趣点

如本文前面所述,将整个可穿戴平台涵盖到一篇文章中是一个漫长的过程。但是我们已经看到了在这个平台上开发应用程序的最重要因素。我们创建了一个示例 Hello Wear 应用程序,创建了磨损模拟器并构建了应用程序。然后,我们为手表创建了一个完整的数学游戏。有一千个范围可以将此应用程序升级为企业级应用程序。在一些逻辑层面上,它可能会更令人愉快。关于谷歌地图WatchFace等,还有更多有趣的可穿戴应用程序开发范围,希望我能在不久的将来带着这些很棒的话题回来。在那之前,请玩得开心 Android Wear。祝你Droiding快乐!


作者其他作品:

【Java】Spring循环依赖:原因与解决方法

OpenAI Sora来了,视频生成领域的GPT-4时代来了

[Java·算法·简单] LeetCode 14. 最长公共前缀 详细解读

【Java】深入理解Java中的static关键字

[Java·算法·简单] LeetCode 28. 找出字a符串中第一个匹配项的下标 详细解读

了解 Java 中的 AtomicInteger 类

算法题 — 整数转二进制,查找其中1的数量

深入理解MySQL事务特性:保证数据完整性与一致性

Java企业应用软件系统架构演变史

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!