首先说蓝牙分类:蓝牙貌似分为4.0,和2.0版本,4.0版本更省电(BLE)
判断方式如下: 是否支持蓝牙: getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
是否支持BLE蓝牙 : getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
//判断远端蓝牙类型:
BluetoothDevice类中有个方法getType();如果返回的是 BluetoothDevice.DEVICE_TYPE_CLASSIC;经典蓝牙,也就是2.0,若是则是 BluetoothDevice.DEVICE_TYPE_LE) {//低功耗蓝牙设备
注册蓝牙需要的广播:
IntentFilter action_found = new IntentFilter(BluetoothDevice.ACTION_FOUND);
getActivity().registerReceiver(mReceiver, action_found);
IntentFilter action_bond = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
getActivity().registerReceiver(mReceiver, action_bond);
IntentFilter action_disconnected = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
getActivity().registerReceiver(mReceiver, action_disconnected);
IntentFilter action_discover_end = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
getActivity().registerReceiver(mReceiver, action_discover_end);
IntentFilter action_pairing_request = new IntentFilter(ACTION_PAIRING_REQUEST);
getActivity().registerReceiver(mReceiver, action_pairing_request);
//蓝牙广播
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {//发现一台蓝牙设备
addDevice(device);
} else if (ACTION_PAIRING_REQUEST.equals(action)) {//新设备直接连接,不用用户输入pin码可以这么做;
setBluetoothPairingPin(device);
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {//扫描附近设备完成)
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {//蓝牙连接状态改变
int prevBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
if (bondState == BluetoothDevice.BOND_BONDING) {
Log.i(TAG, "蓝牙连接中:" + device.getName());
} else if (bondState == BluetoothDevice.BOND_BONDED) {//已连接
((MainActivity) getActivity()).goTagFragment();
} else if (bondState == BluetoothDevice.BOND_NONE) {
Log.i(TAG, "蓝牙没有连接" + device.getName());
} else if (bondState == BluetoothDevice.ERROR) {
Log.i(TAG, "蓝牙连接错误" + device.getName());
ToastUtils.show(R.string.error_bluetooth_connect);
((MainActivity) getActivity()).goConnectBluetoothFragment();
}
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {//断开连接
Log.i(TAG, "蓝牙断开连接" + device.getName());
ToastUtils.show(getString(R.string.bluetooth_disconnected));
((MainActivity) getActivity()).goConnectBluetoothFragment();
}
}
};
//准备配对去人配对码pin
public void setBluetoothPairingPin(BluetoothDevice device) {
String string = "1234";
byte[] pinBytes = string.getBytes();
try {
//Log.d(TAG, "Try to set the PIN");
Method m = device.getClass().getMethod("setPin", byte[].class);
m.invoke(device, pinBytes);
Log.d(TAG, "Success to add the PIN.");
try {
device.getClass().getMethod("setPairingConfirmation", boolean.class).invoke(device, true);
Log.d(TAG, "Success to setPairingConfirmation.");
} catch (Exception e) {
// TODO Auto-generated catch block
// Log.e(TAG, e.getMessage());
e.printStackTrace();
}
} catch (Exception e) {
// Log.e(TAG, e.getMessage());
e.printStackTrace();
}
}
//取消蓝牙配对
private void unpairDevice(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
if (device.getAddress().equals(mLast_addr)) {
sp.edit().putString(KEY_LAST_ADDR_STRING, "").commit();
mLast_addr = "";
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
BluetoothAdapter是本地自己的蓝牙类,获取蓝牙方法:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.isEnabled();是判断蓝牙是否打开;
打开蓝牙方式:
bluetoothAdapter.enable();打开蓝牙(不做提示,强行打开)
//弹出对话框提示用户是后打开
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE_BT);
bluetoothAdapter.disable() ;关闭蓝牙
bluetoothAdapter.cancelDiscovery();取消扫描
bluetoothAdapter.startDiscovery();开始扫描附近蓝牙设备
Set<BluetoothDevice> mBTpaired = bluetoothAdapter.getBondedDevices();获取曾经连接过的设备
再连接前最好停止扫描调用
cancelDiscovery这样能够加速
低功耗BLE蓝牙,连接与传输都使用的是回调的方式
BluetoothDevice 中 .connectGatt(mContext, false, mGattCallback);方法连接,第一个是上下文,第二个是否自动连接,第三个是连接监听回调接接口,如下,创建,然后重写方法即可
/**
* 连接与远端蓝牙回调
*/
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback()
其中这个
onConnectionStateChange方法中有个newstate是当前蓝牙连接状态,如果和 BluetoothProfile.STATE_CONNECTED一致则是连接完成,同时需要开线程准备写入工作,
mBluetoothGatt.getDevice();然后获取当前连接的设备是这个
经典蓝牙需要创建一个线程,然后通过
BluetoothSocket mmSocket = BluetoothDevice.createRfcommSocketToServiceRecord(SPP_UUID);的方法获取套接字一般UUID使用:
// Unique UUID for this application这个应用程序的唯一UUID
// 此处,必须使用Android的SSP(协议栈默认)的UUID:SPP UUID: 00001101-0000-1000-8000-00805F9B34FB
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
然后通过获取的套接字连接,为什么开线程就是因为这里会堵塞:
// Connect the device through the socket. This will block until it succeeds or throws an exception
// 通过插座连接设备。它会阻塞,直到它成功或抛出异常
mmSocket.connect();
然后需要在通过获取到的套接字socket进行获取输入输出流
然后死循环一直进行
BluetoothSocket socket中的socket.getInputStream();获取输入流
socket.getOutputStream();获取输出流
在连接前同时我们需要也开死循环判断服务端是否连接状态,实现多途径连接状态
通过BluetoothServerSocket =bluetoothAdapter的listenUsingRfcommWithServiceRecord获取一个服务端的socket需要传入一个name和uuid, name用当前类名就行,uuid还用刚才的
然后死循环判断状态BluetoothServerSocket .accept();可以获取一个BluetoothSocket