[Android蓝牙]三步实现蓝牙聊天APP

先看下结构目录

 

  1. ChatService.java —— 蓝牙连接
  2. DeviceList.java   —— 设备显示
  3. MainActivity.java—— 主界面

1.权限

要获取蓝牙功能,先在AndroidManifest.xml中申请权限

    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

 

2.界面

先从比较直观的地方 弹 起吧。

                            

 

 

主聊天界面:Listview显示对话,EditText编辑消息,Button发送消息

设备列表:2*ListView分别显示已配对和搜索到的设备。Button按钮开始查找。

下面讲讲如何实现其功能

3.代码

挑几个关键的地方,其它细节就不一一赘述了。

3.1 DeviceList —— 蓝牙搜索设备功能

蓝牙搜索主要是要实现一个BroadcastReceiver 广播接收者。
首先要注册广播,才能使用,添加蓝牙设备ACTION_FOUND等,如下
    private IntentFilter filter = new IntentFilter();
    …………………………………………………

    filter.addAction(BluetoothDevice.ACTION_FOUND);
    filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    this.registerReceiver(mReceiver,filter);
其次就是这里广播接收
一旦开启广播搜索,并找到设备 接收到ACTION_FOUND的信息,则可以从BluetoothDevice.EXTRA_DEVICE中得到搜索到的设备信息,显示到屏幕上。
如果是DISCOVERY_FINISHED,即结束搜索。  下方代码为看起来方便,省略了一些不必要的。
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override public void onReceive(Context context, Intent intent) {
            String action=intent.getAction();
            if(BluetoothDevice.ACTION_FOUND.equals(action)){
                BluetoothDevice  device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 得到设备信息
            }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED
                    .equals(action)){ //结束搜索了  }
            }
        }
    };

3.2 ChatService —— 蓝牙连接功能

通过3个线程来实现。

 3.2.1 AcceptThread —— 被动等待连接的线程

使用BluetoothServerSocket accept函数,收到连接,则保持此连接传给 ConnectedThread 
    // 创建监听线程,准备接受新连接。使用阻塞方式,调用BluetoothServerSocket.accept()
    private class AcceptThread extends Thread{
        private final BluetoothServerSocket mmServerSocket;

        public AcceptThread(){
            BluetoothServerSocket tmp = null;
            try{
                tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
            }catch (IOException e){}
            mmServerSocket = tmp;
        }


        public void run(){
        BluetoothSocket socket= null;

        while(mState != STATE_CONNECTED){
            try{
                socket = mmServerSocket.accept();
            }catch (IOException e) {
                break;
            }
            if(socket != null){
                connected(socket,socket.getRemoteDevice());
                try{
                    mmServerSocket.close();
                }catch (IOException e){}
            }
        }
    }

        public void cancel(){
            try{
                mmServerSocket.close();
            }catch (IOException e){}
        }
}

 3.2.1 ConnectThread —— 主动发起连接的线程

createRfcommSocketToServiceRecord 根据UUID 发起连接,连接成功则将连接传入ConnectedThread
// 连接线程,专门用来对外发出连接对方蓝牙的请求并进行处理
    // 构造函数里通过BluetoothDevice.createRfcommSocketToServiceRecord(),
    // 从待连接的device产生BluetoothSocket,然后在run方法中connect
    // 成功后调用 BluetoothChatService的connnected()方法,定义cancel()在关闭线程时能关闭socket
    private class ConnectThread extends Thread{
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public ConnectThread(BluetoothDevice device){
            // Use a temporary object that is later assigned to mmSocket,
            // because mmSocket is final
            mmDevice=device;
            BluetoothSocket tmp = null;
            // Get a BluetoothSocket to connect with the given BluetoothDevice
            try{
                // MY_UUID is the app's UUID string, also used by the server code
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
            }catch (IOException e){}
            mmSocket = tmp;
        }

        public void run(){
            // Cancel discovery because it will slow down the connection
            mAdapter.cancelDiscovery();
            try{
                // Connect the device through the socket. This will block
                // until it succeeds or throws an exception
                mmSocket.connect();
            }catch (IOException e){
                connectionFailed();
                // Unable to connect; close the socket and get out
                try{
                    mmSocket.close();
                }catch (IOException e2){}

                //ChatService.this.start();
               return;
           }
            synchronized(ChatService.this){
                mConnectedThread = null;
           }
            connected(mmSocket,mmDevice);
        }

        public void cancel(){
           /* try{
                mmSocket.close();
            }catch (IOException e){}*/
        }
    }

 3.2.1 ConnectedThread —— 管理连接的线程

管理连接好的双方,进行数据通信。输入输出流,接收数据,发送数据
 // 双方蓝牙连接后一直运行的线程。构造函数中设置输入输出流。
    // Run方法中使用阻塞模式的InputStream.read()循环读取输入流
    // 然后psot到UI线程中更新聊天信息。也提供了write()将聊天消息写入输出流传输至对方,
    // 传输成功后回写入UI线程。最后cancel()关闭连接的socket

    private class ConnectedThread extends Thread{
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        public ConnectedThread(BluetoothSocket socket){
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut=null;
            // Get the input and output streams, using temp objects because
            // member streams are final
            try{
                tmpIn=mmSocket.getInputStream();
                tmpOut=mmSocket.getOutputStream();
            }catch (IOException e){}

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run(){
            byte[]buffer=new byte[1024];
            int bytes;
            while (true){
                try{
                    bytes = mmInStream.read(buffer);
                    mHandler.obtainMessage(MainActivity.MESSAGE_READ,bytes,-1,buffer).sendToTarget();
                }catch (IOException e){
                    connectionLost();
                    break;
                }
            }
        }

        public void write(byte[]buffer){
            try{
                mmOutStream.write(buffer);
            }catch (IOException e){
                Log.d("MainActivity","Send Fail");
            }
            mHandler.obtainMessage(MainActivity.MESSAGE_WRITE,buffer).sendToTarget();
        }

        public void cancel(){
            try{
                mmSocket.close();
            }catch (IOException e){}
        }
    }

3.3 MainActivity—— 主聊天界面

    主要是将双方信息显示在上方,listview的操作,就不讲了。


最后,源码地址奉上:https://github.com/Zweo/Bluetooth

 
 
 
 
 
 
 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    1.  
 
 
 
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/weixin_42165585/article/details/83113484
今日推荐