1. 程式人生 > >Android適配安卓6.0藍芽通訊實現過程

Android適配安卓6.0藍芽通訊實現過程

實現需要的許可權:由於安卓4.x版以上的版本使用藍芽,需要開啟定位許可權才能搜尋到附近的藍芽裝置

1

2

3

4

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

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

  

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"

/>

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

服務端

實現思路:
1,拿到本地藍芽裝置
.2,藍芽之間的通訊需要一個唯一識別UUID來匹配正確的裝置,使用UUID獲取藍芽的通訊Socket.3 ,開啟獲取資料的執行緒

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

三十

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  

 BluetoothSocket BTSocket;

 BluetoothAdapter BTAdapter;

 Button bt_start;

 TextView tv_msg;

 StringBuilder sb;

  

 @Override

 protected void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

 setContentView(R.layout.activity_main);

 bt_start = (Button) findViewById(R.id.bt_start);

 tv_msg = (TextView) findViewById(R.id.tv_msg);

 bt_start.setOnClickListener(this);

 sb = new StringBuilder();

 //拿到本地藍芽裝置

 BTAdapter = BluetoothAdapter.getDefaultAdapter();

 }

  

 /**

 * UI文字輸出

 *

 * @param msg

 */

 public void show(String msg) {

 sb.append(msg + "\n");

 runOnUiThread(new Runnable() {

 @Override

 public void run() {

 tv_msg.setText(sb.toString());

 }

 });

 }

  

 @Override

 public void onClick(View v) {

 //開啟伺服器

 ServerThread startServerThread = new ServerThread();

 startServerThread.start();

 }

  

 /**

 * 開啟伺服器

 */

 private class ServerThread extends Thread {

 public void run() {

 try {

 BluetoothServerSocket mserverSocket = BTAdapter.listenUsingRfcommWithServiceRecord("btspp",

  UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));

 show("服務端:等待連線");

  

 BTSocket = mserverSocket.accept();

 show("服務端:連線成功");

  

 readThread mreadThread = new readThread();

 mreadThread.start();

 show("服務端:啟動接受資料");

 } catch (IOException e) {

 e.printStackTrace();

 }

 }

 }

  

 /**

 * 讀取資料

 */

 private class readThread extends Thread {

 public void run() {

 byte[] buffer = new byte[1024];

 int bytes;

 InputStream mmInStream = null;

 try {

 mmInStream = BTSocket.getInputStream();

 show("服務端:獲得輸入流");

 } catch (IOException e1) {

 e1.printStackTrace();

 }

 while (true) {

 try {

  if ((bytes = mmInStream.read(buffer)) > 0) {

  byte[] buf_data = new byte[bytes];

  for (int i = 0; i < bytes; i++) {

  buf_data[i] = buffer[i];

  }

  String s = new String(buf_data);

  show("服務端:讀取資料了~~" + s);

  }

 } catch (IOException e) {

  try {

  mmInStream.close();

  } catch (IOException e1) {

  e1.printStackTrace();

  }

  break;

 }

 }

 }

 }

  

}

客戶端

實現思路:
1,檢查是否開啟藍芽
2,註冊一系列藍芽的廣播
。3,由於藍芽每經過一個階段都會發送一個廣播,根據廣播來實現對應的方法
4,藍芽配對- >藍芽連線- >傳送訊息(UUID必須相同)

1

2

3

4

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

三十

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

  

 private TextView tv_msg;

 private Button bt_search, bt_send;

 private BluetoothSocket BTSocket;

 private BluetoothAdapter BTAdapter;

 private BluetoothDevice device;

 private StringBuilder sb;

  

 @Override

 protected void onCreate(Bundle savedInstanceState) {

 super.onCreate(savedInstanceState);

 setContentView(R.layout.activity_main);

  

 bt_search = (Button) findViewById(R.id.bt_search);

 bt_send = (Button) findViewById(R.id.bt_send);

 tv_msg = (TextView) findViewById(R.id.tv_msg);

 bt_search.setOnClickListener(this);

 bt_send.setOnClickListener(this);

 sb = new StringBuilder();

  

 show("客戶端:檢查BT");

 checkBT(this);

 show("客戶端:註冊接收者");

 registerBTReceiver();

 }

  

 /**

 * UI文字輸出

 *

 * @param msg

 */

 public void show(String msg) {

 sb.append(msg + "\n");

 runOnUiThread(new Runnable() {

 @Override

 public void run() {

 tv_msg.setText(sb.toString());

 }

 });

 }

  

 @Override

 public void onClick(View v) {

 switch (v.getId()) {

 case R.id.bt_search:

 show("客戶端:開始尋找裝置");

 BTAdapter.startDiscovery();

 break;

 case R.id.bt_send:

 sendMessage();

 break;

 }

 }

  

 /**

 * 檢查藍芽

 */

 public void checkBT(Context context) {

 BTAdapter = BluetoothAdapter.getDefaultAdapter();

 if (BTAdapter != null) {

 if (!BTAdapter.isEnabled()) {

 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

 // 設定藍芽可見性,最多300秒

 intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);

 context.startActivity(intent);

 }

 } else {

 System.out.println("本地裝置驅動異常!");

 }

 }

  

 /**

 * 開啟客戶端

 */

 private class clientThread extends Thread {

 public void run() {

 try {

 //建立一個Socket連線:只需要伺服器在註冊時的UUID號

 BTSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));

 //連線

 show("客戶端:開始連線...");

 BTSocket.connect();

 show("客戶端:連線成功");

 //啟動接受資料

 show("客戶端:啟動接受資料");

 readThread mreadThread = new readThread();

 mreadThread.start();

 } catch (IOException e) {

 show("客戶端:連線服務端異常!斷開連線重新試一試");

 e.printStackTrace();

 }

 }

 }

  

 /**

 * 讀取資料

 */

 private class readThread extends Thread {

 public void run() {

 byte[] buffer = new byte[1024];

 int bytes;

 InputStream is = null;

 try {

 is = BTSocket.getInputStream();

 show("客戶端:獲得輸入流");

 } catch (IOException e1) {

 e1.printStackTrace();

 }

 while (true) {

 try {

  if ((bytes = is.read(buffer)) > 0) {

  byte[] buf_data = new byte[bytes];

  for (int i = 0; i < bytes; i++) {

  buf_data[i] = buffer[i];

  }

  String s = new String(buf_data);

  show("客戶端:讀取資料了" + s);

  }

 } catch (IOException e) {

  try {

  is.close();

  } catch (IOException e1) {

  e1.printStackTrace();

  }

  break;

 }

 }

 }

 }

  

 /**

 * 傳送資料

 */

 public void sendMessage() {

 if (BTSocket == null) {

 Toast.makeText(this, "沒有連線", Toast.LENGTH_SHORT).show();

 return;

 }

 try {

 OutputStream os = BTSocket.getOutputStream();

 os.write("我愛你[email protected]#%¥*".getBytes());

 os.flush();

 show("客戶端:傳送資訊成功");

 } catch (IOException e) {

 e.printStackTrace();

 }

 }

  

 /**

 * 註冊廣播

 */

 public void registerBTReceiver() {

 // 設定廣播資訊過濾

 IntentFilter intentFilter = new IntentFilter();

 intentFilter.addAction(BluetoothDevice.ACTION_FOUND);

 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

 intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);

 intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

 // 註冊廣播接收器,接收並處理搜尋結果

 registerReceiver(BTReceive, intentFilter);

 }

  

 /**

 * 登出廣播

 */

 public void unregisterBTReceiver() {

 unregisterReceiver(BTReceive);

 }

  

 @Override

 protected void onDestroy() {

 super.onDestroy();

 unregisterBTReceiver();

 }

  

 /**

 * 廣播接收者

 */

 private BroadcastReceiver BTReceive = new BroadcastReceiver() {

 @Override

 public void onReceive(Context context, Intent intent) {

 String action = intent.getAction();

 if (BluetoothDevice.ACTION_FOUND.equals(action)) {

 device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

 show("客戶端:找到的BT名:" + device.getName());

 // 如果查詢到的裝置符合要連線的裝置,處理

 if (device.getName().equalsIgnoreCase("xu")) {

  show("客戶端:配對xu藍芽:");

  // 搜尋藍芽裝置的過程佔用資源比較多,一旦找到需要連線的裝置後需要及時關閉搜尋

  BTAdapter.cancelDiscovery();

  // 獲取藍芽裝置的連線狀態

  int connectState = device.getBondState();

  switch (connectState) {

  // 未配對

  case BluetoothDevice.BOND_NONE:

  show("客戶端:開始配對:");

  try {

  Method createBondMethod = BluetoothDevice.class.getMethod("createBond");

  createBondMethod.invoke(device);

  } catch (Exception e) {

  e.printStackTrace();

  }

  break;

  // 已配對

  case BluetoothDevice.BOND_BONDED:

  try {

  show("客戶端:開始連線:");

  clientThread clientConnectThread = new clientThread();

  clientConnectThread.start();

  } catch (Exception e) {

  e.printStackTrace();

  }

  break;

  }

 }

 } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {

 // 獲取藍芽裝置的連線狀態

 int connectState = device.getBondState();

 // 已配對

 if (connectState == BluetoothDevice.BOND_BONDED) {

  try {

  show("客戶端:開始連線:");

  clientThread clientConnectThread = new clientThread();

  clientConnectThread.start();

  } catch (Exception e) {

  e.printStackTrace();

  }

 }

 }

 show(action);

 }

 };

}

藍芽廣播內容:

ACTION_STATE_CHANGED當你藍芽開啟或者關閉的時候傳送
ACTION_FOUND當你匹配到附近藍芽裝置時傳送
ACTION_DISCOVERY_STARTED當你開始搜尋附近藍芽裝置時傳送
ACTION_DISCOVERY_FINISHED當你結束搜尋附近藍芽裝置時傳送
ACTION_BOND_STATE_CHANGED當你藍芽裝置匹配狀態發生變化時傳送