1.1 客户端简介
1.1.1 界面操作
进入页面后,会自动进行扫描,以发现周围可用蓝牙设备。
在搜索蓝牙设备的多层中,会出现圆环形进度条,当设定的搜索时间到了之后,或者我们选中了被扫描到的设备,该进度条消失,“停止扫描”转换会“扫描”。
点击扫描到的设备进入控制设备控制页面。
这个页面是我们的主要控制界面,我们可以在这个界面看到手环为我们提供的一些数据。
这个下拉菜单可以同过点击也可以通过设备的menu按键获得,主要用来控制计步器。
“断开连接”的按钮的作用是显示现在设备的连接情况,如果不是已经连接了设备,那么可以看到“连接”按钮,可以通过“连接”按钮来实现和蓝牙设备的连接,如果是已经连接了的设备,可以看到“断开连接”,可以通过“断开连接”来断开和蓝牙设备的连接。
设置时间按钮,可以将我们的设备上的时间,同步到蓝牙手环上。
1.1.2 工程结构
Src为java文件目录。
Res为资源文件目录。
AndroidManifest.xml为配置文件。
在src目录下:
Acticity包中,是工程的两个Activity活动相关的代码。
Service包中,是工程启动的服务相关代码。
Tools包中,是工具类相关代码。
UI包中,是自定义界面相关代码。
在资源文件夹中,包含了Layout,values,Drawable等资源文件夹:
其中layout中是布局文件,menu中,是菜单栏的布局文件,values中包括color,string,styles等设置。
1.2 代码分析
1.2.1 界面代码分析
本工程一共有两个主要显示界面,分别为扫描设备,和设备控制,通过两个活动—Activity来进行设置与控制。
扫描-----界面ScanningActivity
在onCreate中设定标题。
Java Code
public void onCreate(Bundle savedInstanceState){
getActionBar().setTitle(R.string.title_devices);
}
在扫描的时候,menu显示为“停止扫描”,并显示圆环进度条以提醒等待;在扫描结束时,menu显示为“扫描”。在界面中使用ListView展示扫描到的设备。
Java Code
/**
* 创建Menu菜单栏
*/
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanning)
{
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else{
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(
R.layout.actionbar_indeterminate_progress);
}
return true;
}
/**
* Menu菜单栏被选择时
*/
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.menu_scan:
mLeDeviceListAdapter.clear();
scanLeDevice(true);
break;
case R.id.menu_stop:
scanLeDevice(false);
break;
}
return true;
}
ListView显示扫描到的设备。
Java Code
@Override
protected void onResume(){
super.onResume();
if (!mBluetoothAdapter.isEnabled()){
if (!mBluetoothAdapter.isEnabled()){
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
}
mLeDeviceListAdapter = new LeDeviceListAdapter();
setListAdapter(mLeDeviceListAdapter);
scanLeDevice(true);
}
点击ListView中的设备跳转到控制界面。
Java Code
@Override
protected void onListItemClick(ListView l, View v, int position, long id){
final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);
if (device == null) return;
final Intent intent = new Intent(this, DeviceControlActivity.class);
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME, device.getName());
intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS, device.getAddress());
if (mScanning) {
mBluetoothAdapter.stopLeScan(mLeScanCallback);
mScanning = false;
}
startActivity(intent);
}
设备控制-------界面DeviceControlActivity
在Activity中设置主界面:
Java Code
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_device_control);
initShow();
btnTime.setOnClickListener(this);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
Toast.makeText(this, mDeviceAddress, Toast.LENGTH_SHORT).show();
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
}
菜单栏包括两部分,一部分是显示“连接”或“断开连接”,一部分是隐藏的用以对计步功能进行设置。
Java Code
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.device_control, menu);
if (connected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
}else{
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item){
int id = item.getItemId();
switch (id){
case R.id.setting_gogal:
showGogalDialog();
break;
case R.id.setting_reset:
showResetDialog();
break;
case R.id.setting_stop:
showStopDialog();
break;
case R.id.menu_connect:
mBleService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBleService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
default:
break;
}
return super.onOptionsItemSelected(item);
}
1.2.2 蓝牙连接代码分析
扫描
蓝牙连接建立的过程中,首先要先扫描到设备。
在ScanningActivity中:
Java Code
public class ScanningActivity extends ListActivity{
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;
private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler();
//PackageManager.FEATURE_BLUETOOTH_LE
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
finish();
}
//BluetoothManager
final BluetoothManager bluetoothManager =
(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
//BluetoothAdapter
if (mBluetoothAdapter == null){
Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
finish();
return;
}
}
private void scanLeDevice(final boolean enable){
if (enable){
mHandler.postDelayed(new Runnable(){
@Override
public void run(){
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
}else{
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
invalidateOptionsMenu();
}
private BluetoothAdapter.LeScanCallback mLeScanCallback =
new BluetoothAdapter.LeScanCallback(){
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord){
runOnUiThread(new Runnable(){
@Override
public void run(){
mLeDeviceListAdapter.addDevice(device);
mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
}
连接蓝牙
在扫描结束的时候,点击ListView上的设备名称的时候,将设备MAC通过Intent传递给DeviceControlActivity,在控制页面启动BLEService服务,控制设备连接。
Java Code
public class DeviceControlActivity extends Activity implements View.OnClickListener
{
private final String TAG = "Device";
private final Double G = 9.8;
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private static String UUID_date = "0000180f-0000-1000-8000-00805f9b34fb";
private static String UUID_D = "00002a19-0000-1000-8000-00805f9b34fb";
private String UUID_write = "00001802-0000-1000-8000-00805f9b34fb";
private String UUID_W = "00002a06-0000-1000-8000-00805f9b34fb";
private Phone mPhone;
private BLEService mBleService;
private String mDeviceAddress;
private String mDeviceName;
private int xBefore, yBefore, zBefore;
private CircleBar mCircleBar;
private Button btnTime;
private TextView txvX, txvY, txvZ, txvPower;
private EditText gogalInput;
private boolean connected = false;
private boolean first = true;
private BluetoothGattCharacteristic mNotifyCharacteristic;
protected void onCreate(Bundle savedInstanceState){
//...
super.onCreate(savedInstanceState);
//bindService启动服务,注册广播接收器实现服务与活动之间的通信
Intent gattIntent = new Intent(this, BLEService.class);
bindService(gattIntent, mServiceConnection, BIND_AUTO_CREATE);
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
//实例化一个电话模型。
mPhone = new Phone(this);
}
@Override
protected void onResume(){
super.onResume();
registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBleService != null){
final boolean result = mBleService.connect(mDeviceAddress);
Log.d(TAG, "Connect request result=" + result);
}
}
//服务连接
private final ServiceConnection mServiceConnection = new ServiceConnection(){
@Override
public void onServiceDisconnected(ComponentName name){
}
@Override
public void onServiceConnected(ComponentName name, IBinder service){
mBleService = ((BLEService.LocalBinder) service).getService();
if (!mBleService.initialize()){
Log.e(TAG, "unable to initilize Bluetooth Service");
finish();
}
mBleService.connect(mDeviceAddress);
}
};
}
BLEService服务代码如下:
Java Code
public class BLEService extends Service{
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private String mBluetoothDeviceAddress;
public BluetoothGatt mBluetoothGatt;
public final static String ACTION_TIME_SETTING = "com.farsight.bluetooth.le.ACTION_TIME_SETTING";
public final static String ACTION_GATT_CONNECTED = "com.farsight.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED = "com.farsight.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.farsight.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE = "com.farsight.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA = "com.farsight.bluetooth.le.EXTRA_DATA";
public final static UUID UUID_FARSIGHT_SMART_WRIST = UUID.fromString(GattAttributes.FARSIGHT_SMART_WRIST);
/**
* 回调函数
*/
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback(){
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState){
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED){
mBluetoothGatt.getServices();
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
}else if (newState == BluetoothProfile.STATE_DISCONNECTED){
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
//发现新服务
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status){
if (status == BluetoothGatt.GATT_SUCCESS){
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
}else{
Log.w("DSTTTTTTTTT", "onServicesDiscovered received: " + status);
}
}
//读到特征设备
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status){
if (status == BluetoothGatt.GATT_SUCCESS){
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic){
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
/**
* 通过广播发送数据
*/
private void broadcastUpdate(final String action){
final Intent intent = new Intent(action);
sendBroadcast(intent);
}
/**
* 通过广播发送数据
*/
private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic){
final Intent intent = new Intent(action);
// For all profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
Log.d(TAG, data.length + "");
if (data != null && data.length > 0){
final StringBuilder stringBuilder = new StringBuilder(data.length);
for (byte byteChar : data)
stringBuilder.append(String.format("%02X ", byteChar));
// new String(data) + "\n" +
intent.putExtra(EXTRA_DATA, stringBuilder.toString());
}
sendBroadcast(intent);
}
if (mBluetoothManager == null){
mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
if (mBluetoothManager == null){
Log.e(TAG, "Unable to initialize BluetoothManager.");
return false;
}
}
mBluetoothAdapter = mBluetoothManager.getAdapter();
if (mBluetoothAdapter == null){
Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
return false;
}
return true;
}
/**
* 连接
*/
public boolean connect(final String address){
if (mBluetoothAdapter == null || address == null){
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null){
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()){
mConnectionState = STATE_CONNECTING;
return true;
}else{
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null){
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
/**
* 可通知
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled){
if (mBluetoothAdapter == null || mBluetoothGatt == null){
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (UUID_FARSIGHT_SMART_WRIST.equals(characteristic.getUuid())){
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
/**
* 所有服务列表
*/
public List getSupportedGattServices(){
if (mBluetoothGatt == null)
return null;
return mBluetoothGatt.getServices();
}
1.2.3 信号处理
从蓝牙设备接收数据
这里我们使用设备接收来自蓝牙的通知即Notification信号,所以我们需要让我们的设备读取相应特征值的可通知信号。
在BLEService中:
Java Code
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled)
{
if (mBluetoothAdapter == null || mBluetoothGatt == null)
{
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
if (UUID_FARSIGHT_SMART_WRIST.equals(characteristic.getUuid()))
{
BluetoothGattDescriptor descriptor = characteristic
.getDescriptor(UUID.fromString(GattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
}
在DeviceControlActivity中,通过广播接收器接收来自BLEService中的广播发出的信号:
Java Code
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent)
{
final String action = intent.getAction();
Log.d(TAG, action);
if (BLEService.ACTION_GATT_CONNECTED.equals(action))
{
connected = true;
invalidateOptionsMenu();
}
else if (BLEService.ACTION_GATT_DISCONNECTED.equals(action))
{
connected = false;
invalidateOptionsMenu();
}
else if (BLEService.ACTION_GATT_SERVICES_DISCOVERED.equals(action))
{
Log.d(TAG, "received Discoveryed");
if (first)
{
first = false;
}
getcharacteristic(mBleService.getSupportedGattServices());
}
else if (BLEService.ACTION_DATA_AVAILABLE.equals(action))
{
String data = intent.getStringExtra(BLEService.EXTRA_DATA);
setTribleAndPower(data);
getcharacteristic(mBleService.getSupportedGattServices());
Log.d("DATAIS", data);
}
}
};
当发现服务的时候,调用getcharacteristic(mBleService.getSupportedGattServices())以判断特征值是否是我们需要的。
Java Code
private void getcharacteristic(List gattServices){
String uuid = null;
Log.d(TAG, "++++++++++++++++++++++++++++++++++++++++++++");
for (BluetoothGattService gattService : gattServices) {
uuid = gattService.getUuid().toString();
Log.d(TAG, uuid);
if (uuid.equalsIgnoreCase(UUID_date)) {
List gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics)
uuid = gattCharacteristic.getUuid().toString();
Log.d(TAG, uuid + "characteristic");
if (uuid.equalsIgnoreCase(UUID_D)) {
final int charaProp = gattCharacteristic.getProperties();
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a
// characteristic, clear
if (mNotifyCharacteristic != null) {
mBleService.setCharacteristicNotification(mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBleService.readCharacteristic(gattCharacteristic);
}
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
mNotifyCharacteristic = gattCharacteristic;
mBleService.setCharacteristicNotification(gattCharacteristic, true); }
}else{
continue;
}
}
}
}
当接收到ACTION_DATA_AVAILABLE广播的时候,读出广播中的数据,并通过数据对界面进行操作。
向蓝牙设备发送数据
电话状态监听类代码:
Java Code
package com.farsight.lastsmartwrist.tools;
import android.annotation.SuppressLint;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class Phone
{
private boolean first = true;
public byte msgCount = 0;
public byte phoneCount = 0;
private Context context = null;
public BufferTool cmdBuf = null;
public Phone(Context con)
{
context = con;
cmdBuf = new BufferTool(1024);
TelephonyManager teleMgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
teleMgr.listen(new MyPhoneStateListener(),
PhoneStateListener.LISTEN_CALL_STATE);
registerObserver();
init();
}
// 刚开始就发送现有的数据
void init()
{
phoneCount = (byte) readMissCall();
cmdBuf.addBuffer((byte) 'a', 1, phoneCount);
msgCount = (byte) getNewSmsCount();
cmdBuf.addBuffer((byte) 'c', 1, msgCount);
}
public void Quit()
{
unregisterObserver();
}
// 监听来电
class MyPhoneStateListener extends PhoneStateListener
{
@Override
public void onCallStateChanged(int state, String incomingNumber)
{
if (state == TelephonyManager.CALL_STATE_RINGING)
{
cmdBuf.addBuffer((byte) 'b', incomingNumber.getBytes().length,
incomingNumber.getBytes());
}
else if (state == TelephonyManager.CALL_STATE_IDLE)
{
int tmp = readMissCall();
if (first == true)
{
phoneCount = (byte) (tmp);
first = false;
}
else
{
phoneCount = (byte) (tmp + 1);
}
cmdBuf.addBuffer((byte) 'a', 1, phoneCount);
}
}
}
// 监听短信
public ContentObserver newMmsContentObserver = new ContentObserver(
new Handler())
{
public void onChange(boolean selfChange)
{
if (cmdBuf.getVolume() == 0)
{
cmdBuf.addBuffer((byte) 'd', 1, (byte) (getNewSmsCount() + 1));// 发送短信通知
}
}
};
// 注册监听者
@SuppressLint("NewApi")
public void registerObserver()
{
unregisterObserver();
context.getContentResolver().registerContentObserver(
Uri.parse("content://sms"), true, newMmsContentObserver);
}
// 取消注册
public void unregisterObserver()
{
try
{
if (newMmsContentObserver != null)
{
context.getContentResolver().unregisterContentObserver(
newMmsContentObserver);
}
}
catch (Exception e)
{
}
}
// 获得短信条数
public int getNewSmsCount()
{
int result = 0;
Cursor csr = context.getContentResolver().query(
Uri.parse("content://sms"), null, "type = 1 and read = 0",
null, null);
if (csr != null)
{
result = csr.getCount();
csr.close();
return result;
}
else
{
return 0;
}
}
// 获得电话个数
public int readMissCall()
{
int result = 0;
Cursor cursor = context.getContentResolver().query(
CallLog.Calls.CONTENT_URI, new String[] { Calls.TYPE },
" type=? and new=?",
new String[] { Calls.MISSED_TYPE + "", "1" }, "date desc");
if (cursor != null)
{
result = cursor.getCount();
cursor.close();
return result;
}
else
{
return 0;
}
}
}
要发送的数据通过BuffTools来设置:
Java Code
package com.farsight.lastsmartwrist.tools;
mport java.util.Collection;
import java.util.HashMap;
import android.annotation.SuppressLint;
public class BufferTool
{
private int volume = 0;
private HashMap buffer = null;
@SuppressLint("UseSparseArrays")
public BufferTool(int dataVolume)
{
volume = dataVolume;
buffer = new HashMap(volume);
}
public synchronized Boolean addBuffer(byte[] data)
{
if (data != null)
{
if (buffer.size() < volume)
{
buffer.put(buffer.size(), data);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public synchronized Boolean addBuffer(int kind, int num, int msg)
{
byte[] cmdd = { (byte) kind, (byte) num, (byte) msg };
if (buffer.size() < volume)
}
else
{
return false;
}
}
public synchronized Boolean addBuffer(int kind, int num, byte[] msg)
{
byte[] cmdd = new byte[msg.length + 2];
cmdd[0] = (byte) kind;
cmdd[1] = (byte) num;
System.arraycopy(msg, 0, cmdd, 2, msg.length);
if (buffer.size() < volume)
{
buffer.put(buffer.size(), cmdd);
return true;
}
else
{
return false;
}
}
public synchronized Boolean addBuffer(int cmd)
{
byte[] cmdd = { (byte) cmd };
if (buffer.size() < volume)
{
buffer.put(buffer.size(), cmdd);
return true;
}
else
{
return false;
}
}
public synchronized byte[] getBuffer()
{
byte[] data = null;
if (buffer.size() > 0)
{
data = buffer.get(buffer.size() - 1);
buffer.remove(buffer.size() - 1);
}
else
{
}
return data;
}
public synchronized byte[][] getBuffer(int num)
{
byte[][] data = new byte[num][];
for (int i = 0; i < num; i++)
{
if (buffer.size() > 0)
{
data[i] = buffer.get(0);
buffer.remove(0);
}
else
{
data[i] = null;
break;
}
}
return data;
}
public synchronized byte[][] getAllBuffer()
{
if (buffer.isEmpty() == false)
{
int num = 0;
Collection Col = buffer.values();
int vol = Col.size();
byte[][] data = new byte[vol + 1][];
for (byte[] i : Col)
{
data[num] = i;
num++;
}
data[num] = null;
buffer.clear();
return data;
}
else
{
return null;
}
}
public synchronized int getVolume()
{
return buffer.size();
}
}
和接收数据时不一样的是,我们在发现服务和特征值之后,就应该去查看Phone实例中是否有未传输出去的数据,如果有,而且服务和特征值是我们要发送的设备的话,就要进行数据传送。
Java Code
private void getcharacteristic(List gattServices)
{
String uuid = null;
Log.d(TAG, "++++++++++++++++++++++++++++++++++++++++++++");
for (BluetoothGattService gattService : gattServices)
{
uuid = gattService.getUuid().toString();
Log.d(TAG, uuid);
if (uuid.equalsIgnoreCase(UUID_date))
{
。。。。
}
else if (uuid.equals(UUID_write))
{
List gattCharacteristics = gattService.getCharacteristics();
for (BluetoothGattCharacteristic bluetoothGattCharacteristic : gattCharacteristics)
{
uuid = bluetoothGattCharacteristic.getUuid().toString();
final BluetoothGattCharacteristic inBluetoothGattCharacteristic = bluetoothGattCharacteristic;
if (uuid.equals(UUID_W))
{
byte[] datas = null;
if (0 != mPhone.cmdBuf.getVolume())
{
}
while (null != (datas = mPhone.cmdBuf.getBuffer()))
{
inBluetoothGattCharacteristic.setValue(datas);
mBleService.mBluetoothGatt.writeCharacteristic(inBluetoothGattCharacteristic);
}
}
else
{
continue;
}
}
}
else
{
continue;
}
}
}