ANCS本质上就是BLE的使用:
协议网络上介绍很清楚,暂且不说了,最最重要的就是解析数据:
ANCS数据解析工具
关键代码:
/**
*连接gatt server结果处理回调类
*/
private classLocalBluetoothGattCallbackextendsBluetoothGattCallback {
@Override
public voidonConnectionStateChange(BluetoothGatt gatt, intstatus, intnewState) {
Log.v(TAG," BluetoothGatt status: "+ status);
if(newState == BluetoothProfile.STATE_CONNECTED) {
isConnected=true;
Log.v(TAG,"ancs connected");
mStateIntent.putExtra("state",Constants.CONNECT_SUCCESS);
sendBroadcast(mStateIntent);
mConnectedGatt= gatt;
gatt.discoverServices();
mBluetoothLeScanner=mBluetoothAdapter.getBluetoothLeScanner();
mBluetoothLeScanner.stopScan(mScanCallback);
}
if(newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG,"ancs disconnected");
isConnected=false;
mConnectedGatt.disconnect();
mConnectedGatt.close();
mStateIntent.putExtra("state",Constants.DISCONNECTED);
sendBroadcast(mStateIntent);
mBinder.connectToGattServer();
}
}
@Override
public voidonServicesDiscovered(BluetoothGatt gatt, intstatus) {
Log.v(TAG," BluetoothGatt status: "+ status);
SystemClock.sleep(1000);
BluetoothGattService ancsService = gatt.getService(
UUID.fromString(service_ancs));
if(ancsService ==null) {
Log.d(TAG,"ANCS cannot find");
}else{
Log.d(TAG,"ANCS find");
mDataSourceChar= ancsService.getCharacteristic(
UUID.fromString(Constants.characteristics_data_source));
mPointControlChar= ancsService.getCharacteristic(
UUID.fromString(characteristics_control_point));
mNotificationSourceChar= ancsService.getCharacteristic(
UUID.fromString(Constants.characteristics_notification_source));
setNotificationEnabled(mDataSourceChar);
}
}
@Override
public voidonDescriptorWrite(BluetoothGatt gatt,BluetoothGattDescriptor descriptor,
intstatus) {
Log.v(TAG," BluetoothGatt status: "+ status);
// Notification source
if(descriptor.getCharacteristic()
.getUuid()
.equals(UUID.fromString(Constants.characteristics_data_source))) {
setNotificationEnabled(mNotificationSourceChar);
Log.d(TAG,"ancs data_source订阅成功");
}
if(descriptor.getCharacteristic()
.getUuid()
.equals(UUID.fromString(
Constants.characteristics_notification_source))) {
Log.d(TAG,"ancs notification_source订阅成功");
}
}
@Override
public voidonCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, intstatus) {
}
@Override
public voidonCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, intstatus) {
Log.v(TAG," BluetoothGatt status: "+ status);
Log.v(TAG,"onCharacteristicWrite");
if(characteristics_control_point.equals(characteristic.getUuid()
.toString())) {
Log.d(TAG,"control_point Write successful");
}
}
@Override
public voidonDescriptorRead(BluetoothGatt gatt,BluetoothGattDescriptor descriptor,
intstatus) {
Log.d(TAG,"onDescriptorRead");
}
@Override
public voidonCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic) {
if(Constants.characteristics_notification_source.equals(characteristic.getUuid()
.toString())) {
mCommonProcessor.init();
mAppNameProcessor.init();
Log.d(TAG,"notification_source Changed");
byte[] nsData = characteristic.getValue();
notification=newNotification(nsData);
Log.w(TAG,"nsData[0] = "+ nsData[0]);
Log.w(TAG,"nsData[0] & 0x02 = "+ (nsData[0] &0x02));
if((nsData[0] &0x02) >0) {
Log.v(TAG," > 0: "+notification.toString());
}else{
Log.v(TAG," <= 0: getMoreAboutNotification");
getMoreAboutNotification(nsData);
}
}
if(Constants.characteristics_data_source.equals(characteristic.getUuid()
.toString())) {
Log.i(TAG,"onCharacteristicChanged: "+ characteristic.getValue().length);
handleCharaData(characteristic.getValue());
}
}
}
private voidhandleCharaData(byte[] charaData) {
Log.v(TAG,"characteristics_data_source changed");
if(charaData ==null|| charaData.length==0) {
return;
}
// parse appId appTitle appMessage
if(bytes==null) {
Log.d(TAG,"bytes == null");
mCommonProcessor.processing(charaData);
if(mCommonProcessor.is_finish_processing()) {
notification.setPackageName(mCommonProcessor.get_ds_app_id());
notification.setTitle(mCommonProcessor.get_ds_title());
notification.setMessage(mCommonProcessor.get_ds_message());
Log.d(TAG,notification.toString());
mCommonProcessor=newCommonProcessor();
charaData =null;
if(notification.getPackageName() ==null||notification.getTitle() ==null||
notification.getMessage() ==null) {
mConnectedGatt.disconnect();
return;
}
getAppAttributes(notification.getPackageName());
}
}
// parse appName
if(bytes!=null&& charaData !=null) {
Log.d(TAG,"bytes != null");
mAppNameProcessor.setPackageLength(bytes.length);
mAppNameProcessor.processing(charaData);
if(mAppNameProcessor.is_finish_processing()) {
bytes=null;
notification.setAppName(mAppNameProcessor.get_ds_app_name());
Log.d(TAG,notification.toString());
mAppNameProcessor=newAppNameProcessor();
if(mOnReceiveNotificationListener!=null&¬ification.getAppName() !=null
&¬ification.getPackageName() !=null) {
mOnReceiveNotificationListener.OnReceiveNotification(notification);
}else{
mConnectedGatt.disconnect();
isConnected=false;
}
}
}
}
为了保证尽量收到数据并且能解析成功,那么只要数据解析异常就断开ble重新订阅ANCS;
如果哪位大神有好的办法可以給指正一下O(∩_∩)O哈!