Android Things 全解析

yvgodargj 7年前
   <p>Android Things 正式接替 Brillo 亮相,名称的改变带来了什么新的内容,广大 Android 开发者如何进入这一新的领域,通过本文,你不仅会了解 Android Things 的来龙去脉,也会直接通过代码来体验开发带给你的魅力。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/b3c322c68a8013f7dc04a3f1984ffab8.png"></p>    <p><strong>Android Everywhere</strong></p>    <p>一张 Google I/O 2015上的旧图,清晰的展示了 Android 的历史和未来。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/223661e40b85332864478735fde88022.jpg"></p>    <p><strong>Android</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/67c13d8e71a507646f98bd7e2d14eec3.jpg"></p>    <p>处于中心的 Android Mobile,已经占据了全球手机市场绝大多数份额,几十亿部 Andriod 手机,构成了 Android 生态系统最坚实的基础。</p>    <p><strong>Android TV</strong></p>    <p><img src="https://simg.open-open.com/show/c29a711f898e53a2a89b6df54da93e6f.jpg"></p>    <p>随着着电视大屏发展的脚步,Android TV 也成了所有电视盒子和智能电视的不二之选,主要归功于 Android 硬件系统的开放、庞大的开发者群体、完整的工具链。如果说手机端还有 iOS 将近 20% 的份额,在 TV 端,目测 tvOS 不到 2%,Android TV 也就代表了整个智能电视,国内更是 100% 的 Android TV,Apple TV 没有国行版本。</p>    <p><strong>Android Wear</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/82b0c04f1be7bbdb6d3feed2dab54851.jpg"></p>    <p>让你的应用跑在手表上,同样使用熟悉的开发工具,主要是面向海外的应用,由于国内 Android Mobile 严重分裂,而 Android Wear 需要依赖手机的支持。</p>    <p><strong>Android Auto</strong></p>    <p><img src="https://simg.open-open.com/show/c298b226ed76253747a0276ec32b1f79.jpg"></p>    <p>针对汽车的使用场景进行优化,有了 Android Auto 就不用上车后就是找电源线,然后开导航,再把手机放到各种架子上,而是直接把 Android Mobile 放到原生底座上,直接使用语音和易操作的中控大屏。</p>    <p><strong>Android Chromebook</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/e95cb65e65aeb7bd47be8a9d868b8caa.jpg"></p>    <p>从 Chrome 操作系统版本 M53 开始,可以直接使用 Chromebook 中的 Google Play Store 下载和使用 Android 应用,现在使用的 Gogole Chrome 版本是55,那么绝大多数已有 Chromebook 都已经支持 Android 应用,新的 Chromebook 自然都会支持。</p>    <p>Android 和 Chrome 两大系统的合并,除了带来了 Android 丰富的应用以外,对于用户最大的好处就是自动更新了,Chrome 自动下载更新,下次重新打开/启动时自动应用更新,从 Android Nougat 开始,Android 系统也将使用这种更新机制。</p>    <p>根据 IDC 报告,Chromebook 在 2016 年第一季度的出货量已经在美国市场超越了Mac,特别是由于教育市场的大量需求。</p>    <p>这里,还要注意,Chromebook 使用的 Chrome OS 和 Google Chrome 高度共享代码,既然 Android 应用可以在 Chromebook 上运行,当未来在 Mac/Windows/Linux 上可以时,你也不要感到惊讶。</p>    <p><strong>Android Things</strong></p>    <p>终于到了今天的主角登场,Android Things!先看外表:</p>    <p>再看内部核心硬件:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/c3e65d2cf4880bced8423b224cab17be.jpg"></p>    <p>它的愿景就是将无数的的设备连接起来,Android Things 作为物联网的大脑,使用公开协议 Weave 与广大的传感器/外部设备进行对话。</p>    <p>不像 Android 其它系统,Android Things 大多数情况下只在后台以服务方式运行,没有显示屏,默默的与打印机、门锁、烤箱、灯泡、插座这些设备一起提供服务。</p>    <p><strong>Android Things 全解析</strong></p>    <p><strong>Android Things 架构</strong></p>    <p>先看 Brillo 和 Android Things 的架构图进行对比:</p>    <p>这是 Brillo: </p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/94b7bb0bcf82c263dbf1a25f6bc6f40b.jpg"></p>    <p>这是 Android Things:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/6ca06586e99d2a266f4037bb7d3a0e43.jpg"></p>    <p>可以很清楚的看出来:</p>    <ul>     <li> <p>Brillo 使用 C/C++ 基于 NDK 进行开发,Android Things 通过 Java API 面向广大的 Android 和 Java 开发者,就算是新手,Android 的也是极易上手的。各位苦于嵌入式开发各种工具坑的福音到了,对于性能和底层要求高的部分仍然可以用 NDK 编写,在 Android Studio 里调试 NDK 代码也和 Java 代码一样的简单。</p> </li>     <li> <p>Android Studio,Android SDK,Play service 和 Firebase,这些工具和 Service 形成了完整易用的工具链。</p> </li>     <li> <p>Android Things 出生最晚,更新条件也是最好的,直接使用 Android Nougat 的自动后台更新机制,最大限度的提高系统的安全性。</p> </li>    </ul>    <p>广泛的硬件平台支持</p>    <p>现在支持以下3款硬件:</p>    <p>1)Intel Edison</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/d23aaf5acae3c3234ec2c4ca367a3aee.jpg"></p>    <p>2)NXP Pico</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/7dd2cd0c30a869bbb82c967a3adcb1d7.jpg"></p>    <p>3)Raspberry Pi 3</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/265b5aa1034459ccf025e4a46b8d5249.jpg"></p>    <p><strong>Hello Android Things</strong></p>    <p>买到的开发版都是没有装操作系统系统的,第一步先把 Android Things 刷到板子里。</p>    <p>Flash image (刷机):</p>    <p>以Intel Edison为例:</p>    <p>0.Android SDK Platform Tools 25.0.3以上,fastboot 工具添加到 PATH 环境变量中,以便从任意目录运行。</p>    <p>1. 下载后打Intel Flash Tool,加打开下载好的对应刷机包。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/88b7c574839b8a0fcb1ad9524127c6a3.jpg"></p>    <p>2. 使用 USB 线链接 Edison,如果 Edison 没有显示,换 USB 口和线试试。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/1d97929ff9eb82342d8f6cba3dc39306.jpg"></p>    <p>3. Start to Flash(开始刷机)</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/7378cd0501b06698b522b67fab6f1a6b.jpg"></p>    <p>4. 使用 Fastboot 刷入系统镜像,此时需要几十秒,光 System.img 就有 500 多M。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/808b2623642a00f27aa972152e9929e8.jpg"></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/834f26431aaca112c4c0afaac504da2f.jpg"></p>    <p>5. 刷入 Google Service 镜像。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/898d8b7d882b5ad00d13b5c4e4c804ea.jpg"></p>    <p>6. 刷入 OEM 镜像。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/a76d51a6074d961b999b0190cbcdbcd6.jpg"></p>    <p>7. 重启</p>    <p>8. 验证系统状态。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/7d0aaafed8237deb868a7a013b748720.jpg"></p>    <p>如果出现以下 Error,把 Intel Flash Tool 关掉,重新连接下 USB。</p>    <p><img src="https://simg.open-open.com/show/54004d9a8cdabf9a0a23bc1ee477de3b.jpg"></p>    <p><strong>Connecting WIFI (联网)</strong></p>    <p>依然是熟悉的 adb 命令和服务启动参数</p>    <p><img src="https://simg.open-open.com/show/14c7a73c759adb5b1dbe02cece608bdc.png"></p>    <p>用 logcat 查看网络状态</p>    <p><img src="https://simg.open-open.com/show/210c843cb0c23c42f038f081a71ca557.png"></p>    <p>Ping 检测</p>    <p><img src="https://simg.open-open.com/show/bab7be65f18243776255f60ba9daefb6.png"></p>    <p><strong>Hello Android Things 项目</strong></p>    <p>1. Android Studio 中新建项目。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/6990efc4596124e9632d0e28abd4f753.jpg"> <img src="https://simg.open-open.com/show/471bda14cdbede4aa8f1b43052914271.jpg"></p>    <p>2.在 build.gralde 中添加依赖 com.google.android.things:androidthings</p>    <pre>  apply plugin: 'com.android.application'  android {      compileSdkVersion 25      buildToolsVersion "25.0.2"      defaultConfig {          applicationId "com.geekdev.alpha.androidthings"          minSdkVersion 24          targetSdkVersion 25          versionCode 1          versionName "1.0"          testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        }      buildTypes {          release {              minifyEnabled false              proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }      }  }  dependencies {      compile fileTree(dir: 'libs', include: ['*.jar'])      androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })      provided 'com.google.android.things:androidthings:0.1-devpreview'      compile 'com.android.support:appcompat-v7:25.1.0'      testCompile 'junit:junit:4.12'  }</pre>    <p>此处依赖方式是 provided,让 Android Things 使用系统中的库。</p>    <p><strong>添加 activity</strong></p>    <p>添加一个主 activity 并配置 AndroidManifest.xml</p>    <p><img src="https://simg.open-open.com/show/101a7f16be7e6f8b0048cf49909170eb.jpg"></p>    <p>在 Activity 中输入 Hello World</p>    <p><img src="https://simg.open-open.com/show/c201cc764bbaf904a5c3391a10d3fdf1.png"></p>    <p><strong>运行输出</strong></p>    <p>直接 Command+R,可以在 logcat 窗口中看到结果了。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/099275c8bab7ae786b4cd0d11af7532a.jpg"></p>    <p><strong>Peripheral I/O</strong></p>    <p>不满足于 Hello Android Things ,继续来使用 Android Things 对外设进行操作。</p>    <pre>  package com.geekdev.alpha.androidthings;    import android.app.Activity;  import android.os.Bundle;  import android.util.Log;  import android.view.KeyEvent;  import android.widget.Button;    import com.google.android.things.contrib.driver.button.ButtonInputDriver;  import com.google.android.things.pio.Gpio;  import com.google.android.things.pio.PeripheralManagerService;    import java.io.IOException;    /**   * Created by Alpha.   * <p>   * Example of using Button driver for toggling a LED.   * <p>   * This activity initialize an InputDriver to emit key events when the button GPIO pin state change   * and flip the state of the LED GPIO pin.   * <p>   * You need to connect an LED and a push button switch to pins specified in {@link BoardDefaults}   * according to the schematic provided above.   */      public class MainActivity extends Activity {        private static final String TAG = MainActivity.class.getSimpleName();          private Gpio mLedGpio;      private ButtonInputDriver mButtonInputDriver;        @Override      protected void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          Log.d(TAG, "Hello Android Things!");          Log.i(TAG, "Starting ButtonActivity");            PeripheralManagerService pioService = new PeripheralManagerService();          try {              Log.i(TAG, "Configuring GPIO pins");              mLedGpio = pioService.openGpio(BoardDefaults.getGPIOForLED());              mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);                Log.i(TAG, "Registering button driver");              // Initialize and register the InputDriver that will emit SPACE key events              // on GPIO state changes.              mButtonInputDriver = new ButtonInputDriver(                      BoardDefaults.getGPIOForButton(),                      Button.LogicState.PRESSED_WHEN_LOW,                      KeyEvent.KEYCODE_SPACE);              mButtonInputDriver.register();          } catch (IOException e) {              Log.e(TAG, "Error configuring GPIO pins", e);          }      }        @Override      public boolean onKeyDown(int keyCode, KeyEvent event) {          if (keyCode == KeyEvent.KEYCODE_SPACE) {              // Turn on the LED              setLedValue(true);              return true;          }            return super.onKeyDown(keyCode, event);      }        @Override      public boolean onKeyUp(int keyCode, KeyEvent event) {          if (keyCode == KeyEvent.KEYCODE_SPACE) {              // Turn off the LED              setLedValue(false);              return true;          }            return super.onKeyUp(keyCode, event);      }        /**       * Update the value of the LED output.       */      private void setLedValue(boolean value) {          try {              mLedGpio.setValue(value);          } catch (IOException e) {              Log.e(TAG, "Error updating GPIO value", e);          }      }        @Override      protected void onDestroy() {          super.onDestroy();            if (mButtonInputDriver != null) {              mButtonInputDriver.unregister();              try {                  mButtonInputDriver.close();              } catch (IOException e) {                  Log.e(TAG, "Error closing Button driver", e);              } finally {                  mButtonInputDriver = null;              }          }            if (mLedGpio != null) {              try {                  mLedGpio.close();              } catch (IOException e) {                  Log.e(TAG, "Error closing LED GPIO", e);              } finally {                  mLedGpio = null;              }              mLedGpio = null;          }      }  }</pre>    <p>使用 Button driver 对 LED 灯进行开关操作。</p>    <pre>  package com.geekdev.alpha.androidthings;    import android.os.Build;    import com.google.android.things.pio.PeripheralManagerService;    import java.util.List;    /**   * Created by Alpha.   */      public class BoardDefaults {      private static final String DEVICE_EDISON_ARDUINO = "edison_arduino";      private static final String DEVICE_EDISON = "edison";      private static final String DEVICE_RPI3 = "rpi3";      private static final String DEVICE_NXP = "imx6ul";      private static String sBoardVariant = "";        /**       * Return the GPIO pin that the LED is connected on.       * For example, on Intel Edison Arduino breakout, pin "IO13" is connected to an onboard LED       * that turns on when the GPIO pin is HIGH, and off when low.       */      public static String getGPIOForLED() {          switch (getBoardVariant()) {              case DEVICE_EDISON_ARDUINO:                  return "IO13";              case DEVICE_EDISON:                  return "GP45";              case DEVICE_RPI3:                  return "BCM6";              case DEVICE_NXP:                  return "GPIO4_IO21";              default:                  throw new IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE);          }      }        /**       * Return the GPIO pin that the Button is connected on.       */      public static String getGPIOForButton() {          switch (getBoardVariant()) {              case DEVICE_EDISON_ARDUINO:                  return "IO12";              case DEVICE_EDISON:                  return "GP44";              case DEVICE_RPI3:                  return "BCM21";              case DEVICE_NXP:                  return "GPIO4_IO20";              default:                  throw new IllegalStateException("Unknown Build.DEVICE " + Build.DEVICE);          }      }        private static String getBoardVariant() {          if (!sBoardVariant.isEmpty()) {              return sBoardVariant;          }          sBoardVariant = Build.DEVICE;          // For the edison check the pin prefix          // to always return Edison Breakout pin name when applicable.          if (sBoardVariant.equals(DEVICE_EDISON)) {              PeripheralManagerService pioService = new PeripheralManagerService();              List<String> gpioList = pioService.getGpioList();              if (gpioList.size() != 0) {                  String pin = gpioList.get(0);                  if (pin.startsWith("IO")) {                      sBoardVariant = DEVICE_EDISON_ARDUINO;                  }              }          }          return sBoardVariant;      }  }</pre>    <p>运行到如下的 Raspberry Pi 3 中,使用按钮来控制 LED 灯。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4da99db533dcb0ce8c5170861debdea3.jpg"></p>    <p> </p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s?__biz=MzAwODY4OTk2Mg==&mid=2652040619&idx=1&sn=30aa2b9f34a6574f4d22ce30bd15665e&chksm=808d4deeb7fac4f887dce4f4dbb67319c5161705113b43905843fee237154306405e5b425722#rd</p>    <p> </p>