最近做了一个小项目,关于蓝牙的一个智能硬件。其中涉及到了蓝牙模块的操作。特记下蓝牙模块的操作过程。只记录下关于蓝牙部分的操作,具体业务逻辑不涉及其中。重点是记录下蓝牙的扫描、链接、通讯。

在使用蓝牙模块之前要判断设备是否支持蓝牙模块:

 if (!getPackageManager().hasSystemFeature(
PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT)
.show();
}

定义Service,与蓝牙模块进行通讯,在后台运行:

/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package com.njzoff.cushion.broadcast; import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; import java.util.List;
import java.util.UUID; /**
* Service for managing connection and data communication with a GATT server hosted on a
* given Bluetooth LE device.
*/
public class BluetoothLeService extends Service {
private final static String TAG = BluetoothLeService.class.getSimpleName(); private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothGatt mBluetoothGatt; public final static String ACTION_GATT_CONNECTED =
"com.example.bluetooth.le.ACTION_GATT_CONNECTED";
public final static String ACTION_GATT_DISCONNECTED =
"com.example.bluetooth.le.ACTION_GATT_DISCONNECTED";
public final static String ACTION_GATT_SERVICES_DISCOVERED =
"com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED";
public final static String ACTION_DATA_AVAILABLE =
"com.example.bluetooth.le.ACTION_DATA_AVAILABLE";
public final static String EXTRA_DATA =
"com.example.bluetooth.le.EXTRA_DATA"; public final static UUID UUID_NOTIFY =
UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb");
public final static UUID UUID_SERVICE =
UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"); public BluetoothGattCharacteristic mNotifyCharacteristic; public void WriteValue(String strValue)
{
mNotifyCharacteristic.setValue(strValue.getBytes());
mBluetoothGatt.writeCharacteristic(mNotifyCharacteristic);
} public void findService(List<BluetoothGattService> gattServices)
{
Log.i(TAG, "Count is:" + gattServices.size());
for (BluetoothGattService gattService : gattServices)
{
Log.i(TAG, gattService.getUuid().toString());
Log.i(TAG, UUID_SERVICE.toString());
if(gattService.getUuid().toString().equalsIgnoreCase(UUID_SERVICE.toString()))
{
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
Log.i(TAG, "Count is:" + gattCharacteristics.size());
for (BluetoothGattCharacteristic gattCharacteristic :
gattCharacteristics)
{
if(gattCharacteristic.getUuid().toString().equalsIgnoreCase(UUID_NOTIFY.toString()))
{
Log.i(TAG, gattCharacteristic.getUuid().toString());
Log.i(TAG, UUID_NOTIFY.toString());
mNotifyCharacteristic = gattCharacteristic;
setCharacteristicNotification(gattCharacteristic, true);
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
return;
}
}
}
}
} // Implements callback methods for GATT events that the app cares about. For example,
// connection change and services discovered.
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
Log.i(TAG, "oldStatus=" + status + " NewStates=" + newState);
if(status == BluetoothGatt.GATT_SUCCESS)
{ if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_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;
mBluetoothGatt.close();
mBluetoothGatt = null;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}
} @Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.w(TAG, "onServicesDiscovered received: " + status);
findService(gatt.getServices());
} else {
if(mBluetoothGatt.getDevice().getUuids() == null)
Log.w(TAG, "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);
Log.e(TAG, "OnCharacteristicWrite");
} @Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
int status)
{
Log.e(TAG, "OnCharacteristicWrite");
} @Override
public void onDescriptorRead(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorRead");
} @Override
public void onDescriptorWrite(BluetoothGatt gatt,
BluetoothGattDescriptor bd,
int status) {
Log.e(TAG, "onDescriptorWrite");
} @Override
public void onReadRemoteRssi(BluetoothGatt gatt, int a, int b)
{
Log.e(TAG, "onReadRemoteRssi");
} @Override
public void onReliableWriteCompleted(BluetoothGatt gatt, int a)
{
Log.e(TAG, "onReliableWriteCompleted");
} }; 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); // This is special handling for the Heart Rate Measurement profile. Data parsing is
// carried out as per profile specifications:
// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml
// For all other profiles, writes the data formatted in HEX.
final byte[] data = characteristic.getValue();
if (data != null && data.length > 0) {
//final StringBuilder stringBuilder = new StringBuilder(data.length);
//for(byte byteChar : data)
// stringBuilder.append(String.format("%02X ", byteChar));
//intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString());
intent.putExtra(EXTRA_DATA, new String(data));
}
sendBroadcast(intent);
} public class LocalBinder extends Binder {
public BluetoothLeService getService() {
return BluetoothLeService.this;
}
} @Override
public IBinder onBind(Intent intent) {
return mBinder;
} @Override
public boolean onUnbind(Intent intent) {
// After using a given device, you should make sure that BluetoothGatt.close() is called
// such that resources are cleaned up properly. In this particular example, close() is
// invoked when the UI is disconnected from the Service.
close();
return super.onUnbind(intent);
} private final IBinder mBinder = new LocalBinder(); /**
* Initializes a reference to the local Bluetooth adapter.
*
* @return Return true if the initialization is successful.
*/
public boolean initialize() {
// For API level 18 and above, get a reference to BluetoothAdapter through
// BluetoothManager.
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;
} /**
* Connects to the GATT server hosted on the Bluetooth LE device.
*
* @param address The device address of the destination device.
*
* @return Return true if the connection is initiated successfully. The connection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
/*
// Previously connected device. Try to reconnect.
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;
}
}
*/
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
if(mBluetoothGatt != null)
{
mBluetoothGatt.close();
mBluetoothGatt = null;
}
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
//mBluetoothGatt.connect(); Log.d(TAG, "Trying to create a new connection.");
return true;
} /**
* Disconnects an existing connection or cancel a pending connection. The disconnection result
* is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
*/
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.disconnect();
} /**
* After using a given BLE device, the app must call this method to ensure resources are
* released properly.
*/
public void close() {
if (mBluetoothGatt == null) {
return;
}
mBluetoothGatt.close();
mBluetoothGatt = null;
} /**
* Request a read on a given {@code BluetoothGattCharacteristic}. The read result is reported
* asynchronously through the {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
* callback.
*
* @param characteristic The characteristic to read from.
*/
public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.readCharacteristic(characteristic);
} /**
* Enables or disables notification on a give characteristic.
*
* @param characteristic Characteristic to act on.
* @param enabled If true, enable notification. False otherwise.
*/
public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enabled) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
return;
}
mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
/*
// This is specific to Heart Rate Measurement.
if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
mBluetoothGatt.writeDescriptor(descriptor);
}
*/
} /**
* Retrieves a list of supported GATT services on the connected device. This should be
* invoked only after {@code BluetoothGatt#discoverServices()} completes successfully.
*
* @return A {@code List} of supported services.
*/
public List<BluetoothGattService> getSupportedGattServices() {
if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices();
}
}

定义BluetoothAdapter mBluetoothAdapter;

 BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
  mBluetoothAdapter =bluetoothManager .getAdapter(); //取得系统蓝牙模块适配器
// 扫描设备
private void scanLeDevice(final boolean enable) { if (enable) {
Log.d("SacanLeDevice", "1 step start ScanLedevice");
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (mScanning) {
mScanning = false;
mBluetoothAdapter.stopLeScan(
mLeScanCallback);//停止扫描
invalidateOptionsMenu();
}
}
}, SCAN_PERIOD); mScanning = true;
// F000E0FF-0451-4000-B000-000000000000
liDevices.clear();
mHandler.sendEmptyMessage(0);
mBluetoothAdapter.startLeScan(mLeScanCallback);//开始扫描设备
} else {
Log.d("SacanLeDevice", "4 step stop Sacan device");
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
} }
//蓝牙设备
private List<BluetoothDevice> liDevices = new ArrayList<BluetoothDevice>();

// 扫描蓝牙设备的回调
 private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {


@Override
  public void onLeScan(final BluetoothDevice device, final int rssi,
    final byte[] scanRecord) {
   runOnUiThread(new Runnable() {
    @Override
    public void run() {
     Log.d("SacanLeDevice", "2 step  add device");
     liDevices.add(device);
     // mLeDeviceListAdapter.addDevice(device);
     mHandler.sendEmptyMessage(1);
    }
   });
  }
 };

//通过handle取出扫描结果并进行其他操作,我这这里是判断扫描结果中是否有上次链接的缓存记录,如果有进行自动重连

// Hander
 public final Handler mHandler = new Handler() {
  @Override
  public void handleMessage(Message msg) {
   switch (msg.what) {
   case 1: // Notify change
    Log.d("SacanLeDevice", "3 step  cnnect device");
    if (!CoushionApplication.isconnect && liDevices.size() > 0) {// 如果没有连接,并且已经扫描到蓝牙设备
     SharedPreferences mySharedPreferences = getSharedPreferences(
       "device", Activity.MODE_PRIVATE);
     String address = mySharedPreferences.getString(
       "DeviceAddress", "");// 获取上次链接的设备地址
     if (!address.equals("")) {
      for (int i = 0; i < liDevices.size(); i++) {
       if (liDevices.get(i).getAddress().equals(address)) {

      BluetoothLeService.connect(address);//根据地址链接蓝牙设备

break;
       }
      }
     }
    }


break;
   }
  }
 };

定义一个广播接收器,接受设备连接蓝牙状态的一个广播:

mGattUpdateReceiver = new GattupdateReceiver();
mGattUpdateReceiver.setBluetoothConnetinteface(this);
registerReceiver(mGattUpdateReceiver,
makeGattUpdateIntentFilter()); public static IntentFilter makeGattUpdateIntentFilter() { // 注册接收的事件
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED);
intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED);
intentFilter
.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED);
intentFilter.addAction(BluetoothLeService.ACTION_DATA_AVAILABLE);
intentFilter.addAction(BluetoothDevice.ACTION_UUID);
return intentFilter;
}
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.util.Log; public class GattupdateReceiver extends BroadcastReceiver {
public static String TAG = "GattupdateReceiver";
String data ;
private BluetoothConnetListen mBluetoothConnetListen;//实现接口 private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0: // 连接成功
if (mBluetoothConnetListen != null) {
mBluetoothConnetListen.SuccessConnect();
}
break;
case 1: // 链接中断
if (mBluetoothConnetListen != null) {
mBluetoothConnetListen.CancelConnect();
}
break;
case 2: // 可以进行数据通信
CoushionApplication.isconnect = true;
if (mBluetoothConnetListen != null) {
mBluetoothConnetListen.onDoThing();
}
break;
case 3: // 接受到数据 if (mBluetoothConnetListen != null) {
mBluetoothConnetListen.ReceiveData(data);
} break;
}
}
}; public void setBluetoothConnetinteface(BluetoothConnetListen m) {
mBluetoothConnetListen = m;
} @Override
public void onReceive(Context arg0, Intent intent) {
// TODO Auto-generated method stub final String action = intent.getAction();
Log.d(TAG, "Action==" + action);
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { //连接成功
Log.e(TAG, "Only gatt, just wait"); mHandler.sendEmptyMessage(0); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { //连接失败
mHandler.sendEmptyMessage(1);
} else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVERED
.equals(action)) //可以通信
{
mHandler.sendEmptyMessage(2);

} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) { //接受到数据
Log.e(TAG, "RECV DATA"); data = intent.getStringExtra(BluetoothLeService.EXTRA_DATA);
mHandler.sendEmptyMessage(3);
}
} }

在activity中实现接口后 BluetoothConnetListen。即可多蓝牙模块进行操作了。

mBluetoothLeService.WriteValue(edtSend.getText().toString());//向蓝牙发送指令或者数据

android 蓝牙连接与通讯(Bluetooth)的更多相关文章

  1. Android蓝牙连接自动测试工具

    蓝牙连接自动测试工具 1.需求产生 开发不按着需求走都是耍流氓且浪费时间.此工具的需求产生是研发人员在开发产品时涉及到蓝牙驱动和安卓蓝牙两个东西.但是呢,蓝牙不太稳定,那么工作来了.就需要研发人员一边 ...

  2. Android蓝牙连接以及数据接收发送

    1.加入权限 <uses-feature android:name="android.hardware.bluetooth_le" android:required=&quo ...

  3. android 蓝牙连接端(客户端)封装

    0.权限  AndroidManifest.xml <uses-permission android:name="android.permission.BLUETOOTH"/ ...

  4. Android 蓝牙4.0的连接和通讯

    1.加入权限 <uses-sdk android:minSdkVersion=" android:targetSdkVersion="/> <uses-featu ...

  5. 深入了解Android蓝牙Bluetooth——《基础篇》

    什么是蓝牙?   也可以说是蓝牙技术.所谓蓝牙(Bluetooth)技术,实际上是一种短距离无线电技术,是由爱立信公司公司发明的.利用"蓝牙"技术,能够有效地简化掌上电脑.笔记本电 ...

  6. Android 蓝牙开发之搜索、配对、连接、通信大全

            蓝牙( Bluetooth®):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据 交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙设备最 ...

  7. 深入了解Android蓝牙Bluetooth ——《总结篇》

    在我的上两篇博文中解说了有关android蓝牙的认识以及API的相关的介绍,蓝牙BLE的搜索,连接以及读取. 没有了解的童鞋们请參考: 深入了解Android蓝牙Bluetooth--<基础篇& ...

  8. Android bluetooth介绍(两): android 蓝牙源架构和uart 至rfcomm过程

    关键词:蓝牙blueZ  UART  HCI_UART H4  HCI  L2CAP RFCOMM  版本号:基于android4.2先前版本 bluez内核:linux/linux3.08系统:an ...

  9. android 蓝牙串口通讯使用简介

    需要的权限 <uses-permission android:name="android.permission.BLUETOOTH" />  <uses-perm ...

随机推荐

  1. 泛型Hub

    SignalR循序渐进(二)泛型Hub 接上一篇,文章末尾抛出了2个问题: 能不能让客户端声明一个强类型的方法列表呢?这样首先不容易写错. 同样的,能不能让服务端声明一个强类型的方法列表给客户端调用呢 ...

  2. Node填坑教程——HelloWorld

    环境安装(极简): Node需要的环境可以说及其简单,也可以说及其复杂.为什么这么说呢? 如果里只需要运行环境那么到Node官网下载一个包就行了.里面自带npm管理工具,这是包管理工具,以后会频繁的使 ...

  3. Idea构建Maven项目教程

    Idea构建Maven项目,以及其中遇到的坑,及解决方案 步骤一:配置Idea的maven插件 步骤二:创建maven项目 file-->new-->project 下一步,设置group ...

  4. HttpClient的使用-爬虫学习(一)

    Apache真是伟大,为我们提供了HttpClient.jar,这个HttpClient是客户端的http通信实现库,这个类库的作用是接受和发送http报文,引进这个类库,我们对于http的操作会变得 ...

  5. C# 制作Windows服务安装包

    C# 制作Windows服务安装包   这两天公司要用C#写一个windows服务,做成安装安装包.制作的过程中遇到了一些问题,写完之后总结一下.如果以后在用到的话可以可以参考一下,而且由于原来没有做 ...

  6. IOS学习之路二十三(EGOImageLoading异步加载图片开源框架使用)

    EGOImageLoading 是一个用的比较多的异步加载图片的第三方类库,简化开发过程,我们直接传入图片的url,这个类库就会自动帮我们异步加载和缓存工作:当从网上获取图片时,如果网速慢图片短时间内 ...

  7. Oracle JDBC存入图片Blob

    创建测试表 create table test_img( id integer primary key, name ), image blob ); 存储图片 import java.io.FileI ...

  8. sed 入门

         sed 是 stream editor(流编辑器)的缩写.它能够完美配合正则表达式使用.sed命令众所周知的一个功能是文本的替换. 1. sed可以替换给定文本中的字符串.它可以配合正则表达 ...

  9. xhEditor实现插入代码功能

    如果大家经常使用CSDN或者其他技术博客,都会有插入程序代码或脚本功能 开源中国 CSDN 这里介绍xhEditor实现插入代码功能,对xhEditor进行插件扩展 一.首先定义插件样式 <st ...

  10. (转)JS中公共/私有变量和方法

    私有变量 在对象内部使用'var'关键字来声明,而且它只能被私有函数和特权方法访问. 私有函数 在对象的构造函数里声明(或者是通过var functionName=function(){...}来定义 ...