Android Wear开发 - 数据通讯 - 第三节 : 事件处理

http://developer.android.com/training/wearables/data-layer/events.html

  以下是本人在学习官方开发文档时的笔记,主要是翻译为主,并在中间会插入一些自己的总结与研究,希望对读者有所帮助.

本文分为2大部分:
Section1 : 如何获取数据通讯的结果.
Section2 : 如何监听数据层中的数据事件.
其中Section2分为2模块:
  1. 继承WearableListenerService;
  2. Activity实现数据接口.

Section 1 : Wait for the Status of Data Layer Calls- 等待数据操作结果

  在进行数据通讯的时候,有时候会返回一个PendingResult对象,例如调用了putDataItem方法.一旦PendingResult对象被构建了,那么数据操作就会在后台队列中.你可以选择是否对这个操作结果进行处理.PendingResult对象可以让你获取到操作结果,无论是同步还是异步.

Asynchronously waiting-异步等待

若你是在UI线程中执行数据操作,那么小心阻塞问题.在这里可以使用回调监听的方式来实现异步等待:

pendingResult.setResultCallback(new ResultCallback<DataItemResult>() {
    @Override
    public void onResult(final DataItemResult result) {
        if(result.getStatus().isSuccess()) {
            Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
        }
    }
});

Synchronously waiting-同步等待

若你在独立的后台服务进程中进行数据操作,那么可以使用同步等待的方式来处理操作结果,在获取到处理结果前都会阻塞住进程.

DataItemResult result = pendingResult.await();
if(result.getStatus().isSuccess()) {
    Log.d(TAG, "Data item set: " + result.getDataItem().getUri());
}

Section 2 : Listen for Data Layer Events- 监听数据层事件

因为在手机和手表的数据通讯同步的,所以通常需要监听一些重要的事件,如数据创建,消息接收,通讯的连接.

监听数据通讯,可以通过以下两种方式实现:

  • 创建一个继承自WearableListenerService的Service
  • 创建一个实现了DataApi.DataListener数据接口的Activity

1.With a WearableListenerService

使用情景

  一般而言都会在手机端和手表端都构建一个这样的子类Service. 但如果哪一端对数据事件的监听处理没什么需求,那一端则无需构建.

  例如,你可以在手机端构建和传递数据给手表,手表则监听这些数据事件来更新自身界面.但手表端只是单方面的获取数据,不会对数据进行做任何修改,那么,手机端则无需监听数据通讯事件.

方法介绍

接下来是介绍WearableListenerService的一些重要事件方法:

  • onDataChanged() :增,删,改,这三种事件都会调用这个接口.并且是两端都会被触发调用.→双向
  • onMessageReceived():消息从一端发送,会调用另一端的接口.→单向
  • onPeerConnected() , onPeerDisconnected():当两端进行连接或者断开的时候会触发.改变一端的连接状态都会调用两端的接口.→双向

实现步骤

  1. 继承WearableListenerService
  2. 监听数据通讯事件
  3. 在Manifest中声明,并添加intent filter监听com.google.android.gms.wearable.BIND_LISTENER这个动作

代码样例

public class DataLayerListenerService extends WearableListenerService {

    private static final String TAG = "DataLayerSample";
    private static final String START_ACTIVITY_PATH = "/start-activity";
    private static final String DATA_ITEM_RECEIVED_PATH = "/data-item-received";

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "onDataChanged: " + dataEvents);
        }
        final List events = FreezableUtils
                .freezeIterable(dataEvents);

        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .build();

        ConnectionResult connectionResult =
                googleApiClient.blockingConnect(30, TimeUnit.SECONDS);

        if (!connectionResult.isSuccess()) {
            Log.e(TAG, "Failed to connect to GoogleApiClient.");
            return;
        }

        // Loop through the events and send a message
        // to the node that created the data item.
        for (DataEvent event : events) {
            Uri uri = event.getDataItem().getUri();

            // Get the node id from the host value of the URI
            String nodeId = uri.getHost();
            // Set the data of the message to be the bytes of the URI.
            byte[] payload = uri.toString().getBytes();

            // Send the RPC
            Wearable.MessageApi.sendMessage(googleApiClient, nodeId,
                    DATA_ITEM_RECEIVED_PATH, payload);
        }
    }
}

注解 :

  1. final List events = FreezableUtils .freezeIterable(dataEvents); 

    这里的作用是通过工具类FreezableUtils将数据对象dataEvents转换成不可修改的类型,以避免在处理数据的过程中,数据发生改变.

  2. ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);

    阻塞当前线程,在30秒内获取连接状态,否则视为超时连接.因为onDataChange属于异步线程中,所以这里不会导致主线程阻塞.注意区分,这里是获取和googleApiClient的连接,而Section One中是发送数据的结果.

Manifest声明

<service android:name=".DataLayerListenerService">
  <intent-filter>
      <action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
  </intent-filter>
</service>

Permissions within Data Layer Callbacks

注意点

数据回调接口中的权限问题
  为了回调数据事件接口,Google Play会绑定你的Service并且通过IPC的方式调用.这也导致了你的回调接口继承了调用进程的权限.
若想要在回调接口中做某些特权操作,你会发现安全验证失败了,你会发现回调接口中打印出来的进程id,是在触发回调接口的进程的id,而不是你的应用的进程.
  为了解决这个问题,先调用clearCallingIdentity()来重置id,恢复为应用进程id;再执行你所需要的操作;最后再调用恢复为restoreCallingIdentity()调用者的id.

long token = Binder.clearCallingIdentity();
try {
    performOperationRequiringPermissions();
} finally {
    Binder.restoreCallingIdentity(token);
}

WearableListenerService的深入研究:

以下关于生命周期的测试环境是在模拟器上,在其他环境上可能略有差异.

  1. 生命周期 :完全由Android Wear控制 !
  • 前提 : 在Manifest中进行了声明,监听了com.google.android.gms.wearable.BIND_LISTENER这个Action
  • 现象 : 在手表和手机断开的情况下,安装了Demo,Service没有调用onCreate方法.当连接上,则立即调用onCreate方法.
  • 生命周期流程:
    连接手机 : onCreate > onPeerConnected
    操作过程 : 若Service没有接收到消息,以最后一次被回调为准,约8~12秒左右后会自杀,调用onDestroy.
    断开手机 : 若Service已死 : onCreate > onPeerDisconnected > onDestroy(等待8~12秒);若Service处于活跃状态,则调用后面2个方法.
  1. 自身已经实现了DataApi.DataListener,MessageApi.MessageListener,NodeApi.NodeListener这3个接口.

总结 :

 1.WearableListenerService是由Android Wear控制;

 2.生命周期较短,在停止操作8~12秒内消亡

 3.不能理解为手机端和手表端的连接,而应该是理解为监听这个连接 : 因为断开两端的连接,不会立刻调用onDestroy方法

 4.在连接后台发生状态改变,会被立即地创建,调用回调接口,以处理应用业务

2.With a Listener Activity

方法介绍

若你的应用只是需要在用户打开时监听数据通讯事件,而不需要在后台监听数据改变,那么可以实现以下接口来实现你的需求.

  • DataApi.DataListener
  • MessageApi.MessageListener
  • NodeApi.NodeListener

实现步骤

接下来是创建一个监听数据通讯事件的Activity

  1. 实现接口 : 实现上面列举的接口(根据需求来定,不需要全部都实现)
  2. 创建服务对象 : 在onCreate方法中创建一个GoogleApiClient对象来实现与数据通讯的连接.
  3. 连接服务 : 在onStart方法中调用GoogleApiClient的connect方法来连接服务
  4. 注册监听器 : 当GoogleApiClient连接上了服务,会回调onConnected方法,那么我们就可以在这里中注册监听器,来监听我们所关心的通讯事件.
  5. 反注册监听器,并断开服务 : 在onStop方法中,反注册之前注册的监听器,然后再断开GoogleApiClient服务连接.
  6. 实现事件回调接口 : 根据注册的监听器实现接口,处理相关的需求.

代码样例

以下是一个实现了DataApi.DataListener的样例:

public class MainActivity extends Activity implements
        DataApi.DataListener, ConnectionCallbacks, OnConnectionFailedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (!mResolvingError) {
            mGoogleApiClient.connect();
        }
    }

   @Override
    public void onConnected(Bundle connectionHint) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Connected to Google Api Service");
        }
        Wearable.DataApi.addListener(mGoogleApiClient, this);
    }

    @Override
    protected void onStop() {
        if (null != mGoogleApiClient && mGoogleApiClient.isConnected()) {
            Wearable.DataApi.removeListener(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }
        super.onStop();
    }

    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_DELETED) {
                Log.d(TAG, "DataItem deleted: " + event.getDataItem().getUri());
            } else if (event.getType() == DataEvent.TYPE_CHANGED) {
                 Log.d(TAG, "DataItem changed: " + event.getDataItem().getUri());
            }
        }
    }
时间: 2024-10-09 12:05:35

Android Wear开发 - 数据通讯 - 第三节 : 事件处理的相关文章

Android Wear开发 - 数据通讯 - 事件处理

http://developer.android.com/training/wearables/data-layer/events.html#Wait Section 1 : Wait for the Status of Data Layer Calls- 等待数据操作结果 You'll notice that calls to the data layer API sometimes return a PendingResult, such as putDataItem(). As soon

Android Wear开发 - 数据通讯 - 第二节 : 数据的发送与接收

本节由介绍3种数据的发送接收:1.Data Items : 比特类型数据,限制100KB以内2.Assets : 资源类型数据,大小无上限3.Message : 发送消息,触发指令 http://developer.android.com/training/wearables/data-layer/data-items.html 1.Syncing Data Items DataItem定义了同步手机和手表的数据接口.一个DataItem对象一般包括下面2个部分: 负载 : 一个比特类型数组,支

Android Wear开发 - 数据通讯 - 第一节 : 连接数据层

http://developer.android.com/training/wearables/data-layer/accessing.html Accessing the Wearable Data Layer-数据层连接 GoogleApiClient是一个用于整合所有谷歌服务的入口,想要连接数据层,需要构建一个对象.GoogleApiClient提供了一个builder方法简化了构建对象的步骤. GoogleApiClient mGoogleApiClient = new GoogleA

Android Wear开发 - 数据通讯 - 第四节 : 数据封装(解决不能序列化问题)

一. 前言 背景 一开始笔者在研究数据发送与接收的时候,看到Wear数据类DataMap除了可以put基本类型外,还有个fromBundle方法来构建一个DataMap对象.所以一口气的将原本功能上的序列化对象传递过去,结果手表端一直都收不到消息. 问题原因 后来查阅了开发者文档,发现这个Bundle并没有我们在Intent中传递数据的那么强大,它并不支持序列化!先附上开发者文档的说明: Returns a DataMap from a Bundle. The input Bundle is e

IDEA搭建Android wear开发环境,Android wear,I&#39;m comming!

随着google发布了android wear这个东西,然后又有了三星的gear,LG的G watch以及moto 360,苹果由发布了apple watch,未来可能在智能手表行业又有一场战争.当然这只是笔者的个人观点,仅供参考. 作为开发者,当然关心的是只能手表的开发了,所以我们来搭建一下android wear的开发环境吧! 搭建android wear开发环境,我们需要以下的软件Intellij 13.1.3,android-sdk 23.0.02. 首先需要下载安装好android-s

Android Wear 开发入门

大家好,我是陆嘉杰,我是一名Android开发者.我想和大家进行一些技术交流,希望越来越多的人能和我成为好朋友. 大家都知道,智能手表是下一个开发的风口,而这方面的技术又属于前沿,所以和大家分享下Android Wear的开发流程. 首先,我推荐大家使用Android Studio来进行Wear的开发,这也是谷歌推荐的,本次讲授过程也将以Android Studio作为开发集成环境进行. 下面我们来创建Android Wear项目. 请注意,Android Wear项目中同时包含mobile和w

Android Wear 开发入门——如何创建一个手机与可穿戴设备关联的通知(Notification)

创建通知 为了创建在手机与可穿戴设备中都能展现的通知,可以使用 NotificationCompat.Builder.通过该类创建的通知,系统会处理该通知是否展现在手机或者穿戴设备中. 导入必要的类库 在开发之前首先需要导入以下类库 importandroid.support.v4.app.NotificationCompat; importandroid.support.v4.app.NotificationManagerCompat; importandroid.support.v4.app

想做Android Wear开发?你得先搞明白这四件事

手环和手表的腕上穿戴之争,随着Apple Watch发布和Android Wear不断完善而告一段落.尽管续航上略有缺陷,但手表以其类似手机可扩展的生态环境赢得了众多巨头的支持. Google曾透露,Android Wear发布三周左右应用数就超过了Google Glass,并将有数以千计的app不断加入.Apple Watch发布的该月内,雷锋网驻硅谷的记者发现已有公司开始招聘相关开发者. 国外的开发者生态一向积极,国内虽明面上动静不大,但实际各家也已经都在暗自开动.鉴于Apple Watch

在Android Wear开发中使用蓝牙调试同时操作手机与手表设备

在开发Android Wear应用过程中需要对手表和手机进行同时操作,可以通过蓝牙同时对手机和手表进行操作. 1 打开手表和手机的调试设置 打开手机的usb调试 打开手表设置的开发者选项,选中Debug over Bluetooth   如果是首次使用手表调试,需要在Setting中找到About,单击7次打开开发者选项 2 连接手表到开发工具 在手机端打开Android Wear App,进入Setting,选中Debugging over Bluetooth,会发现当前状态是 <span s