一:简介

       当两台android设备正常连接后,搜索与连接文章在这里(蓝牙搜索与连接),各自需要开启一个服务端和客户端接收消息(类似于socket),两台设备需要邦定同一个通信标识,通常是一个uuid。如:00001101-0000-1000-8000-00805F9B34FB

二:创建蓝牙服务端

     1)在已配对的蓝牙列表,选择需要通信的蓝牙设备

    

bondDevicesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                mBluetoothAdapter.cancelDiscovery();
                ClsUtils.closeDiscoverableTimeout(mBluetoothAdapter);
                final BluetoothDevice bluetoothDevice = bondDevices.get(position);//用户选择的蓝牙设备
                Bundle bun = new Bundle();
                Constant.setBluetoothDevice(bluetoothDevice);
                Intent intent = new Intent(mContenxt, ClientSendMsgAct.class);
                intent.putExtras(bun);
                startActivity(intent);
            }
        });

    2)启动一个线程创建服务端,两个通信的设备需要使用同一个蓝牙标识,如:Constant.PRIVATE_UUID

 @Override
    public void run() {
        try {
            adapter = BluetoothAdapter.getDefaultAdapter();
            serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord("myBluetooth", Constant.PRIVATE_UUID);
            mHandler.obtainMessage(CREATE_SUCCESS).sendToTarget();
            while (status) {
                socket = serverSocket.accept();
                doWork();
            }
        } catch (Exception e) {
            e.printStackTrace();
            setActivityMsg(CREATE_FAIL, "创建服务线程出现异常:" + e.getMessage());
        }
    }

三:发送文本消息

    1)发送文字消息前,需要创建一个线程,使用DataOutputStream来发送消息

BluetoothDevice serverDevice;//用户选择的蓝牙设备,详见2.1(在已配对的蓝牙列表,选择需要通信的蓝牙设备)代码
BluetoothSocket socket = serverDevice.createInsecureRfcommSocketToServiceRecord(Constant.PRIVATE_UUID);
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());

String sendMessage = "nihao"; int f_len = sendMessage.getBytes("UTF-8").length; //消息长度 long totalLen = 4 + 1 + 1 + f_len;//数据的总长度 byte[] data = new byte[f_len]; data = sendMessage.getBytes("UTF-8"); dataOutputStream.writeLong(totalLen); //1.写入数据的总长度 dataOutputStream.writeByte(type);//2.写入类型 dataOutputStream.writeByte(f_len); //3.写入消息的长度 dataOutputStream.write(data); //4.写入消息数据 dataOutputStream.flush();

 目前是测试,每发送一条消息启动一个线程,消息发送也不频繁,所以不会有影响

 BluetoothClientThread bluetoothClientThread = new BluetoothClientThread(clientHandler,mContext,msg,socket);
 new Thread(bluetoothClientThread).start();

 2)接收文字消息是在最早我们创建的,服务端线程里面

socket = serverSocket.accept();
dataInputStream = new DataInputStream(socket.getInputStream());
long totalLen = dataInputStream.readLong();//总长度
byte type = dataInputStream.readByte();//类型
 byte len = dataInputStream.readByte();//消息长度
byte[] ml = new byte[len];
int size = 0;
 int receivelen = 0;
 while (receivelen < len) {
   size = dataInputStream.read(ml, 0, ml.length);
    receivelen += size;
 }
msg = new String(ml, "UTF-8");
setActivityMsg(MSG, msg);//将消息回调到activity,并且刷新接收到的消息

3)发送图片消息

发送图片消息需要分为两步发送,第一次发图片名称,大小等,第二次才发正式发送图片,和soket一样。

  a)发送图片名称,大小

 fins=new FileInputStream(Constant.FILE_PATH+imagePath);
long fileDataLen = fins.available(); //文件的总长度
int f_len=imagePath.getBytes("UTF-8").length; //文件名长度
 byte[] data=new byte[f_len];
data=imagePath.getBytes("UTF-8");
 long totalLen = 4+1+1+f_len+fileDataLen;//数据的总长度
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeLong(totalLen); //1.写入数据的总长度
 dataOutputStream.writeByte(type);//2.写入类型
dataOutputStream.writeByte(f_len); //3.写入文件名的长度
 dataOutputStream.write(data);    //4.写入文件名的数据
 dataOutputStream.flush();

  b)正式发送图片

 FileInputStream fins=new FileInputStream("实际图片路径");
while((size=fins.read(buffer, 0, 1024*10))!=-1)
                {
                    dataOutputStream.write(buffer, 0, size);
                    dataOutputStream.flush();
                    sendlen+=size;
                    i++;
                    if(i%10==0){
                        long time2=Calendar.getInstance().getTimeInMillis();
                        tspeed=sendlen/(time2-time1)*1000/1024;
                    }
                    downbl = ((sendlen * 100) / fileDataLen);
                    Message msg = mHandler.obtainMessage(SEND_PROGRESS);
                    Bundle bun = new Bundle();
                    bun.putFloat("tspeed",downbl);
                    msg.setData(bun);
                    mHandler.sendMessage(msg);//更新发送进度
                }

4)接收图片消息

接收和发送一样,需要分为两步,第一步,接收图片名称,第二步,接收图片流

a)接收图片名称

byte len = dataInputStream.readByte();//文件名长度
 byte[] fn = new byte[len];
dataInputStream.read(fn);//读取文件名
 String filename = new String(fn, "UTF-8");

b)接收图片流

byte[] buffer = new byte[1024 * 1024];
long datalength = totalLen - 1 - 4 - 1 - fn.length;//文件数据
long receivelen = 0;
while (receivelen < datalength) {
                    size = dataInputStream.read(buffer);
                    fileOutputStream.write(buffer, 0, size);
                    receivelen += size;
                    i++;
                    if (i % 10 == 0) {
                        long time2 = Calendar.getInstance().getTimeInMillis();
                        tspeed = receivelen / (time2 - time1) * 1000 / 1024;
       }
    downbl = (receivelen * 100) / datalength;
 }

 

接收文字消息,文本消息代码结束了。

demo代码下载:github