android实现主动连接和被动连接的蓝牙聊天功能

时间:2021-12-21 21:43:11

在项目中经常用到蓝牙的应用,在这里特意写了一个demo。并且封装了代码,可以主动连接和被动连接一起使用,也可以分开使用。方便后面以后查询使用,也重新踩了部分坑。

项目地址:android实现蓝牙聊天功能

1、程序简单的界面

android实现主动连接和被动连接的蓝牙聊天功能

android实现主动连接和被动连接的蓝牙聊天功能

android实现主动连接和被动连接的蓝牙聊天功能

2、客户端,主动连接

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package com.bluetooth.tool;
 
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
 
//蓝牙连接管理类
public class BluetoothManage {
 private static final Object mLock = new Object();
 //蓝牙类的具体实现核心成员
 private BluetoothAdapter mBtAdapter = BluetoothAdapter.getDefaultAdapter();
 //蓝牙类的具体数据核心成员
 private BluetoothSocket mTransferSocket = null;
 //当前连接的蓝牙地址
 String mstrName = "";//当前连接用到的IP地址
 String mstrAddress = "";//当前连接用到的IP地址
 //读线程
 ReadThread mReadThread = null;
 //从数据核心成员拿到的输入输出
 InputStream mInputStream = null;
 OutputStream mOutputStream = null;
 private static BluetoothManage manage = null;
 
 public static BluetoothManage getInstance(){
 synchronized (BluetoothManage.class){
  if(manage == null)
  manage = new BluetoothManage();
 }
 return manage;
 }
 
 public boolean sendData(int nLength, byte[] data) {
 if (mOutputStream == null) return false;
 try {
  mOutputStream.write(data, 0, nLength);
  return true;
 } catch (IOException e) {
  e.printStackTrace();
 }
 return false;
 }
 
 ConnectListener mConnectListener = null;
 
 public void regConnectListener(ConnectListener arg0) {
 mConnectListener = arg0;
 }
 
 TopDataIOListener mIOListener = null;
 
 public void regIOListener(TopDataIOListener arg0) {
 mIOListener = arg0;
 }
 
 public void unRegIOListener() {
 mIOListener = null;
 }
 
 public boolean setSelectedDevice(String strDevice) {
 String[] strings = strDevice.split("\\|");
 
 if (strings.length == 2) {
  mstrName = strings[0];
  mstrAddress = strings[1];
  return true;
 }
 return false;
 }
 
 public String getSelectedDeviceName() {
 if (mstrAddress.length() == 0) {
  return null;
 }
 
 return String.format("%s|%s", mstrName, mstrAddress);
 }
 
 public void connect() {
 if (mstrAddress.length() == 0) return;
 
 final BluetoothDevice device = mBtAdapter.getRemoteDevice(mstrAddress);
 new Thread(new Runnable() {
  @Override
  public void run() {
  synchronized (mLock) {
   String strLogString = "";
   try {
   try {
    mTransferSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
   } catch (IOException e1) {
    mTransferSocket = null;
   }
 
   if (mTransferSocket == null) {
    if (null != mConnectListener)
    mConnectListener.OnConnectStatusCallBack(false);
    return;
   }
   long nStartMillTime = System.currentTimeMillis();
 
   //连接
   try {
    mTransferSocket.connect();
   } catch (IOException e1) {
    try {
    mTransferSocket.close();
    } catch (IOException e2) {
    e2.printStackTrace();
    }
    //等待一定时间
    mTransferSocket = null;
 
    try {
    long havePassTime = System.currentTimeMillis() - nStartMillTime;
    if (havePassTime < 6000) {
     Thread.sleep(7000 - havePassTime);
    }
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
   }
   //连接失败
   if (mTransferSocket == null) {
    if (null != mConnectListener)
    mConnectListener.OnConnectStatusCallBack(false);
    return;
   }
 
   try {
    mInputStream = mTransferSocket.getInputStream();
    mOutputStream = mTransferSocket.getOutputStream();
    mReadThread = new ReadThread();
    mReadThread.start();
 
    if (null != mConnectListener)
    mConnectListener.OnConnectStatusCallBack(true);
   } catch (IOException e1) {
    //断开连接
    try {
    if (mTransferSocket != null)
     mTransferSocket.close();
    } catch (IOException e2) {
    e2.printStackTrace();
    }
 
    mTransferSocket = null;
    e1.printStackTrace();
 
    if (null != mConnectListener)
    mConnectListener.OnConnectStatusCallBack(false);
   }
   } catch (Exception e) {
   //总体异常
   if (null != mConnectListener)
    mConnectListener.OnConnectStatusCallBack(false);
   }
  }
  }//run()
 }).start();
 }
 
 //读取数据
 class ReadThread extends Thread {
 public void run() {
  int nMaxBufLength = 1024;
  byte[] buffer = new byte[nMaxBufLength];
  int byteRead = -1;
 
  synchronized (mLock) {
  while (!isInterrupted()) {
   try {
   if (mInputStream != null) {
    byteRead = mInputStream.read(buffer);
    if (byteRead > 0 && byteRead <= buffer.length) {
    if (mIOListener != null)
     mIOListener.OnIOCallBack(byteRead, buffer);
    } else /*if (byteRead < 0 || byteRead > buffer.length)*/ {
    //连接已断开
    if (mConnectListener != null) {
     mConnectListener.OnDisConnectCallBack();
    }
    break;
    }
   } else {
    break;
   }
   } catch (IOException e) {
   //连接已断开
   if (mConnectListener != null) {
    mConnectListener.OnDisConnectCallBack();
   }
   break;
   }
  }//while(!isInterrupted())
  }//synchronized (mLock)
 }
 }
 
 //断开蓝牙
 public void disConnect() {
 mConnectListener = null;
 //结束读线程
 if (mReadThread != null) {
  mReadThread.interrupt();
  mReadThread = null;
 }
 //取消所有连接
 if (mTransferSocket != null) {
  try {
  mTransferSocket.close();
  if (mInputStream != null)
   mInputStream.close();
  if (mOutputStream != null)
   mOutputStream.close();
  mInputStream = null;
  mOutputStream = null;
  mTransferSocket = null;
  } catch (IOException e) {
  e.printStackTrace();
  } catch (Exception e) {
  }
 }
 }
}

主动连接应该是比较简单的,一个类就能实现,包括数据的收发。

3、蓝牙服务端,接收蓝牙连接

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
/**
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package com.bluetooth.tool;
 
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
 
/**
 * This class does all the work for setting up and managing Bluetooth
 * connections with other devices. It has a thread that listens for incoming
 * connections, a thread for connecting with a device, and a thread for
 * performing data transmissions when connected.
 */
public class BluetoothChatService {
 // Debugging
 private static final String TAG = "BluetoothChatService";
 private static final boolean D = true;
 
 // Name for the SDP record when creating server socket
 private static final String NAME = "BluetoothChat";
 
 // Unique UUID for this application
 // private static final UUID MY_UUID =
 // UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
 private static final UUID MY_UUID = UUID
  .fromString("00001101-0000-1000-8000-00805F9B34FB");
 //
 
 // Member fields
 private final BluetoothAdapter mAdapter;
 private final Handler mHandler;
 private AcceptThread mAcceptThread;
 private ConnectThread mConnectThread;
 private ConnectedThread mConnectedThread;
 private int mState;
 private BluetoothDevice mBluetoothDevice = null;
 
 // Constants that indicate the current connection state
 public static final int STATE_NONE = 0; // we're doing nothing
 public static final int STATE_LISTEN = 1; // now listening for incoming
      // connections
 public static final int STATE_CONNECTING = 2; // now initiating an outgoing
       // connection
 public static final int STATE_CONNECTED = 3; // now connected to a remote
       // device
 
 public static boolean mbIsOpenTimer = false;
 /**
 * Constructor. Prepares a new BluetoothChat session.
 *
 * @param context
 *  The UI Activity Context
 * @param handler
 *  A Handler to send messages back to the UI Activity
 */
 public BluetoothChatService(Context context, Handler handler) {
 mAdapter = BluetoothAdapter.getDefaultAdapter();
 mState = STATE_NONE;
 mHandler = handler;
 }
 
 /**
 * Set the current state of the chat connection
 *
 * @param state
 *  An integer defining the current connection state
 */
 private synchronized void setState(int state) {
 if (D)
  Log.d(TAG, "setState() " + mState + " -> " + state);
 mState = state;
 
 // Give the new state to the Handler so the UI Activity can update
 mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1)
  .sendToTarget();
 }
 
 /**
 * Return the current connection state.
 */
 public synchronized int getState() {
 return mState;
 }
 
 /**
 * Start the chat service. Specifically start AcceptThread to begin a
 * session in listening (server) mode. Called by the Activity onResume()
 */
 public synchronized void start() {
 if (D)
  Log.d(TAG, "start");
 
 // Cancel any thread attempting to make a connection
 if (mConnectThread != null) {
  mConnectThread.cancel();
  mConnectThread = null;
 }
 
 // Cancel any thread currently running a connection
 if (mConnectedThread != null) {
  mConnectedThread.cancel();
  mConnectedThread = null;
 }
 
 // Start the thread to listen on a BluetoothServerSocket
 if (mAcceptThread == null) {
  Log.d(TAG, "start mAcceptThread");
  mAcceptThread = new AcceptThread();
  mAcceptThread.start();
 }
 setState(STATE_LISTEN);
 }
 
 /**
 * Start the ConnectThread to initiate a connection to a remote device.
 *
 * @param device
 *  The BluetoothDevice to connect
 */
 public synchronized void connect(BluetoothDevice device) {
 if (D)
  Log.d(TAG, "connect to: " + device);
 
 // Cancel any thread attempting to make a connection
 if (mState == STATE_CONNECTING) {
  if (mConnectThread != null) {
  mConnectThread.cancel();
  mConnectThread = null;
  }
 }
 
 // Cancel any thread currently running a connection
 if (mConnectedThread != null) {
  mConnectedThread.cancel();
  mConnectedThread = null;
 }
 
 // Start the thread to connect with the given device
 mConnectThread = new ConnectThread(device);
 mConnectThread.start();
 setState(STATE_CONNECTING);
 mBluetoothDevice = device;
 }
 
 /**
 * Start the ConnectedThread to begin managing a Bluetooth connection
 *
 * @param socket
 *  The BluetoothSocket on which the connection was made
 * @param device
 *  The BluetoothDevice that has been connected
 */
 public synchronized void connected(BluetoothSocket socket,
  BluetoothDevice device) {
 if (D)
  Log.d(TAG, "connected");
 
 // Cancel the thread that completed the connection
 if (mConnectThread != null) {
  mConnectThread.cancel();
  mConnectThread = null;
 }
 
 // Cancel any thread currently running a connection
 if (mConnectedThread != null) {
  mConnectedThread.cancel();
  mConnectedThread = null;
 }
 
 // Cancel the accept thread because we only want to connect to one
 // device
 if (mAcceptThread != null) {
  mAcceptThread.cancel();
  mAcceptThread = null;
 }
 
 // Start the thread to manage the connection and perform transmissions
 mConnectedThread = new ConnectedThread(socket);
 mConnectedThread.start();
 
 // Send the name of the connected device back to the UI Activity
 Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
 Bundle bundle = new Bundle();
 bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
 msg.setData(bundle);
 mHandler.sendMessage(msg);
 
 setState(STATE_CONNECTED);
 }
 
 /**
 * Stop all threads
 */
 public synchronized void stop() {
 if (D)
  Log.d(TAG, "stop");
 if (mConnectThread != null) {
  mConnectThread.cancel();
  mConnectThread = null;
 }
 if (mConnectedThread != null) {
  mConnectedThread.cancel();
  mConnectedThread = null;
 }
 if (mAcceptThread != null) {
  mAcceptThread.cancel();
  mAcceptThread = null;
 }
 setState(STATE_NONE);
 }
 
 /**
 * Write to the ConnectedThread in an unsynchronized manner
 *
 * @param out
 *  The bytes to write
 * @see ConnectedThread#write(byte[])
 */
 public void write(byte[] out) {
 // Create temporary object
 ConnectedThread r;
 // Synchronize a copy of the ConnectedThread
 synchronized (this) {
  if (mState != STATE_CONNECTED)
  return;
  r = mConnectedThread;
 }
 // Perform the write unsynchronized
 r.write(out);
 }
 
 /**
 * Indicate that the connection attempt failed and notify the UI Activity.
 */
 private void connectionFailed() {
 setState(STATE_LISTEN);
 
 // Send a failure message back to the Activity
 Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
 Bundle bundle = new Bundle();
 bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
 msg.setData(bundle);
 mHandler.sendMessage(msg);
 }
 
 /**
 * Indicate that the connection was lost and notify the UI Activity.
 */
 private void connectionLost() {
 setState(STATE_LISTEN);
 
 // Send a failure message back to the Activity
 Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
 Bundle bundle = new Bundle();
 bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
 msg.setData(bundle);
 mHandler.sendMessage(msg);
 start();
 }
 
 /**
 * This thread runs while listening for incoming connections. It behaves
 * like a server-side client. It runs until a connection is accepted (or
 * until cancelled).
 */
 private class AcceptThread extends Thread {
 // The local server socket
 private final BluetoothServerSocket mmServerSocket;
 
 public AcceptThread() {
  BluetoothServerSocket tmp = null;
 
  // Create a new listening server socket
  try {
  tmp = mAdapter
   .listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
  } catch (IOException e) {
  Log.e(TAG, "listen() failed", e);
  }
  mmServerSocket = tmp;
 }
 
 public void run() {
  if (D)
  Log.d(TAG, "BEGIN mAcceptThread" + this);
  setName("AcceptThread");
  BluetoothSocket socket = null;
 
  // Listen to the server socket if we're not connected
  while (mState != STATE_CONNECTED) {
  try {
   // This is a blocking call and will only return on a
   // successful connection or an exception
   if(mmServerSocket != null)
   {
   Log.d(TAG, "waitting accept!");
   socket = mmServerSocket.accept();
   Log.d(TAG, "accpting!");
   }
   else
   {
   setState(STATE_NONE);
    
   if (mAcceptThread != null) {
    mAcceptThread = null;
   }
    
   Log.d(TAG, "mmServerSocket = null!");
   break;
   }
   
  } catch (IOException e) {
   Log.e(TAG, "accept() failed", e);
   break;
  }
 
  // If a connection was accepted
  if (socket != null) {
   synchronized (BluetoothChatService.this) {
   switch (mState) {
   case STATE_LISTEN:
   case STATE_CONNECTING:
    // Situation normal. Start the connected thread.
    connected(socket, socket.getRemoteDevice());
    break;
   case STATE_NONE:
   case STATE_CONNECTED:
    // Either not ready or already connected. Terminate
    // new socket.
    try {
    socket.close();
    } catch (IOException e) {
    Log.e(TAG, "Could not close unwanted socket", e);
    }
    break;
   }
   }
  }
  }
  if (D)
  Log.i(TAG, "END mAcceptThread");
 }
 
 public void cancel() {
  if (D)
  Log.d(TAG, "cancel " + this);
  try {
  if(mmServerSocket != null)
   mmServerSocket.close();
  } catch (IOException e) {
  Log.e(TAG, "close() of server failed", e);
  }
 }
 }
 
 /**
 * This thread runs while attempting to make an outgoing connection with a
 * device. It runs straight through; the connection either succeeds or
 * fails.
 */
 private class ConnectThread extends Thread {
 private final BluetoothSocket mmSocket;
 private final BluetoothDevice mmDevice;
 
 public ConnectThread(BluetoothDevice device) {
  mmDevice = device;
  BluetoothSocket tmp = null;
 
  // Get a BluetoothSocket for a connection with the
  // given BluetoothDevice
  try {
  tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
  } catch (IOException e) {
  Log.e(TAG, "create() failed", e);
  }
  mmSocket = tmp;
 }
 
 public void run() {
  Log.i(TAG, "BEGIN mConnectThread");
  setName("ConnectThread");
 
  // Always cancel discovery because it will slow down a connection
  mAdapter.cancelDiscovery();
 
  // Make a connection to the BluetoothSocket
  try {
  // This is a blocking call and will only return on a
  // successful connection or an exception
  mmSocket.connect();
  } catch (IOException e) {
  connectionFailed();
  // Close the socket
  try {
   mmSocket.close();
  } catch (IOException e2) {
   Log.e(TAG,
    "unable to close() socket during connection failure",
    e2);
  }
  // Start the service over to restart listening mode
  BluetoothChatService.this.start();
  return;
  }
 
  // Reset the ConnectThread because we're done
  synchronized (BluetoothChatService.this) {
  mConnectThread = null;
  }
 
  // Start the connected thread
  connected(mmSocket, mmDevice);
 }
 
 public void cancel() {
  try {
  mmSocket.close();
  } catch (IOException e) {
  Log.e(TAG, "close() of connect socket failed", e);
  }
 }
 }
 
 /**
 * This thread runs during a connection with a remote device. It handles all
 * incoming and outgoing transmissions.
 */
 private class ConnectedThread extends Thread {
 private final BluetoothSocket mmSocket;
 private final InputStream mmInStream;
 private final OutputStream mmOutStream;
 
 public ConnectedThread(BluetoothSocket socket) {
  Log.d(TAG, "create ConnectedThread");
  mmSocket = socket;
  InputStream tmpIn = null;
  OutputStream tmpOut = null;
  try {
  tmpIn = socket.getInputStream();
  tmpOut = socket.getOutputStream();
  } catch (IOException e) {
  Log.e(TAG, "temp sockets not created", e);
  }
 
  mmInStream = tmpIn;
  mmOutStream = tmpOut;
 }
 
 public void run() {
  Log.i(TAG, "BEGIN mConnectedThread");
  byte[] buffer = new byte[1024];
  int bytes;
 
  // Keep listening to the InputStream while connected
  while (true) {
  try {
   // Read from the InputStream
   if(mmInStream != null ){
   bytes = mmInStream.read(buffer);
   if(bytes > 0 && bytes <= buffer.length)
   {
    onDadaReceive(buffer,0,bytes);
   }
   else{
    Log.i("recieve", "Baddata");
   }
   }
   else{
   Log.i(TAG, "BadInputStream");
   connectionLost();
   break;
   }
  }
  catch (IOException e) {
   Log.i(TAG, "disconnected" + e.toString(), e);
   connectionLost();
   break;
  } catch (Exception e) {
   e.printStackTrace();
  }
  }
 }
 
 private void onDadaReceive(byte[] buffer, int i, int bytes) {
  if(bytes>0)
  {
  //֪ͨܘַ
  mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes,
   -1, buffer).sendToTarget();
 
  }
  else
  Log.e("recieve","null");
 
 }
 
 /**
  * Write to the connected OutStream.
  *
  * @param buffer
  *  The bytes to write
  */
 public void write(byte[] buffer) {
  try {
  mmOutStream.write(buffer);
 
  // Share the sent message back to the UI Activity
  mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1,
   buffer).sendToTarget();
  } catch (IOException e) {
  Log.e(TAG, "Exception during write", e);
  }
 }
 
 public void cancel() {
  try {
  mmSocket.close();
  } catch (IOException e) {
  Log.e(TAG, "close() of connect socket failed", e);
  }
 }
 }
 
}

这个蓝牙服务的代码,是标准蓝牙示例demo代码

我根据上面,自已封装了一层,方便管理数据。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package com.bluetooth.tool;
 
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
 
/**
 * 蓝牙服务,接收蓝牙连接
 */
public class BluetoothChat {
 // Debugging
 private static final String TAG = "BluetoothChat";
 private static final boolean D = true;
 
 public static final int MESSAGE_STATE_CHANGE = 1;
 public static final int MESSAGE_READ = 2;
 public static final int MESSAGE_WRITE = 3;
 public static final int MESSAGE_DEVICE_NAME = 4;
 public static final int MESSAGE_TOAST = 5;
 
 // Key names received from the BluetoothChatService Handler
 public static final String DEVICE_NAME = "device_name";
 public static final String TOAST = "toast";
 
 private String mConnectedDeviceName = null;
 private static StringBuffer mOutStringBuffer;
 private static BluetoothChatService mChatService = null;
 private static Context mContext;
 private volatile static BluetoothChat mBluetoothChat = null;
 TopDataIOListener mIOListener = null;
 
 public static BluetoothChat GetInstance(Context context) {
 if (mBluetoothChat == null && mContext == null) {
  synchronized (BluetoothChat.class){
  mBluetoothChat = new BluetoothChat();
  mContext = context;
  }
 }
 return mBluetoothChat;
 }
 
 
 public void onStart() {
 if (mChatService == null)
  setupChat();
 if (mChatService != null) {
  if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
  mChatService.start();
  }
 }
 }
 
 private void setupChat() {
 mChatService = new BluetoothChatService(mContext,mHandler);
 mOutStringBuffer = new StringBuffer("");
 }
 
 public void onDestroy() {
 if (mChatService != null)
  mChatService.stop();
 }
 
 public void sendMessage(String message) {
 if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
  Log.i("Show", "");
  return;
 }
 if (message.length() > 0) {
  byte[] send = message.getBytes();
  mChatService.write(send);
  mOutStringBuffer.setLength(0);
 }
 }
 
 private final Handler mHandler = new Handler() {
 @Override
 public void handleMessage(Message msg) {
  switch (msg.what) {
  case MESSAGE_STATE_CHANGE:
  if (D)
   Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
  switch (msg.arg1) {
  case BluetoothChatService.STATE_CONNECTED:
   break;
  case BluetoothChatService.STATE_CONNECTING:
   break;
  case BluetoothChatService.STATE_LISTEN:
   break;
  case BluetoothChatService.STATE_NONE:
   break;
  }
  break;
  case MESSAGE_WRITE:
  byte[] writeBuf = (byte[]) msg.obj;
  String writeMessage = new String(writeBuf);
  break;
  case MESSAGE_READ:
  byte[] readBuf = (byte[]) msg.obj;
  //收到的蓝牙数据,回传给界面显示
  if (mIOListener != null)
   mIOListener.OnIOCallBack(readBuf.length, readBuf);
  break;
  case MESSAGE_DEVICE_NAME:
  mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
  Log.i(TAG, "MESSAGE_DEVICE_NAME " + mConnectedDeviceName);
  break;
  case MESSAGE_TOAST:
  break;
  }
 }
 };
 
 public void regIOListener(TopDataIOListener arg0) {
 mIOListener = arg0;
 }
 
}

还有一个蓝牙的广播。这里就不贴代码了。

4、权限

?
1
2
3
4
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- 部分手机6.0以上 蓝牙startDiscovery方法需要加上这个权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

蓝牙服务接收广播注册

?
1
2
3
4
5
6
7
8
<receiver android:name=".tool.BluetoothReceiver">
 <intent-filter android:priority="1000">
 <action android:name="android.bluetooth.adapter.action.STATE_CHANGED"/>
 <action android:name="android.bluetooth.device.action.ACL_CONNECTED"/>
 <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED"/>
 <action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED"/>
 </intent-filter>
</receiver>

5、在上面注释看到了有个bug注释

就是部分手机6.0以上 蓝牙蓝牙startDiscovery方法需要加上这个权限android.permission.ACCESS_COARSE_LOCATION。不然启动搜索蓝牙无效。

原文链接:https://blog.csdn.net/qq_16064871/article/details/78725195