上周某杰同学遇到了蓝牙连接打印机的问题,来请教笔者,于是乎便各种百度终于解决了问题。本文对于这个问题做详细说明与记录来帮助各位看官解决类似问题,也方便以后用到的时候查询。
如标题描述,分为以下两个问题:
1. 蓝牙连接打印机(本文)
2. 实现格式化打印(下一篇文章介绍)
对于蓝牙想来大家应该都比较熟悉,基础知识便不再赘述,如有不懂的可以留言或者自行百度,本文重点介绍android实现蓝牙连接的流程和相关代码。
1.判断设备是否支持并打开蓝牙
<span style="font-size:18px;"> //判断设备是否支持蓝牙
BlueToothAdapter adapter=BlueToothAdapter.getDefaultAdapter();
if(adapter==null){
//设备不支持蓝牙
Toast.makeText(this, "本机没有找到蓝牙硬件或驱动!", Toast.LENGTH_SHORT).show();
return;
}
//比较暴力的方式(静默打开蓝牙),需要BlueTooth_Admin权限
if(!adapter.isEnabled){//蓝牙没有开启
adapter.enable();
}
//关闭蓝牙
adapter.disable();
//弹出对话框提示后开启蓝牙,用户点击了允许会收到RESULT_OK 否则RESULT_CANCELED
Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(mIntent, 1);
//在onActivityResult中做相关处理
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "蓝牙已经开启", Toast.LENGTH_SHORT).show();
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "不允许蓝牙开启", Toast.LENGTH_SHORT).show();
finish();
}
}
} </span>
2.获取已配对过的设备,返回结果是Set<BluetoothDevice>
<span style="font-size:18px;">Set<BluetoothDevice> devices = adapter.getBondedDevices();
if(devices.size()>0) {
for(BluetoothDevice bluetoothDevice:devices) {
bondDevices.add(bluetoothDevice);
}
}</span>
3.检索周围的设备
<span style="font-size:18px;">//开启检索:
adapter.startDiscovery();</span>
设备检索是通过广播的方式接收的,分为注册intentFilter和处理广播两部分
//注册intentFilter
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver,intentFilter);
这里的action选项看源码(限于篇幅,列出部分):
<span style="font-size:18px;">@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";//发现新设备
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DISAPPEARED = "android.bluetooth.device.action.DISAPPEARED";//设备变为不可见
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";//连接完成
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";//断开连接请求
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_DISCONNECTED ="android.bluetooth.device.action.ACL_DISCONNECTED";//断开连接
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";//蓝牙设备名称变化
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";//绑定状态发生变化的广播
public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";//接收到发现新设备的广播的时候从intent中获取数据的key
public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";//获取设备名字的key
public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";//获取配对状态的key</span>
</pre><pre name="code" class="java"><span style="font-size:18px;"> //在receiver中的处理,本文只列出了发现新设备的广播的接收处理
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context,Intent intent){
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(device.getBondState()==BluetoothDevice.BOND_BONDED) {
//已配对设备
addBondDevicesToListView(device);
} else {
//未配对设备
addUnbondDevicesToListView(device);
}
}
};</span>
4.设备配对
<span style="font-size:18px;"> //设备的配对是通过反射实现的,调用的是createBond方法,返回值可以判断是否配对成功
try {
Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
boolean result = createBondMethod.invoke(unbondDevices.get(arg2));
} catch (Exception e) {
Toast.makeText(BluetoothActivity.this,e.getMessage(),Toast.LENGTH_SHORT).show();
}</span>
5.配对完成后开始正常通信
蓝牙通信的本质是蓝牙套接字,即BluetoothSocket,除了以下代码就是一些关于流的操作。
<span style="font-size:18px;">public void connect(){
if(!isConnection) {
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
bluetoothSocket.connect();
if(device.getBondState()==BluetoothDevice.BOND_BONDED) {
outputStream = bluetoothSocket.getOutputStream();
isConnection = true;
if(bluetoothAdapter.isDiscovering()) {
System.out.println("关闭适配器!");
bluetoothAdapter.isDiscovering();
}
}
} catch (Exception e) {
Toast.makeText(PrintDataActivity.this,"连接失败!",1).show();
}
Toast.makeText(PrintDataActivity.this,device.getName()+"连接成功!",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(PrintDataActivity.this,"设备已连接",Toast.LENGTH_SHORT).show();
}
}</span>
关键代码就两句话:
<span style="font-size: 18px;"> </span><span style="font-size:18px;">bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
bluetoothSocket.connect();</span>
通过device.getBondState()==BluetoothDevice.BOND_BONDED判断是否连接成功
补充uuid的定义,固定的不用改:
private static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
6.权限的注册
<uses-permission android:name="android.permission.BLUETOOTH" />
如果使用adapter.enable()需要注册另外一个权限
另外别忘记了广播的注册和反注册。
至此关于android中蓝牙的基本使用介绍完毕,如有疑问可自行百度或者留言。
打印相关的知识和代码将在下篇文章中介绍,敬请期待。