最近公司在做智能穿戴设备,用到了蓝牙4.0,当时就震惊了,完全没用过啊。智能硬着头皮自己上了,还好研究了几天之后终于明白了,下面把这几天的经验写一下。
在android里面,蓝牙4.0的编程和之前有很大不同,不在需要socket,serverSocket,也就是说没有了服务器/客户端的概念,而且手机和蓝牙设备也不再需要配对,可以直接连接。
蓝牙4.0的编程分为几个步骤:
- 获取蓝牙管理类对象;
- 获取蓝牙适配器对象;
- 搜索蓝牙设备;
- 连接蓝牙设备;
- 调用连接回调函数。
private BluetoothManager manager;
manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);</span>
二、获取蓝牙适配器对象
private BluetoothAdapter adapter;
adapter = manager.getAdapter();</span>
三、搜索蓝牙设备
bluetoothAdapter.startLeScan(callback);</span>
callback是搜索结果的回调对象,其实现如下:
private BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// TODO Auto-generated method stub
//如果搜索到了蓝牙设备,则在界面上添加蓝牙设备
if(dialog != null)
dialog.dismiss();
adapter.addDevice(device);
adapter.notifyDataSetChanged();
}
};
在这里我实现了一个adapter类,继承自BaseAdapter。adapter里面有一ArrayList对象,用来存储BluetoothDevice对象。
四、连接蓝牙设备
device.connectGatt(this, false, gattCallback);
五、调用连接回调函数
其实就是实现上面代码中的gattCallback对象,这里注意,gattCallback里面有9个方法,但是不需要每个都重写,自己需要哪个重写哪个,但是onConnectionStateChange方法一定要实现,因为蓝牙设备连接成功后,自动调用的方法就是这个。
private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
if(newState == BluetoothProfile.STATE_CONNECTED){
System.out.println("connected");
gatt.discoverServices();
}
}
}
因为我要实现向蓝牙设备写数据,要先发现蓝牙设备提供的服务,所以实现了gatt.discoverServices(),这个方法会回调gattCallback里面的onServicesDiscovered方法。
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
super.onServicesDiscovered(gatt, status);
System.out.println("discovered");
if(status == BluetoothGatt.GATT_SUCCESS){
BluetoothGattService service = gatt.getService(UUID.fromString(SERVER_UUID));
if(service != null){
characteristic = service.getCharacteristic(UUID.fromString(UUID_AVAILABLE));
gatt.setCharacteristicNotification(characteristic, true);
characteristic.setValue("gfrd");
gatt.writeCharacteristic(characteristic);
}
}
}
这里面获得服务的UUID和获得数据传输的UUID是不一样的,具体多少看蓝牙设备的设置,然后
gatt.writeCharacteristic(characteristic)方法会调用gattCallback里面的onCharacteristicWrite方法,这个方法我没有重写,因为暂时不需要。
android蓝牙4.0编程简单,主要是要搞清楚步骤,还有就是最后连接设备之后的调用关系,设备连接之后调用的方法一定是onConnectionStateChange方法,在这里面实现你需要的操作,然后结果在对应的回调函数里面获取即可。
下面贴完整代码: 首先是主activity类:
<pre name="code" class="java"> public static class BluetoothDeviceAvtivity extends ListActivity{
private LeDeviceListAdapter adapter;//自己实现的ListActivity的adapter;
private ProgressDialog dialog;
private ServiceConnection conn;
private BluetoothManager manager;
private BluetoothAdapter bluetoothAdapter;
//连接蓝牙设备返回的参数
private BluetoothAdapter.LeScanCallback callback = new BluetoothAdapter.LeScanCallback() {
@SuppressLint("NewApi") @Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
// TODO Auto-generated method stub
//如果搜索到了蓝牙设备,则在界面上添加蓝牙设备
if(dialog != null)
dialog.dismiss();
adapter.addDevice(device);
adapter.notifyDataSetChanged();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
adapter = new LeDeviceListAdapter();
manager = (BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
bluetoothAdapter = manager.getAdapter();
scanDevice();
setListAdapter(adapter);
}
/**
* 当用户点击了一个蓝牙设备时,连接蓝牙设备
* @param l
* @param v
* @param position
* @param id
*/
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
bluetoothAdapter.stopLeScan(callback);
BluetoothDevice device = adapter.getBluetoothDevice(position);
if(device != null){
bluetoothDevice = device;
connectDevice();
finish();
}
}
/**
* TODO扫描蓝牙设备,2秒后停止
* @throw
* @return void
*/
@SuppressLint("NewApi") public void scanDevice(){
showProgress();
bluetoothAdapter.startLeScan(callback);
}
public void showProgress(){
if(dialog == null){
dialog = new ProgressDialog(this);
}
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.setMessage("正在搜索蓝牙设备");
dialog.show();
}
/**
* TODO连接蓝牙设备,如果设备没有绑定,首先绑定
* @throw
* @return void
*/
@SuppressLint("NewApi") public void connectDevice(){
if(bluetoothDevice == null){
new AlertDialog.Builder(this).setTitle("提示").setMessage("无法连接到该设备").setPositiveButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
}
}).show();
}else{
String bluetoothName = bluetoothDevice.getName();
String bluetoothAddress = bluetoothDevice.getAddress();
Intent intent = new Intent(this, BluetoothServer.class);
intent.putExtra("name", bluetoothName);
intent.putExtra("address", bluetoothAddress);
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
new AlertDialog.Builder(BluetoothDeviceAvtivity.this).setTitle("提示").setMessage("蓝牙设备无法连接")
.setPositiveButton("重新扫描", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
scanDevice();
setListAdapter(adapter);
}
}).setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
dialog.dismiss();
finish();
}
}).show();
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
Toast.makeText(BluetoothDeviceAvtivity.this, "蓝牙设备已连接", Toast.LENGTH_SHORT).show();
}
};
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(conn != null)
unbindService(conn);
}
/**
* TODO自定义的ListView的适配器
* @author DingChang
* @data: 2015-6-8 上午10:58:47
* @version: V1.0
*/
public class LeDeviceListAdapter extends BaseAdapter{
private ArrayList<BluetoothDevice> arrayList;
private LayoutInflater mInflater;
public LeDeviceListAdapter(){
super();
arrayList = new ArrayList<BluetoothDevice>();
mInflater = BluetoothDeviceAvtivity.this.getLayoutInflater();
}
public void addDevice(BluetoothDevice device){
if(!arrayList.contains(device))
arrayList.add(device);
}
public BluetoothDevice getBluetoothDevice(int position) {
return arrayList.get(position);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return arrayList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return arrayList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@SuppressLint("InflateParams") @Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder viewHolder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.adapter_layout, null);
viewHolder = new ViewHolder();
viewHolder.addressTextView = (TextView) convertView.findViewById(R.id.blueDeviceAddress);
viewHolder.nameTextView = (TextView) convertView.findViewById(R.id.blueDeviceName);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
BluetoothDevice device = arrayList.get(position);
final String deviceName = device.getName();
if (deviceName != null && deviceName.length() > 0)
viewHolder.nameTextView.setText(deviceName);
else
viewHolder.nameTextView.setText("未知设备");
viewHolder.addressTextView.setText(device.getAddress());
return convertView;
}
}
}
public static class ViewHolder{
TextView nameTextView;
TextView addressTextView;
}
</pre><pre name="code" class="java"> 然后就是后台实现蓝牙连接,数据传输的Service类:
<pre name="code" class="java">public class BluetoothServer extends Service {
private BluetoothAdapter adapter;
private BluetoothManager manager;
private BluetoothDevice device;
private final static String UUID_AVAILABLE = "00001002-0000-1000-8000-00805f9b34fb";
private final static String SERVER_UUID = "00001000-0000-1000-8000-00805f9b34fb";
private BluetoothGattCharacteristic characteristic;
@SuppressLint("NewApi") private BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
if(status == BluetoothProfile.STATE_CONNECTED && newState == BluetoothProfile.STATE_DISCONNECTED){
stopSelf();
}
if(newState == BluetoothProfile.STATE_CONNECTED){
System.out.println("connected");
gatt.discoverServices();
}
}
@Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
// TODO Auto-generated method stub
super.onServicesDiscovered(gatt, status);
System.out.println("discovered");
if(status == BluetoothGatt.GATT_SUCCESS){
BluetoothGattService service = gatt.getService(UUID.fromString(SERVER_UUID));
if(service != null){
characteristic = service.getCharacteristic(UUID.fromString(UUID_AVAILABLE));
gatt.setCharacteristicNotification(characteristic, true);
characteristic.setValue("gfrd");
gatt.writeCharacteristic(characteristic);
}
}
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic, int status) {
// TODO Auto-generated method stub
super.onCharacteristicWrite(gatt, characteristic, status);
System.out.println("write");
}
};
@SuppressLint("NewApi") @Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
//String name = arg0.getStringExtra("name");
String addressString = arg0.getStringExtra("address");
device = adapter.getRemoteDevice(addressString);
device.connectGatt(this, false, gattCallback);
//boolean b = bluetoothGatt.discoverServices();
//System.out.println(b);
return null;
}
@SuppressLint("NewApi") @Override
public void onCreate() {
// TODO Auto-generated method stub
manager = (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
adapter = manager.getAdapter();
super.onCreate();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
// TODO Auto-generated method stub
return super.onUnbind(intent);
}
}
</pre><br /><br /><br /><pre>