前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android Auto开发初探

Android Auto开发初探

作者头像
QQ音乐技术团队
发布2018-01-31 17:55:20
9.5K0
发布2018-01-31 17:55:20
举报

一、Android Auto 概述

最近物联网是比较热门的话题,做为物联网重要的一部份车联网也被众多汽车厂商越来越重视,纷纷推出自己的车联网系统。谷歌也是看到了车联网的重要性于2014年6月推出了Android Auto系统。它是谷歌生态系统的一个重要终端。说它是个系统其实并不完全准确,因为谷歌并没有提供完整的操作系统,而是提供了一套Android Auto SDK给汽车厂商。汽车厂商需要把这套Android Auto SDK 集成到他们自己的车载操作系统中。当然你也可以用这个SDK集成到谷歌的Android系统中。为了构建Android Auto生态圈,谷歌与汽车厂商共同组建“开放汽车联盟”(Open Automotive Alliance),已经有40多个汽车厂商加入。

Android Auto主要提供了语音,导航,IM,音乐,电话等几大核心功能。提供开发接口的目前只有音乐,IM两类应用。

二、Android Auto 使用方法

Android Auto是如何与手机连接并使用的呢?你必须使用Android 5.0以上手机并支持google api(原生系统),通过USB(最新版本支持Wifi)与支持Android Auto 的车机连接,当你在车机上选择音乐时,在音乐界面里会列出手机上支持Android Auto 的音乐应用,你选择连接某个应用。这样就可以播放音乐了。如下图:

三、Android Auto 连接方式及原理

Android Auto车机与手机连接,是同时通过USB(或者Wifi)及蓝牙来实现。蓝牙只用来通话作用,USB(或者Wifi)主要用来传送应用图像、车机的触摸事件及音频数据。所有的程序运行都在手机端,车机端只是用来显示及回传事件。具体原理如下图:

上图左边是车机,右边是手机。从这个图我们可以看出来,手机这边在Android 5.0及以上系统已经集成了Android Auto的SDK。车机侧需要使用Android Auto的SDK集成到车机系统,比如:WinCE,QNX,Linux等。但通话还是通过标准的蓝牙HFP来实现。

四、Android Auto应用开发

刚才已经说了,目前Android Auto支持开发的接口应用只有音乐和消息两类应用。我这里主要讲一下音乐的开发过程。

1.创建新应用支持Android Auto

以Android Studio为例,这个与创建普通应用差别不大,但有一个地方需要注意,如下图:

在选择你要运行的平台时,选择支持Android Auto。

这里需要你选择要开发的音乐应用还是消息应用,这里我们选择音乐类。这样就完成了支持Android Auto音乐功能应用的创建。

2.现有应用中加入Android Auto的支持

直接在现在项目中选择File->New->Android Auto->Media service就可以了。注意此时你的项目最小SDK必须是21以上,否则Media service为灰色,你无法创建。具体如下图:

3.支持Android Auto的应用配置

以上两种方式无论你按那种方式完成,我们都会发现在你应用的XML目录里新建一个xml,比如:automotive_app_desc.xml,打开XML有以下内容:

<?xml version="1.0" encoding="utf-8"?>
<automotiveApp>
    <uses name="media"/>
</automotiveApp>

这里标识了应用的类型,这里是media,表示是支持Android Auto的音乐应用。 在AndroidManifest.xml中加入以下内容来标识应用支持Android Auto功能:

<application>
    ...
    <meta-data android:name="com.google.android.gms.car.application"
                       android:resource="@xml/automotive_app_desc"/>
</application>
4.Android Auto的界面定制

先来看一下Android Auto音乐类的界面

说是界面定制,实际上你除了换颜色其它什么都不能做了,如上图,你只能改变1和2的颜色,他们分别对应到res->values->styles.xml里1-colorPrimaryDark 2-colorAccent的两个值。

5.获取连接上车机的广播
IntentFilter filter = new IntentFilter("com.google.android.gms.car.media.STATUS");
BroadcastReceiver receiver = new BroadcastReceiver() {
    ...
    public void onReceive(Context context, Intent intent) {
        String status = intent.getStringExtra("media_connection_status");
        boolean  isConnectedToCar = "media_connected".equals(status);
        // adjust settings based on the connection status
    }
};

通过接收com.google.android.gms.car.media.STATUS的广播,来判断当前应用是否已经连接上了车机。

6.判断目前是否处于车机模式
public static booleanisCarUiMode(Context c) {
UiModeManageruiModeManager=(UiModeManager)c.getSystemService(Context.UI_MODE_SERVICE);
      if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR) {
          Log.d(TAG, "Running in Car mode");
          return true;
      } else {
          Log.d(TAG, "Running on a non-Car mode");
          return false;
        }
  }
7.继承实现服务MediaBrowserService

MediaBrowserService也是继承Servcie,这个服务中车机用来浏览及显示歌曲列表的功能。和一般服务一样,我们需要在AndroidManifest.xm声明服务:

<application>
    ...
    <service android:name=".QQMusicAndroidAutoService"
             android:exported="true">
        <intent-filter>
            <action android:name="android.media.browse.MediaBrowserService"/>
        </intent-filter>
    </service>
    ...
<application>

这里需要注意:exproted必须为true,允许外部调用。与普通服务最大的不同就是必须要实现两个接口:

public BrowserRooton GetRoot(String clientPackageName, intclientUid, Bundle rootHints);
public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result);

我们就是通过上面两个接口来获取歌曲列表。onGetRoot这个接口是用来获取歌曲列表根目录。第一个参数是车机获取根目录的的应用的包名,你可以根据包名来判断是否允许指定的车机应用来读取根目录信息。我们只要简单返回

return new BrowserRoot("root", null); 

就可以了。onLoadChildren这个接口是用来获取歌曲列表子目录。根据第一个参数parentMediaId来确认要获取那个目录的子目录或者歌曲列表,第二参数result是要返回的子目录或者歌曲列表。通过上面两个接口的实现,我们就可以在车机上浏览歌曲列表了。

8.播放控制

要实现播放控制,就要使用Android5.0 的全新的MediaSession,它用于播放器与控制器之间进行交互,它取代之前的RemoteControlClient。 先来看一下如何创MediaSession,具体如下:

MediaSessionmSession = new MediaSession(this, "QQMusicAndroidAuto");
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
                  MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
mSession.setCallback(new MediaSessionCallback());

这里有两个重要方法:setCallback和setFlags,我们分别来看一下。setFlags是来设置这个MediaSeccion的功能。 FLAG_HANDLES_MEDIA_BUTTONS 设置此标志可以处理媒体按钮事件。 FLAG_HANDLES_TRANSPORT_CONTROLS 设置此标志以可以处理传输控制命令 setCallback是用来设置车机操作的回调,这个回调是MediaSession的内部接口Callback,需要我们实现,比较重要的几个接口如下:

private final class MediaSessionCallback extends MediaSession.Callback {
    @Override
    public void onPlay(){};
    @Override
    public void onSeekTo(long position){};
    @Override
    public void onPlayFromMediaId(String mediaId, Bundle extras){};
    @Override
    public void onPause(){};
    @Override
    public void onSkipToNext(){};
    @Override
    public void onSkipToPrevious(){};
    @Override
    public void onCustomAction(String action, Bundle extras){};
    @Override
    public void onPlayFromSearch(final String query, final Bundle extras){};
}
onPlay:播放暂停后恢复播放调用
onSeekTo:跳转到某个时间点播放
onPlayFromMediaId:用户选定某个歌曲播放
onPause:暂停播放
onSkipToNext:播放下一首
onSkipToPrevious:播放上一首
onCustomAction:自定命令
onPlayFromSearch:搜索命令

以上各自分别实现就可以了。最后MediaBrowserServicer通过

setSessionToken(mSession.getSessionToken());

来设置MediaSession到服务。

五、Android Auto开发总结

总的来说,开发还是相对简单,只要实现几个接口就可以了,界面用户可以不用关心。对开发者来说,只要提供数据就可以了。这大大减轻了开发者的工作,快速实现功能,但这也是缺点,无法实现自己定义的界面,界面单一。

参考文档:

  1. 谷歌Android Auto开发官网: https://developer.android.com/training/auto/index.html
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-12-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 QQ音乐技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Android Auto 概述
  • 二、Android Auto 使用方法
    • 四、Android Auto应用开发
      • 1.创建新应用支持Android Auto
      • 2.现有应用中加入Android Auto的支持
      • 3.支持Android Auto的应用配置
      • 4.Android Auto的界面定制
      • 5.获取连接上车机的广播
      • 6.判断目前是否处于车机模式
      • 7.继承实现服务MediaBrowserService
      • 8.播放控制
  • 五、Android Auto开发总结
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档