基于 Android蓝牙4.0开发详细讲解,与硬件通信 史上最牛逼,最详细

1.如果你准备搞蓝牙开发了,那么Android的基本常识你也应该很熟悉,比如说:Service 。你还需要一个支持蓝牙4.0的手机,不然神马都白瞎! 首先,几乎所有的蓝牙开发都是基于服务的,那么你需要建立一个蓝牙服务类。 像这样

public class BluetoothService extends Service {


	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
}

当然,服务需要在AndroidManifest中注册的,然后在恰当的时候(很显然,是在你恰当的时候)启动服务 

startService(new Intent(this,BluetoothService.class));

   


2.服务建立好之后,我们要初始化蓝牙(2B青年都知道初始化蓝牙的前提是你必须开启手机的蓝牙,申请蓝牙所需要的权限),我比较喜欢在onCreate方法中初始化,网上有很多很多的方法,我想说的是:能搞出来就行了,你就牛逼了

    
    
上面是申请权限,我就不解释了, 然后 初始化蓝牙,当然你也可以在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 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();
		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 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();
		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 list){
		if (list == null) return;
		 for (BluetoothGattService gattService : list) {
			 List gattCharacteristics =gattService.getCharacteristics();
			  for ( final BluetoothGattCharacteristic  gattCharacteristic: gattCharacteristics) {
				  if(gattCharacteristic.getUuid().toString().equalsIgnoreCase("0000fff1-0000-1000-8000-00805f9b34fb")){
//					  这是我的特征值
				  }
			}
			 
		 }
	}
}

注意我的最下面的一个方法,获取到这个特征值之后,便可以在里面写入数据了

6.写入数据,上代码中....看最后

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 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();
		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 list){
		if (list == null) return;
		 for (BluetoothGattService gattService : list) {
			 List 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值!元芳,你怎么看? 



 




 


你可能感兴趣的:(Android)