«

android 通过蓝牙和设备通信 收发数据

时间:2024-3-2 17:55     作者:韩俊     分类: Android


这边由于我不知道我们公司的设备代码怎么设计的,所以不太清楚通用性如何,不过一般而言应该差不多吧。

首先我自定义了一个蓝牙连接管理的类,初始化的参数为Activity的context(这里我写的很随意,理论上这个类写在Service中更好):

public class BTManager {
    private Context context = null;
    private BluetoothAdapter adapter = null;
    private BroadcastReceiver receiver = null;
    private BTService bts = null;

    // 初始化
    public BTManager(Context context) {
        this.context = context;
        initAdapter();
        initRecevier();
    }
}
首先判断手机支不支持蓝牙功能,如果支持则开启蓝牙

// 看是否支持蓝牙
private void initAdapter() {
    adapter = BluetoothAdapter.getDefaultAdapter();
    if (adapter == null) {
        Toast.makeText(context, "该设备不支持蓝牙!", Toast.LENGTH_SHORT).show();
        return;
    }
    enabledBT();
}

// 开启蓝牙
private void enabledBT() {
    if (!adapter.isEnabled()) {
        Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        context.startActivity(mIntent);
    }
}
然后初始化广播,这个广播是要给Acitivty注册的,用来通知界面蓝牙连接的状态:

// 初始化广播
private void initRecevier() {
    if(receiver == null){
        receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String actionName = intent.getAction();
                if (actionName.equals("android.bluetooth.device.action.FOUND")) {
                    // 获取找到设备的对象
                    BluetoothDevice device = (BluetoothDevice) intent
                            .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

                    // 如果找到的设备和想要搜索的设备名一致,就发送找到广播
                    if (device.getName() != null
                            && device.getName().equalsIgnoreCase(
                                    Params.deviceName)) {
                        Intent it = new Intent(
                                "com.fisee.bluetooth.findFinished");
                        it.putExtra("state", true);
                        context.sendBroadcast(it);
                        cancelDiscover();

                        bts = new BTService(device);
                    }
                } else if (actionName
                        .equals("android.bluetooth.adapter.action.DISCOVERY_FINISHED")) {
                    // 搜索结束
                    Intent it = new Intent("com.fisee.bluetooth.findFinished");
                    it.putExtra("state", false);
                    context.sendBroadcast(it);

                    cancelDiscover();
                }
            }
        };
    }
}
android.bluetooth.device.action.FOUND为找到设备后收到的广播,但是周围开启的蓝牙设备都有可能被搜索到,所以要将搜索到的设备名和我们要搜索的设备名进行比较,如果一致则停止搜寻设备,进行连接。

android.bluetooth.adapter.action.DISCOVERY_FINISHED为搜索结束后收到的广播,一般蓝牙搜索的过程会持续12s,12s后没有找到要匹配的设备则收到此广播。

下面是开始搜寻设备的方法和停止搜寻设备的方法:

// 开始搜寻设备
public void discover(String name) {
    if (adapter == null) {
        return;
    }
    Params.deviceName = name;
    if (adapter.isDiscovering()) {
        Toast.makeText(context, "正在搜索请等待...", Toast.LENGTH_SHORT).show();
    } else {
        // 注册广播
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.bluetooth.device.action.FOUND");
        filter.addAction("android.bluetooth.adapter.action.DISCOVERY_FINISHED");
        context.registerReceiver(receiver, filter);

        adapter.startDiscovery();
    }
}

// 停止搜索设备
private void cancelDiscover() {
    // 如果还在搜寻设备,则停止
    if (adapter.isDiscovering()) {
        adapter.cancelDiscovery();
    }
    // 注销广播
    context.unregisterReceiver(receiver);
}
在搜寻开始时注册广播,如果搜寻结束,要记住注销广播。

然后我写了一个内部类,专门用来处理蓝牙收发数据:

public class BTService {
    private BluetoothDevice target = null;// socket连接的对象
    private Thread thread = null;// 接收数据线程
    private BluetoothSocket socket = null;// bt socket对象
    private boolean running = false;// socket是否正在运行

    public BTService(BluetoothDevice device) {
        running = false;
        closeSocket();
        target = device;
        if (thread == null) {
            thread = new Thread() {
                public void run() {
                    try {
                        Log.e("CREAT BT SOCKET", "creating bt socket");
                        /**
                         * 蓝牙socket连接的建立
                         */
                        Method m = target.getClass().getMethod(
                                "createRfcommSocket",
                                new Class[] { Integer.TYPE });
                        socket = ((BluetoothSocket) m.invoke(target,
                                new Object[] { Integer.valueOf(1) }));
                        socket.connect();
                    } catch (IOException e) {
                        closeSocket();
                        Log.e("IOException", "creat bt socket exception");
                    } catch (SecurityException e) {
                        closeSocket();
                        Log.e("SecurityException",
                                "close bt socket exception");
                    } catch (NoSuchMethodException e) {
                        closeSocket();
                        Log.e("Exception", "close bt socket exception");
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }

                    if (socket == null)
                        return;
                    running = true;
                    OnConnect();

                    byte[] buf = new byte[1024];
                    Log.e("creating success", "create bt socket success");
                    while (running) {
                        try {
                            InputStream isr = socket.getInputStream();
                            int sz = isr.read(buf);
                            isr = null;
                            if (sz <= 0) {
                                // Log.e("BluetoothSockTask",
                                // " read error size:" +
                                // sz);
                            } else {
                                // Log.e("BluetoothSockTask",
                                // " receive data success size:" + sz);
                                OnRecv(buf, sz);
                            }
                        } catch (Exception e) {
                            // Log.e("Exception","receive bt socket data exception");
                            if (running)
                                closeSocket();
                        }
                    }
                }
            };
        }
        thread.start();
    }

    // 关闭socket
    private void closeSocket() {
        running = false;
        if (this.socket == null) {
            return;
        }
        try {
            socket.close();
            System.out.println("closing bt socket");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        clear_bond();
        socket = null;
    }

    public void clear_bond() {
        BluetoothAdapter m_adapter = BluetoothAdapter.getDefaultAdapter();
        BluetoothDevice m_btdevice = null;
        Method removeBondMethod = null;
        int i = 0;
        Set<BluetoothDevice> m_dev_set = m_adapter.getBondedDevices();
        for (Iterator<BluetoothDevice> it = m_dev_set.iterator(); it
                .hasNext();) {
            Log.e("", "clear bond++++++++++++++ " + i);
            m_btdevice = it.next();
            i++;
            try {
                removeBondMethod = m_btdevice.getClass().getMethod(
                        "removeBond");// 移除沾和
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                @SuppressWarnings("unused")
                Boolean returnValue = (Boolean) removeBondMethod
                        .invoke(m_btdevice);
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }

    //socket创建成功
    public void OnConnect(){
        Intent intent = new Intent(
                "com.fisee.bluetooth.bluetoothConnected");
        context.sendBroadcast(intent);
    }

    //接收到数据
    public void OnRecv(byte[] buf,int size){
        byte[] data = new byte[size];
        for (int i = 0; i < size; i++) {
            data[i] = buf[i];
        }

        //处理数据
        System.out.println(data.length);
    }

    /**
     * 蓝牙socket发送出的数据
     * 
     * @param data
     * @param size
     * @return
     */
    public int sendData(byte[] data, int size) {    
        if ((!this.running) || (data == null) || (this.socket == null))
            return -1;
        try {
            OutputStream out = this.socket.getOutputStream();
            if (data.length <= size) {

                out.write(data);
                size = data.length;
            } else {
                out.write(data, 0, size);
            }
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            return 0;
        }
        return size;
    }
}
running相当于是个标志位,用来判断socket的状态,同时也控制着接收蓝牙数据的线程。sendData(byte[] data, int size) 方法是用来发送蓝牙包的。

标签: android

热门推荐