首页 > 代码库 > Android 建立手机与手表数据同步机制总结
Android 建立手机与手表数据同步机制总结
Android Wear 数据同步机制总结
当手机与手表建立蓝牙连接之后,数据就可以通过Google Play Service进行传输。
同步数据对象Data Item
DataItem提供手机与手表数据存储的自动同步,一个DataItem对象由其创建者与路径组成的URI所确定。一个DataItem对象为手机和手表提供了一个数据通路,开发者通过改变指定的DataItem实现手机和手表的数据自动同步。
访问数据层API
DataItem可以提供手机和手表数据的保存,改变该对象的操作则依赖数据层API(the Data Layer APIs),也就是说,在改变DataItem数据之前,需要先访问数据层,获得一个GoogleApiClient实例,从而能够使用数据层API。
下面是实例化GoogleApiClient的代码
GoogleApiClient mGoogleAppiClient = new GoogleApiClient.Builder(this) .addConnectionCallbacks(new ConnectionCallbacks() { @Override public void onConnected(Bundle connectionHint) { Log.d(TAG, "onConnected: " + connectionHint); // Now you canuse the data layer API } @Override public void onConnectionSuspended(int cause) { Log.d(TAG, "onConnectionSuspended: " + cause); } }) .addOnConnectionFailedListener(new OnConnectionFailedListener() { @Override public void onConnectionFailed(ConnectionResult result) { Log.d(TAG, "onConnectionFailed: " + result); } }) .addApi(Wearable.API) .build();
在使用数据层Api的之前,需要先调用connect()方法,如果成功则会回调onConnected()方法,否则回调onConnectionFailed()。
同步DataItems
GoogleApiClient连接成功后,就可以通过DataItem进行数据同步了。
一个DataItem包括连个部分,一个是Payload,这是一个字节数组,可以通过序列化或者反序列化保存需要的数据类型和对象;另一个是Path,这是一个唯一的字符串,由反斜杠开头,区别不同的DataItem。
通常在开发过程中是使用DataMap类实现DataItem接口,类似Bundle键值对的存储方式。
下面是使用的DataMap步骤:
1、 创建PutDataMapRequest对象,为DataItem设置path值;
2、 使用put…()方法为DataMap设置需要的数据;
3、 调用PutDataMapRequest.asPutDataRequest()创建PutDataRequest对象;
4、 调用DataApi.putDataItem()请求系统创建DataItem。
如果此时手机和手表没有建立连接,则会将数据保存在Buffer中,等下次连接后会发送到另一方。
下面是使用DataMap创建DataItem的方法
PutDataMapRequest dataMap = PutDataMapRequest.create("/count"); dataMap.getDataMap().putInt(COUNT_KEY, count++); PutDataRequest request = dataMap.asPutDataRequest(); PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi .putDataItem(mGoogleApiClient, request);
监听数据层事件
由于数据层同步或发送的数据连接手机和手表,所以经常需要获知何时DataItem被创建以及手机与手表什么时候连接或断开等事件。
监听数据层时间可以使用两种方式,一种是继承WearableListenerService,一种是在Activity中实现DataApi.DataListener。无论使用两种方式的哪种,可以重写其需要的回调方法执行相应的操作。
1、 使用WearableListenerService
该service在手机和手表端都可以使用,如果在一方不需要监听数据层时间可以不适用该服务。
例如,可以在手机端接收和设置DataItem,然后在手表端实现该服务,监听数据层的事件,从而修改手表的UI。
WearableListenerService提供回调接口onDataChanged()处理DataItem的变化,当DataItem被创建、更改或删除,手机和手表的该事件将被触发。
下面是使用WearableListenerService的方法
1、 创建一个类继承WearableListenerService;
2、 监听需要的事件,如onDataChanged();
3、 在配置文件中声明一个intentfilter通知系统监听WearableListenerService,这样在系统需要的时候就会绑定WearableListenerService。
下面代码是一个简单的WearableListenerService实现。
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); } } }
下面代码是配置文件中声明的intentfilter
<service android:name=".DataLayerListenerService"> <intent-filter> <action android:name="com.google.android.gms.wearable.BIND_LISTENER" /> </intent-filter> </service>
使用DataApi.DataListener监听数据层
如果不需要后台长时间进行监听,可以使用DataApi.DataListener进行监听,下面是使用该方式的方法。
1、 使用DataApi.DataListener接口
2、 在onCreate中创建 GoogleApiClient,访问数据层API
3、 在onStart中调用connect()连接Google PlayService
4、 但连接上GooglePlay Service后,系统调用onConnected(),通知Google Play service该activity监听数据层事件
5、 在onStop中调用DataApi.removeListener()
6、 实现 onDataChanged()回调
下面是使用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()); } } }
获取手机通知大家的服务
Android提供了一个服务类接口NotificationListenerService,继承该服务,可以获取手机中应用发起的通知,在配置文件中需要添加如下声明和权限
<service android:name=".NotificationListener" android:label="@string/service_name" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service>
这样在系统设置中会出现一个是否允许该服务捕获通知的选项,在设置--安全与隐私--通知读取权限
该服务有两个抽象方法需要实现,分别是当有通知发起与通知被销毁,都会触发其回调方法。
public class NotificationCollectorService extends NotificationListenerService { @Override public void onNotificationPosted(StatusBarNotification sbn) { } @Override public void onNotificationRemoved(StatusBarNotification sbn) { } }
也就是说当系统发现某应用产生通知或者用户删除某通知,都会回调该服务的这两个函数,函数的参数StatusBarNotification包含着该通知的具体信息。
如果是在Android Wear开发中,使用该方法捕获手机的通知,然后同步到手表中,就是使用该服务进行的中转。
通知同步
接收到的通知以StatusBarNotification对象形式传递给回调函数onNotificationPosted(),
调用StatusBarNotification对象的公共方法,分别取出StatusBarNotification中的PackageName、Tag、Id、notification对象和PostTime,通过这些值去创建DataItem。