微信扫一扫

028-83195727 , 15928970361
business@forhy.com

Android 蓝牙开发(一)蓝牙通信

Android,蓝牙,Bluetooth2016-06-07

随着可穿戴设备的流行,研究蓝牙是必不可少的一门技术了。

总结了下蓝牙开发使用的一些东西分享一下。


首先需要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监听来自其他设备的连接请求。


获取蓝牙适配器

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
开启蓝牙

 if(!mBluetoothAdapter.isEnabled()){
//弹出对话框提示用户是后打开
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
      //不做提示,直接打开,不建议用下面的方法,有的手机会有问题。
      // mBluetoothAdapter.enable();
}


搜索设备

mBluetoothAdapter.startDiscovery();

开始搜索设备,该过程是异步的,通过下面注册广播接受者,可以监听是否搜到设备。

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);

监听扫描结果

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();


当然有客户端就有服务端了,服务端应先开启,并一直等待客户端连接。直到连接成功。

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); 收到消息。


有时候扫描不到设备,需要设备蓝牙可见,这样才能被搜索到。

设置蓝牙可见性

Intent discoveryIntent = new Intent(
	BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoveryIntent.putExtra(
BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//时间300s,
startActivity(discoveryIntent);