本文转载自:http://blog.csdn.net/vnanyesheshou/article/details/51554852
随着可穿戴设备的流行,研究蓝牙是必不可少的一门技术了。
总结了下蓝牙开发使用的一些东西分享一下。
首先需要AndroidManifest.xml文件中添加操作蓝牙的权限。
<uses-permissionandroid:name="Android.permission.BLUETOOTH" />
允许程序连接到已配对的蓝牙设备。
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" />
允许程序发现和配对蓝牙设备。
操作蓝牙主要用到的类 BluetoothAdapter类,使用时导包
import android.bluetooth.BluetoothAdapter;
源码具体位置frameworks/base/core/Java/android/bluetooth/BluetoothAdapter.java
BluetoothAdapter 代表本地设备的蓝牙适配器。该BluetoothAdapter可以执行基本的蓝牙任务,例如启
动设备发现,查询配对的设备列表,使用已知的MAC地址实例化一个BluetoothDevice类,并创建一个
BluetoothServerSocket监听来自其他设备的连接请求。
获取蓝牙适配器
[java] view plain copy
- BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
开启蓝牙
[java] view plain copy
- if(!mBluetoothAdapter.isEnabled()){
- //弹出对话框提示用户是后打开
- Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivityForResult(enabler, REQUEST_ENABLE);
- //不做提示,直接打开,不建议用下面的方法,有的手机会有问题。
- // mBluetoothAdapter.enable();
- }
获取本地蓝牙信息
[java] view plain copy
- //获取本机蓝牙名称
- String name = mBluetoothAdapter.getName();
- //获取本机蓝牙地址
- String address = mBluetoothAdapter.getAddress();
- Log.d(TAG,"bluetooth name ="+name+" address ="+address);
- //获取已配对蓝牙设备
- Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices();
- Log.d(TAG, "bonded device size ="+devices.size());
- for(BluetoothDevice bonddevice:devices){
- Log.d(TAG, "bonded device name ="+bonddevice.getName()+" address"+bonddevice.getAddress());
- }
打印:
[java] view plain copy
- D/MainActivity(16800): bluetooth name =Coolpad 8297 address =18:DC:56:D2:30:BD
- D/MainActivity(16800): bonded device size =1
- D/MainActivity(16800): bonded device name =小米手机 addressF8:A4:5F:02:B1:8F
搜索设备
mBluetoothAdapter.startDiscovery();
开始搜索设备,该过程是异步的,通过下面注册广播接受者,可以监听是否搜到设备。
[java] view plain copy
- IntentFilter filter = new IntentFilter();
- //发现设备
- filter.addAction(BluetoothDevice.ACTION_FOUND);
- //设备连接状态改变
- filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- //蓝牙设备状态改变
- filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
- registerReceiver(mBluetoothReceiver, filter);
监听扫描结果
[java] view plain copy
- private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver(){
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- Log.d(TAG,"mBluetoothReceiver action ="+action);
- if(BluetoothDevice.ACTION_FOUND.equals(action)){//每扫描到一个设备,系统都会发送此广播。
- //获取蓝牙设备
- BluetoothDevice scanDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if(scanDevice == null || scanDevice.getName() == null) return;
- Log.d(TAG, "name="+scanDevice.getName()+"address="+scanDevice.getAddress());
- //蓝牙设备名称
- String name = scanDevice.getName();
- if(name != null && name.equals(VnApplication.BLUETOOTH_NAME)){
- mBluetoothAdapter.cancelDiscovery();
- //取消扫描
- mProgressDialog.setTitle(getResources().getString(R.string.progress_connecting)); //连接到设备。
- mBlthChatUtil.connect(scanDevice);
- }
- }else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
- }
- }
- };
mBlthChatUtil.connect(scanDevice)连接到设备,
此方法中主要是获取socket客户端,并连接。
BluetoothSocket mmSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
mmSocket.connect();
当然有客户端就有服务端了,服务端应先开启,并一直等待客户端连接。直到连接成功。
[java] view plain copy
- private class AcceptThread extends Thread {
- // serverSocket
- private final BluetoothServerSocket mServerSocket;
- public AcceptThread() {
- BluetoothServerSocket tmp = null;
- // 创建一个新的侦听服务器套接字
- try {
- tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
- } catch (IOException e) {
- Log.e(TAG, "listen() failed", e);
- }
- mServerSocket = tmp;
- }
- public void run() {
- if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
- setName("AcceptThread");
- BluetoothSocket socket = null;
- // 循环,直到连接成功
- while (mState != STATE_CONNECTED) {
- try {
- // 这是一个阻塞调用和将只返回一个
- // 成功的连接或例外
- socket = mServerSocket.accept();
- } catch (IOException e) {
- Log.e(TAG, "accept() failed", e);
- break;
- }
- // 如果连接被接受
- if (socket != null) {
- synchronized (BluetoothChatUtil.this) {
- switch (mState) {
- case STATE_LISTEN:
- case STATE_CONNECTING:
- // 正常情况。启动连接螺纹。
- connected(socket, socket.getRemoteDevice());
- break;
- case STATE_NONE:
- case STATE_CONNECTED:
- // 没有准备或已连接。socket终止。
- try {
- socket.close();
- } catch (IOException e) {
- Log.e(TAG, "Could not close unwanted socket", e);
- }
- break;
- }
- }
- }
- }
- if (D) Log.i(TAG, "END mAcceptThread");
- }
- }
当连接成功后,connected(mmSocket, mmDevice); 获取输入输出流,从而进行通信。
private InputStream mmInStream = socket.getInputStream();
private OutputStream mmOutStream =socket.getOutputStream();
mmOutStream.write(buffer);发送信息。
mmInStream.read(buffer); 收到消息。
有时候扫描不到设备,需要设备蓝牙可见,这样才能被搜索到。
设置蓝牙可见性
[java] view plain copy
- Intent discoveryIntent = new Intent(
- BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
- discoveryIntent.putExtra(
- BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//时间300s,
- startActivity(discoveryIntent);