android 蓝牙搜索、配对连接通信总结

蓝牙协议可以实现一个蓝牙设备和6到8个蓝牙设备进行通信。

1、蓝牙搜索的实现

利用蓝牙的发现和完成动作动态注册广播接受者获得蓝牙设备。

第一步,获得蓝牙适配器

BluetoothAdapter mBtAdapter= BluetoothAdapter.getDefaultAdapter();
// 判断蓝牙是否打开
if (!mAdapter.isEnabled()) {
    mAdapter.enable();
}

第二步动态注册蓝牙搜索广播接收者

  // Register for broadcasts when a device is discovered
  IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  this.registerReceiver(mReceiver, filter);

  // Register for broadcasts when discovery has finished
  filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
  this.registerReceiver(mReceiver, filter);

并且可以利用意图过滤器设置广播的优先级

 filter.setPriority(Integer.MAX_VALUE);

对应的广播接收者:

    // The BroadcastReceiver that listens for discovered devices and
    // changes the title when discovery is finished
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            // When discovery finds a device
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                // Get the BluetoothDevice object from the Intent
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                // If it's already paired, skip it, because it's been listed already
                if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
                    mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
                }
            // When discovery is finished, change the Activity title
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                setProgressBarIndeterminateVisibility(false);
                setTitle(R.string.select_device);
                if (mNewDevicesArrayAdapter.getCount() == 0) {
                    String noDevices = getResources().getText(R.string.none_found).toString();
                    mNewDevicesArrayAdapter.add(noDevices);
                }
            }
        }
    };

或者利用发现和完成动作定义两个广播接受者,在完成的动作中注销广播接收者。

关键代码如下:

    /**
     * 接收器 当搜索蓝牙设备完成时调用
     */
    private BroadcastReceiver _foundReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {

            BluetoothDevice device = intent
                    .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            // 将结果添加到列表中
            _devices.add(device);
            DeviceInfo info = new DeviceInfo();
            info.setmDeviceName(device.getName());
            info.setmDeviceMacAddr(device.getAddress());
            infos.add(info);
            info = null;
            // 显示列表
            showDevices();

        }
    };
    private BroadcastReceiver _discoveryReceiver = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            // 卸载注册的接收器
            unregisterReceiver(_foundReceiver);
            unregisterReceiver(this);
            _discoveryFinished = true;
        }
    };

这样便完成蓝牙的搜索了。

2、蓝牙配对

蓝牙要想通信目前是必须要先配对才能连接的。

蓝牙配对的api是hide的。但是api19可以直接调用蓝牙设备的配对方法。

所以配对都是利用反射的方法。这里有一个强大的工具类可以直接拿来使用,如下:

public class ClsUtils {

    public ClsUtils() {
        // TODO Auto-generated constructor stub
    }
     /** 
     * 与设备配对 参考源码:platform/packages/apps/Settings.git 
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
     */  
    static public boolean createBond(Class btClass, BluetoothDevice btDevice)  
    throws Exception  
    {  

        Method createBondMethod = btClass.getMethod("createBond");  
        Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);  
        return returnValue.booleanValue();  
    }  

    /** 
     * 与设备解除配对 参考源码:platform/packages/apps/Settings.git 
     * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
     */  
    static public boolean removeBond(Class btClass, BluetoothDevice btDevice)  
            throws Exception  
    {  
        Method removeBondMethod = btClass.getMethod("removeBond");  
        Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);  
        return returnValue.booleanValue();  
    }  

    static public boolean setPin(Class btClass, BluetoothDevice btDevice,  
            String str) throws Exception  
    {  
        try  
        {  
            Method removeBondMethod = btClass.getDeclaredMethod("setPin",  
                    new Class[]  
                    {byte[].class});  
            Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,  
                    new Object[]  
                    {str.getBytes()});  
            Log.e("returnValue设置密码", "" + returnValue.booleanValue());  
            return returnValue.booleanValue();  
        }  
        catch (SecurityException e)  
        {  
            // throw new RuntimeException(e.getMessage());  
            e.printStackTrace();  
        }  
        catch (IllegalArgumentException e)  
        {  
            // throw new RuntimeException(e.getMessage());  
            e.printStackTrace();  
        }  
        catch (Exception e)  
        {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
        return false;  

    }  

    // 取消用户输入  
    static public boolean cancelPairingUserInput(Class btClass,  
            BluetoothDevice device)  
    throws Exception  
    {  
        Method createBondMethod = btClass.getMethod("cancelPairingUserInput");  
        cancelBondProcess(btClass,device) ; 
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);  
        Log.i("取消对话框","cancelPairingUserInput"+returnValue.booleanValue());
        return returnValue.booleanValue();  
    }  

    // 取消配对  
    static public boolean cancelBondProcess(Class btClass,  
            BluetoothDevice device)  
    throws Exception  
    {  
        Method createBondMethod = btClass.getMethod("cancelBondProcess");  
        Boolean returnValue = (Boolean) createBondMethod.invoke(device);  
        return returnValue.booleanValue();  
    }  

    /** 
     * 
     * @param clsShow 
     */  
    static public void printAllInform(Class clsShow)  
    {  
        try  
        {  
            // 取得所有方法  
            Method[] hideMethod = clsShow.getMethods();  
            int i = 0;  
            for (; i < hideMethod.length; i++)  
            {  
                Log.e("method name", hideMethod[i].getName() + ";and the i is:"  
                        + i);  
            }  
            // 取得所有常量  
            Field[] allFields = clsShow.getFields();  
            for (i = 0; i < allFields.length; i++)  
            {  
                Log.e("Field name", allFields[i].getName());  
            }  
        }  
        catch (SecurityException e)  
        {  
            // throw new RuntimeException(e.getMessage());  
            e.printStackTrace();  
        }  
        catch (IllegalArgumentException e)  
        {  
            // throw new RuntimeException(e.getMessage());  
            e.printStackTrace();  
        }  
        catch (Exception e)  
        {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }  
    }  


    static public boolean pair(String strAddr, String strPsw)  
    {  
        boolean result = false;  
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter  
                .getDefaultAdapter();  

        bluetoothAdapter.cancelDiscovery();  

        if (!bluetoothAdapter.isEnabled())  
        {  
            bluetoothAdapter.enable();  
        }  



        BluetoothDevice device = bluetoothAdapter.getRemoteDevice(strAddr);  

        if (device.getBondState() != BluetoothDevice.BOND_BONDED)  
        {  
            try  
            {  
                Log.d("mylog", "NOT BOND_BONDED");  
                boolean flag1=ClsUtils.setPin(device.getClass(), device, strPsw); // 手机和蓝牙采集器配对  
                boolean flag2=ClsUtils.createBond(device.getClass(), device);  
//                remoteDevice = device; // 配对完毕就把这个设备对象传给全局的remoteDevice 

                     result = true;  


            }  
            catch (Exception e)  
            {  
                // TODO Auto-generated catch block  

                Log.d("mylog", "setPiN failed!");  
                e.printStackTrace();  
            } //  

        }  
        else  
        {  
            Log.d("mylog", "HAS BOND_BONDED");  
            try  
            {  
                ClsUtils.removeBond(device.getClass(), device);
                //ClsUtils.createBond(device.getClass(), device);  
               boolean flag1= ClsUtils.setPin(device.getClass(), device, strPsw); // 手机和蓝牙采集器配对  
                boolean flag2=ClsUtils.createBond(device.getClass(), device);  
//                remoteDevice = device; // 如果绑定成功,就直接把这个设备对象传给全局的remoteDevice 

                 result = true;  


            }  
            catch (Exception e)  
            {  
                // TODO Auto-generated catch block  
                Log.d("mylog", "setPiN failed!");  
                e.printStackTrace();  
            }  
        }  
        return result;  
    }  

}

蓝牙配对的关键代码:

 flag3= ClsUtils.createBond(device.getClass(), device);

其中device是蓝牙设备。在配对的时候会有一个配对广播,可以自定义一个广播接受者获取配对广播,然后在这个广播接收者里设置pin值,取消确定对话框,实现自动配对。关键代码如下:

mReceiver=new ParingReceiver(device);
IntentFilter filter=new IntentFilter();
filter.addAction( BluetoothDevice.ACTION_PAIRING_REQUEST);
filter.setPriority(Integer.MAX_VALUE);
registerReceiver(mReceiver, filter);

private class ParingReceived extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {

                 BluetoothDevice btDevice=mAdapter.getRemoteDevice("EC:89:F5:98:46:f9");

                    try {
                        setPin(btDevice.getClass(),btDevice,"000000");
                        cancelPairingUserInput(btDevice.getClass(), btDevice);

                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }


        }

在我的4.2系统上是没有效果的。找了一个上午的资料;网上给出了两种解决方法:(1)修改setting 系统源码,(2)模拟点击事件。

蓝牙配对完成后就可以连接通信了。

3、蓝牙通信

蓝牙同时的本质是蓝牙套接字,一个主动发起连接的的设备做客户端,一个监听连接的设备做服务端,类似sokcet网络编程,利用多线程,读取数据流就可完成蓝牙通信。

如下是蓝牙串口通信的关键代码:

    /**
     * 建立连接并通信
     * 
     * @param btDev
     * @return
     */
    private boolean connect(BluetoothDevice btDev) {
        boolean flag = false;
        try {
            /*if(btDev.fetchUuidsWithSdp()){
                btDev.getUuids();
            }*/


            //建立连接
            mSocket = btDev.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
            mSocket.connect();
            mOutputStream = mSocket.getOutputStream();
            mInputStream = mSocket.getInputStream();
            mOutputStream.write("StartOnNet\n".getBytes());


            mOutputStream.flush();
            flag = true;
        } catch (Exception e) {

        }

如下蓝牙服务端关键代码:

private class ServerThread implements Runnable {

        private InputStream mInputStream;
        private OutputStream mOutputStream;

        public ServerThread() {

        }

        @Override
        public void run() {

            try {

                while (true) {
                    mBluetoothServerSocket = mAdapter
                            .listenUsingRfcommWithServiceRecord(
                                    "btspp",
                                    UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));

                    Log.i("服务端线程运行", "蓝牙服务端线程开始");

                    Log.i("服务端线程运行", "蓝牙服务端线程阻塞中");

                    mBluetoothSocket = mBluetoothServerSocket.accept();
                    if (mBluetoothSocket != null) {

                        break;
                    }

                }

                Log.i("服务端线程运行", "蓝牙服务端线程<<<<<<<<<<<<<");
                mInputStream = mBluetoothSocket.getInputStream();
                mOutputStream = mBluetoothSocket.getOutputStream();
                byte[] data = getSocketResult(mInputStream);

                String tempString = new String(data);

                Log.i("蓝牙服务端监听str", tempString);
                // 向客户端发送数据
                if (tempString.equals("StartOnNet\n")) {

                    mOutputStream.write("haha".getBytes());
                    mOutputStream.flush();
                    if(!isServiceRunning("com.yqq.endClient3.service.GpsInfoCollectionService",BluethoothServer.this)){
                        // 开启GPS收集服务
                         gpsService= new Intent(BluethoothServer.this,
                                GpsInfoCollectionService.class);
                         Log.i("蓝牙服务端监听<<<<<<<<<<<<<<<<<<<<<<", "<<<<<<<<<<<<<<<<<");
                        startService(gpsService);
                    }

                }

            } catch (Exception e) {
                // TODO: handle exception
            } finally {
                if (mInputStream != null) {
                    try {
                        mInputStream.close();
                        mInputStream = null;
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

                if (mInputStream != null) {
                    try {
                        mOutputStream.close();
                        mOutputStream = null;
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
                if (mBluetoothSocket != null) {
                    try {
                        mBluetoothSocket.close();
                        mBluetoothSocket = null;
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
                if (mBluetoothServerSocket != null) {
                    try {
                        mBluetoothServerSocket.close();
                        mBluetoothServerSocket = null;
                        Looper.prepare();
                        Message message = Message.obtain();
                        message.what = 0x123456;
                        mHandler.sendMessage(message);
                        Looper.loop();

                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        }
    }

转自:http://www.2cto.com/kf/201502/374785.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值