蓝牙开发基本步骤:
一、设置权限
二、判断手机是否支持蓝牙,然后启动蓝牙
// 获取到蓝牙默认的适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter==null){
Toast.makeText(SecondActivity.this,"手机不支持蓝牙",Toast.LENGTH_SHORT).show();
return;
}
if (!mBluetoothAdapter.isEnabled()){//蓝牙未开启 则开启蓝牙
Intent enableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,200);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==200){
//蓝牙已开启
Toast.makeText(SecondActivity.this,"蓝牙已开启",Toast.LENGTH_SHORT).show();
}
}
三、搜索蓝牙设备
1、设置本机蓝牙可见
if(mBlueToothAdapter.getScanMode()==BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
Intent discoverableIntent=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//使本机在300秒内可被搜索
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(discoverableIntent);
}
2、查找曾经匹配的蓝牙设备
// 用Set集合保持已匹配的蓝牙设备
Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
if (devices.size() > 0) {
for (BluetoothDevice bluetoothDevice : devices) {
// 保存到arrayList集合中
bluetoothDevices.add(bluetoothDevice.getName() + ":"
+ bluetoothDevice.getAddress() + "\n");
}
}
3、搜索蓝牙设备
//先判断蓝牙设备是否在扫描
if (mBluetoothAdapter.isDiscovering()) {
//停止扫描
mBluetoothAdapter.cancelDiscovery();
}
mBluetoothAdapter.startDiscovery();
四、注册广播接收搜索到的蓝牙设备信息
// 因为蓝牙搜索到设备和完成搜索都是通过广播来告诉其他应用的
// 这里注册找到设备和完成搜索广播
IntentFilter filter=new IntentFilter(BluetoothDevice.ACTION_FOUND);
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED); //设备已经连接广播
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //设备断开连接广播
registerReceiver(receiver, filter);
// 注册广播接收者
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context arg0, Intent intent) {
// 获取到广播的action
String action = intent.getAction();
// 判断广播是搜索到设备还是搜索完成
if (action.equals(BluetoothDevice.ACTION_FOUND)) {
// 找到设备后获取其设备
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判断这个设备是否是之前已经绑定过了,如果是则不需要添加,在程序初始化的时候已经添加了
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 设备没有绑定过,则将其保持到arrayList集合中
bluetoothDevices.add(device.getName() + ":"
+ device.getAddress() + "\n");
// 更新字符串数组适配器,将内容显示在listView中
arrayAdapter.notifyDataSetChanged();
}
} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
setTitle("搜索完成");
}
}
};
五、模拟创建服务端
// 开启服务端 实例接收客户端传过来的数据线程
thread = new AcceptThread();
// 线程开始
thread.start();
// 服务端接收信息线程
private class AcceptThread extends Thread {
private BluetoothServerSocket serverSocket;// 服务端接口
private BluetoothSocket socket;// 获取到客户端的接口
private InputStream is;// 获取到输入流
private OutputStream os;// 获取到输出流
public AcceptThread() {
try {
// 通过UUID监听请求,然后获取到对应的服务端接口
serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (Exception e) {
// TODO: handle exception
}
}
public void run() {
try {
// 接收其客户端的接口请求
socket = serverSocket.accept();
// 获取到输入流
is = socket.getInputStream();
// 获取到输出流
os = socket.getOutputStream();
// 无限循环来接收数据
while (true) {
// 创建一个128字节的缓冲
byte[] buffer = new byte[128];
// 每次读取128字节,并保存其读取的角标
int count = is.read(buffer);
// 创建Message类,向handler发送数据
Message msg = new Message();
// 发送一个String的数据,让他向上转型为obj类型
msg.obj = new String(buffer, 0, count, "utf-8");
// 发送数据
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 创建handler,因为我们接收是采用线程来接收的,在线程中无法操作UI,所以需要handler
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
// 通过msg传递过来的信息,吐司一下收到的信息
Toast.makeText(SecondActivity.this, (String) msg.obj, Toast.LENGTH_SHORT).show();
}
};
六、模拟客户端发送消息
搜索出来的蓝牙设备列表,点击某一个item,发送
// 点击listView中的设备,传送数据
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// 获取到某一个设备的信息
String s =bluetoothDevices.get(position);
// 对其进行分割,获取到这个设备的地址
String address = s.substring(s.indexOf(":") + 1).trim();
// 判断当前是否还是正在搜索周边设备,如果是则暂停搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 如果选择设备为空则代表还没有选择设备
if (selectDevice == null) {
//通过地址获取到该设备
selectDevice = mBluetoothAdapter.getRemoteDevice(address);
}
// 这里需要try catch一下,以防异常抛出
try {
// 判断客户端接口是否为空
if (clientSocket == null) {
// 获取到客户端接口
clientSocket = selectDevice.createRfcommSocketToServiceRecord(MY_UUID);
// 向服务端发送连接
clientSocket.connect();
// 获取到输出流,向外写数据
os = clientSocket.getOutputStream();
}
// 判断是否拿到输出流
if (os != null) {
// 需要发送的信息
String text ="发送到"+selectDevice.getName()+"的信息";
// 以utf-8的格式发送出去
os.write(text.getBytes("UTF-8"));
}
// 吐司一下,告诉用户发送成功
Toast.makeText(this, "发送信息成功,请查收", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
// 如果发生异常则告诉用户发送失败
Toast.makeText(this, "发送信息失败", Toast.LENGTH_SHORT).show();
}
}
需要注意的地方:
1.如果手机之间传数据,保证两个手机都打开蓝牙
2.传数据时必须保证两个手机都处于非搜索蓝牙设备状态
3.两个手机之间同时运行,因为一个手机作为客户端,而另一个作为服务端,服务端必须保证在线可以访问状态