</pre>1.如果你准备搞蓝牙开发了,那么Android的基本常识你也应该很熟悉,比如说:<span style="font-size:18px;"><span style="color:#ff0000;">Service 。你还需要一个支持蓝牙4.0的手机,不然神马都白瞎! </span>首先,几乎所有的蓝牙开发都是基于服务的,那么你需要建立一个蓝牙服务类。 像这样</span><p></p><p><span style="font-size:18px;">public class BluetoothService extends Service {</span></p><p></p><pre name="code" class="java"><span style="font-size:18px;">
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}</span>
当然,服务需要在AndroidManifest中注册的,然后在恰当的时候(很显然,是在你恰当的时候)启动服务
startService(new Intent(this,BluetoothService.class));
<service
android:name="com.hebiao.blutoothtest.BluetoothService"
android:enabled="true"
android:exported="false" />
2.服务建立好之后,我们要初始化蓝牙(2B青年都知道初始化蓝牙的前提是你必须开启手机的蓝牙,申请蓝牙所需要的权限),我比较喜欢在onCreate方法中初始化,网上有很多很多的方法,我想说的是:能搞出来就行了,你就牛逼了
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
上面是申请权限,我就不解释了, 然后
初始化蓝牙,当然你也可以在Activity中
判断蓝牙是否可用,或者是否启动
import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Intent;
import android.os.IBinder;
public class BluetoothService extends Service {
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
// TODO Auto-generated method stub
bluetoothManager=(BluetoothManager)getSystemService(Service.BLUETOOTH_SERVICE);
// 这个方法属于新API,我的eclipse中也报错,按eclipse提示修改
bluetoothAdapter=bluetoothManager.getAdapter();
// 若蓝牙为打开,就会提示用户启动蓝牙服务
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
return;
}
super.onCreate();
}
}
3.我们启动了蓝牙服务,光有蓝牙没有设备那是瞎掰,我们需要搜索周围的设备,一般是搜索一段时间之后自动停止搜索。如果你从我大天朝地大物博,物产丰富的角度考虑的话,你可以让你的手机一直搜索设备,毕竟我们天朝有的是能源。蓝牙适配器给我们提供了一个搜索方法:bluetoothAdapter.startLeScan(callback) 很显然callBack是个回调,是一个 BluetoothAdapter.LeScanCallback的回调 ,我是最受不了这种回调了,一大坨,看得蛋疼,这里不得不说objective-c了,objective-c最大的好处是你可以让所有的方法平行,那么很明显,我们需要调用startLeScan()必须实例化一个LeScanCallback的类且覆写回调函数。上代码
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothService extends Service {
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private Handler handler;
private boolean scanning;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
// TODO Auto-generated method stub
bluetoothManager=(BluetoothManager)getSystemService(Service.BLUETOOTH_SERVICE);
// 这个方法属于新API,我的eclipse中也报错,按eclipse提示修改
bluetoothAdapter=bluetoothManager.getAdapter();
// 若蓝牙为打开,就会提示用户启动蓝牙服务
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
return;
}
handler=new Handler();
super.onCreate();
}
private void startFindDevice() {
if (!bluetoothAdapter.isDiscovering()) {
scanLeDevice(true);
}
}
public void stopFindDevice() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}, 10000);
scanning = true;
bluetoothAdapter.startLeScan(leScanCallback);
} else {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}
BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback(){
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] arg2) {
// TODO Auto-generated method stub
// device 搜索到的设备
// rssi 设备的rssi 也就是当前的设备信号的强弱
}
};
}
我们现在
可以找到附近的蓝牙设备,且能够获取到搜索的时候的瞬间的设备信号大小,但是问题来了?这些所有的操作都是在服务里面,如何与
你所在的Activity通信了,添加广播和广播接受者,不用我想起说了,想知道私信。
4.找到设备之后,我们需要连接设备,并且将已经连接上的设备保存起来,通常硬件设备都有一个唯一的MAC地址,连接硬件的方法是bluetoothDevice.connectGatt(context, autoConnect, callback), 第二个参数重点说下,一般是false,如果是写true设备会自动重新连接的,第三个参数又是个蛋疼的回调BluetoothGattCallback(这里面有很多牛逼的方法,这是蓝牙通信的核心),一般要动态的读取rssi的值很明显你要马不停蹄的读取,从成功连接到设备开始,我们开始搞起, gatt.readRemoteRssi() 这是读取远程蓝牙设备的rssi值,是一个循环读取的过程
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothService extends Service {
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private Handler handler;
private boolean scanning;
private Map<String, BluetoothGatt> bluetoothGattMap;
private Timer mRssiTimer;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
// TODO Auto-generated method stub
bluetoothManager=(BluetoothManager)getSystemService(Service.BLUETOOTH_SERVICE);
// 这个方法属于新API,我的eclipse中也报错,按eclipse提示修改
bluetoothAdapter=bluetoothManager.getAdapter();
// 若蓝牙为打开,就会提示用户启动蓝牙服务
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
return;
}
bluetoothGattMap=new HashMap<String, BluetoothGatt>();
handler=new Handler();
super.onCreate();
}
private void startFindDevice() {
if (!bluetoothAdapter.isDiscovering()) {
scanLeDevice(true);
}
}
public void stopFindDevice() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}, 10000);
scanning = true;
bluetoothAdapter.startLeScan(leScanCallback);
} else {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}
BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback(){
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] arg2) {
// TODO Auto-generated method stub
// device 搜索到的设备
// rssi 设备的rssi 也就是当前的设备信号的强弱
}
};
private boolean connect(String address) {
stopFindDevice();
if ((bluetoothAdapter == null) || (address == null)) {
return false;
}
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (device == null) {
return false;
}
gatt = device.connectGatt(this, false, bluetoothGattCallback);
bluetoothGattMap.put(address, gatt);
return true;
}
public boolean disconnect(String address) {
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
bluetoothGattMap.remove(address);
return true;
}
BluetoothGattCallback bluetoothGattCallback=new BluetoothGattCallback(){
@Override
public void onConnectionStateChange(final BluetoothGatt gatt,
int status, int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
TimerTask task = new TimerTask() {
@Override
public void run() {
// 我不停的读取,不停的读取,时间频率自己控制就行
gatt.readRemoteRssi();
}
};
mRssiTimer = new Timer();
mRssiTimer.schedule(task, 1000, 1000);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mRssiTimer != null) {
mRssiTimer.cancel();
}
}
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// 动态获取 rssi 值
}
};
}
注意:
是rssi的值需要不停的循环读取的,这是一个长连接
5.获取蓝牙的特征值,也就是蓝牙那个模块可写可读,我一般是蓝牙连接成功之后调用发现服务方法gatt.discoverServices();
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
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.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothService extends Service {
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private Handler handler;
private boolean scanning;
private Map<String, BluetoothGatt> bluetoothGattMap;
private Timer mRssiTimer;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
// TODO Auto-generated method stub
bluetoothManager=(BluetoothManager)getSystemService(Service.BLUETOOTH_SERVICE);
// 这个方法属于新API,我的eclipse中也报错,按eclipse提示修改
bluetoothAdapter=bluetoothManager.getAdapter();
// 若蓝牙为打开,就会提示用户启动蓝牙服务
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
return;
}
bluetoothGattMap=new HashMap<String, BluetoothGatt>();
handler=new Handler();
super.onCreate();
}
private void startFindDevice() {
if (!bluetoothAdapter.isDiscovering()) {
scanLeDevice(true);
}
}
public void stopFindDevice() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}, 10000);
scanning = true;
bluetoothAdapter.startLeScan(leScanCallback);
} else {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}
BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback(){
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] arg2) {
// TODO Auto-generated method stub
// device 搜索到的设备
// rssi 设备的rssi 也就是当前的设备信号的强弱
}
};
private boolean connect(String address) {
stopFindDevice();
if ((bluetoothAdapter == null) || (address == null)) {
return false;
}
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (device == null) {
return false;
}
gatt = device.connectGatt(this, false, bluetoothGattCallback);
bluetoothGattMap.put(address, gatt);
return true;
}
public boolean disconnect(String address) {
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
bluetoothGattMap.remove(address);
return true;
}
BluetoothGattCallback bluetoothGattCallback=new BluetoothGattCallback(){
@Override
public void onConnectionStateChange(final BluetoothGatt gatt,
int status, int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
// 连接成功时获取特征值
gatt.discoverServices();
TimerTask task = new TimerTask() {
@Override
public void run() {
// 我不停的读取,不停的读取,时间频率自己控制就行
gatt.readRemoteRssi();
}
};
mRssiTimer = new Timer();
mRssiTimer.schedule(task, 1000, 1000);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mRssiTimer != null) {
mRssiTimer.cancel();
}
}
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// 动态获取 rssi 值
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
showService(gatt.getServices());
} else {
}
}
};
private void showService(List<BluetoothGattService> list){
if (list == null) return;
for (BluetoothGattService gattService : list) {
List<BluetoothGattCharacteristic> gattCharacteristics =gattService.getCharacteristics();
for ( final BluetoothGattCharacteristic gattCharacteristic: gattCharacteristics) {
if(gattCharacteristic.getUuid().toString().equalsIgnoreCase("0000fff1-0000-1000-8000-00805f9b34fb")){
// 这是我的特征值
}
}
}
}
}
</pre><span style="color:#cc0000;">注意我的最下面的一个方法,获取到这个特征值之后,便可以在里面写入数据了</span><p></p><p><span style="font-size:18px;"><span style="color:#cc0000;"></span></span></p><p><span style="font-size:18px;">6.写入数据,上代码中....看最后</span></p><p><pre name="code" class="java" style="font-size: 18px;">import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
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.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public class BluetoothService extends Service {
private BluetoothManager bluetoothManager;
private BluetoothAdapter bluetoothAdapter;
private Handler handler;
private boolean scanning;
private Map<String, BluetoothGatt> bluetoothGattMap;
private Timer mRssiTimer;
private ExecutorService readWriteWorker = Executors.newSingleThreadExecutor();
private volatile BluetoothGattCharacteristic bluetoothGattCharacteristic;
private volatile BluetoothGatt bluetoothGatt;
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@SuppressLint("NewApi")
@Override
public void onCreate() {
// TODO Auto-generated method stub
bluetoothManager=(BluetoothManager)getSystemService(Service.BLUETOOTH_SERVICE);
// 这个方法属于新API,我的eclipse中也报错,按eclipse提示修改
bluetoothAdapter=bluetoothManager.getAdapter();
// 若蓝牙为打开,就会提示用户启动蓝牙服务
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(enableBtIntent);
return;
}
bluetoothGattMap=new HashMap<String, BluetoothGatt>();
handler=new Handler();
super.onCreate();
}
private void startFindDevice() {
if (!bluetoothAdapter.isDiscovering()) {
scanLeDevice(true);
}
}
public void stopFindDevice() {
scanLeDevice(false);
}
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
handler.postDelayed(new Runnable() {
@Override
public void run() {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}, 10000);
scanning = true;
bluetoothAdapter.startLeScan(leScanCallback);
} else {
scanning = false;
bluetoothAdapter.stopLeScan(leScanCallback);
}
}
BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback(){
@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] arg2) {
// TODO Auto-generated method stub
// device 搜索到的设备
// rssi 设备的rssi 也就是当前的设备信号的强弱
}
};
private boolean connect(String address) {
stopFindDevice();
if ((bluetoothAdapter == null) || (address == null)) {
return false;
}
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
if (device == null) {
return false;
}
gatt = device.connectGatt(this, false, bluetoothGattCallback);
bluetoothGattMap.put(address, gatt);
return true;
}
public boolean disconnect(String address) {
BluetoothGatt gatt = (BluetoothGatt) bluetoothGattMap.get(address);
if (gatt != null) {
gatt.close();
}
bluetoothGattMap.remove(address);
return true;
}
BluetoothGattCallback bluetoothGattCallback=new BluetoothGattCallback(){
@Override
public void onConnectionStateChange(final BluetoothGatt gatt,
int status, int newState) {
// TODO Auto-generated method stub
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
// 连接成功时获取特征值
gatt.discoverServices();
TimerTask task = new TimerTask() {
@Override
public void run() {
// 我不停的读取,不停的读取,时间频率自己控制就行
gatt.readRemoteRssi();
}
};
mRssiTimer = new Timer();
mRssiTimer.schedule(task, 1000, 1000);
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
if (mRssiTimer != null) {
mRssiTimer.cancel();
}
}
}
@Override
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
// 动态获取 rssi 值
}
@Override
// New services discovered
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
bluetoothGatt=gatt;
showService(gatt.getServices());
} else {
}
}
};
private void showService(List<BluetoothGattService> list){
if (list == null) return;
for (BluetoothGattService gattService : list) {
List<BluetoothGattCharacteristic> gattCharacteristics =gattService.getCharacteristics();
for ( final BluetoothGattCharacteristic gattCharacteristic: gattCharacteristics) {
if(gattCharacteristic.getUuid().toString().equalsIgnoreCase("0000fff1-0000-1000-8000-00805f9b34fb")){
// 这是我的特征值
}
}
}
}
private void writeData(){
byte[] value = new byte[]{(byte) 0x01,(byte) 0x01,(byte) 0x01,(byte) 0x01};
bluetoothGattCharacteristic.setValue(value);
bluetoothGatt.writeCharacteristic(bluetoothGattCharacteristic);
}
}
实际开发中还会遇到一个问题,就是读取多个设备的rssi值!元芳,你怎么看?