development
修订版 | 6314c20eebbea8eadf6bec36624dbc366da9b2dc (tree) |
---|---|
时间 | 2011-01-15 06:11:34 |
作者 | Jaikumar Ganesh <jaikumar@goog...> |
Commiter | Jaikumar Ganesh |
Do Not Merge: Modify Bluetooth Chat app for new insecure rfcomm API.
Also fix some bugs.
Bug: 3352266
Change-Id: Ie64cb243159b1f6eea5f268f02a1dd58970d1e22
@@ -14,9 +14,12 @@ | ||
14 | 14 | limitations under the License. |
15 | 15 | --> |
16 | 16 | <menu xmlns:android="http://schemas.android.com/apk/res/android"> |
17 | - <item android:id="@+id/scan" | |
17 | + <item android:id="@+id/secure_connect_scan" | |
18 | 18 | android:icon="@android:drawable/ic_menu_search" |
19 | - android:title="@string/connect" /> | |
19 | + android:title="@string/secure_connect" /> | |
20 | + <item android:id="@+id/insecure_connect_scan" | |
21 | + android:icon="@android:drawable/ic_menu_search" | |
22 | + android:title="@string/insecure_connect" /> | |
20 | 23 | <item android:id="@+id/discoverable" |
21 | 24 | android:icon="@android:drawable/ic_menu_mylocation" |
22 | 25 | android:title="@string/discoverable" /> |
@@ -35,6 +35,7 @@ | ||
35 | 35 | <string name="button_scan">Scan for devices</string> |
36 | 36 | |
37 | 37 | <!-- Options Menu --> |
38 | - <string name="connect">Connect a device</string> | |
38 | + <string name="secure_connect">Connect a device - Secure</string> | |
39 | + <string name="insecure_connect">Connect a device - Insecure</string> | |
39 | 40 | <string name="discoverable">Make discoverable</string> |
40 | 41 | </resources> |
@@ -59,8 +59,9 @@ public class BluetoothChat extends Activity { | ||
59 | 59 | public static final String TOAST = "toast"; |
60 | 60 | |
61 | 61 | // Intent request codes |
62 | - private static final int REQUEST_CONNECT_DEVICE = 1; | |
63 | - private static final int REQUEST_ENABLE_BT = 2; | |
62 | + private static final int REQUEST_CONNECT_DEVICE_SECURE = 1; | |
63 | + private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2; | |
64 | + private static final int REQUEST_ENABLE_BT = 3; | |
64 | 65 | |
65 | 66 | // Layout Views |
66 | 67 | private TextView mTitle; |
@@ -287,16 +288,16 @@ public class BluetoothChat extends Activity { | ||
287 | 288 | public void onActivityResult(int requestCode, int resultCode, Intent data) { |
288 | 289 | if(D) Log.d(TAG, "onActivityResult " + resultCode); |
289 | 290 | switch (requestCode) { |
290 | - case REQUEST_CONNECT_DEVICE: | |
291 | + case REQUEST_CONNECT_DEVICE_SECURE: | |
291 | 292 | // When DeviceListActivity returns with a device to connect |
292 | 293 | if (resultCode == Activity.RESULT_OK) { |
293 | - // Get the device MAC address | |
294 | - String address = data.getExtras() | |
295 | - .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); | |
296 | - // Get the BLuetoothDevice object | |
297 | - BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); | |
298 | - // Attempt to connect to the device | |
299 | - mChatService.connect(device); | |
294 | + connectDevice(data, true); | |
295 | + } | |
296 | + break; | |
297 | + case REQUEST_CONNECT_DEVICE_INSECURE: | |
298 | + // When DeviceListActivity returns with a device to connect | |
299 | + if (resultCode == Activity.RESULT_OK) { | |
300 | + connectDevice(data, false); | |
300 | 301 | } |
301 | 302 | break; |
302 | 303 | case REQUEST_ENABLE_BT: |
@@ -313,6 +314,16 @@ public class BluetoothChat extends Activity { | ||
313 | 314 | } |
314 | 315 | } |
315 | 316 | |
317 | + private void connectDevice(Intent data, boolean secure) { | |
318 | + // Get the device MAC address | |
319 | + String address = data.getExtras() | |
320 | + .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS); | |
321 | + // Get the BLuetoothDevice object | |
322 | + BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); | |
323 | + // Attempt to connect to the device | |
324 | + mChatService.connect(device, secure); | |
325 | + } | |
326 | + | |
316 | 327 | @Override |
317 | 328 | public boolean onCreateOptionsMenu(Menu menu) { |
318 | 329 | MenuInflater inflater = getMenuInflater(); |
@@ -322,11 +333,17 @@ public class BluetoothChat extends Activity { | ||
322 | 333 | |
323 | 334 | @Override |
324 | 335 | public boolean onOptionsItemSelected(MenuItem item) { |
336 | + Intent serverIntent = null; | |
325 | 337 | switch (item.getItemId()) { |
326 | - case R.id.scan: | |
338 | + case R.id.secure_connect_scan: | |
339 | + // Launch the DeviceListActivity to see devices and do scan | |
340 | + serverIntent = new Intent(this, DeviceListActivity.class); | |
341 | + startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE); | |
342 | + return true; | |
343 | + case R.id.insecure_connect_scan: | |
327 | 344 | // Launch the DeviceListActivity to see devices and do scan |
328 | - Intent serverIntent = new Intent(this, DeviceListActivity.class); | |
329 | - startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); | |
345 | + serverIntent = new Intent(this, DeviceListActivity.class); | |
346 | + startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE); | |
330 | 347 | return true; |
331 | 348 | case R.id.discoverable: |
332 | 349 | // Ensure this device is discoverable by others |
@@ -336,4 +353,4 @@ public class BluetoothChat extends Activity { | ||
336 | 353 | return false; |
337 | 354 | } |
338 | 355 | |
339 | -} | |
\ No newline at end of file | ||
356 | +} |
@@ -43,15 +43,20 @@ public class BluetoothChatService { | ||
43 | 43 | private static final boolean D = true; |
44 | 44 | |
45 | 45 | // Name for the SDP record when creating server socket |
46 | - private static final String NAME = "BluetoothChat"; | |
46 | + private static final String NAME_SECURE = "BluetoothChatSecure"; | |
47 | + private static final String NAME_INSECURE = "BluetoothChatInsecure"; | |
47 | 48 | |
48 | 49 | // Unique UUID for this application |
49 | - private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); | |
50 | + private static final UUID MY_UUID_SECURE = | |
51 | + UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66"); | |
52 | + private static final UUID MY_UUID_INSECURE = | |
53 | + UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66"); | |
50 | 54 | |
51 | 55 | // Member fields |
52 | 56 | private final BluetoothAdapter mAdapter; |
53 | 57 | private final Handler mHandler; |
54 | - private AcceptThread mAcceptThread; | |
58 | + private AcceptThread mSecureAcceptThread; | |
59 | + private AcceptThread mInsecureAcceptThread; | |
55 | 60 | private ConnectThread mConnectThread; |
56 | 61 | private ConnectedThread mConnectedThread; |
57 | 62 | private int mState; |
@@ -103,19 +108,25 @@ public class BluetoothChatService { | ||
103 | 108 | // Cancel any thread currently running a connection |
104 | 109 | if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} |
105 | 110 | |
111 | + setState(STATE_LISTEN); | |
112 | + | |
106 | 113 | // Start the thread to listen on a BluetoothServerSocket |
107 | - if (mAcceptThread == null) { | |
108 | - mAcceptThread = new AcceptThread(); | |
109 | - mAcceptThread.start(); | |
114 | + if (mSecureAcceptThread == null) { | |
115 | + mSecureAcceptThread = new AcceptThread(true); | |
116 | + mSecureAcceptThread.start(); | |
117 | + } | |
118 | + if (mInsecureAcceptThread == null) { | |
119 | + mInsecureAcceptThread = new AcceptThread(false); | |
120 | + mInsecureAcceptThread.start(); | |
110 | 121 | } |
111 | - setState(STATE_LISTEN); | |
112 | 122 | } |
113 | 123 | |
114 | 124 | /** |
115 | 125 | * Start the ConnectThread to initiate a connection to a remote device. |
116 | 126 | * @param device The BluetoothDevice to connect |
127 | + * @param secure Socket Security type - Secure (true) , Insecure (false) | |
117 | 128 | */ |
118 | - public synchronized void connect(BluetoothDevice device) { | |
129 | + public synchronized void connect(BluetoothDevice device, boolean secure) { | |
119 | 130 | if (D) Log.d(TAG, "connect to: " + device); |
120 | 131 | |
121 | 132 | // Cancel any thread attempting to make a connection |
@@ -127,7 +138,7 @@ public class BluetoothChatService { | ||
127 | 138 | if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} |
128 | 139 | |
129 | 140 | // Start the thread to connect with the given device |
130 | - mConnectThread = new ConnectThread(device); | |
141 | + mConnectThread = new ConnectThread(device, secure); | |
131 | 142 | mConnectThread.start(); |
132 | 143 | setState(STATE_CONNECTING); |
133 | 144 | } |
@@ -137,8 +148,9 @@ public class BluetoothChatService { | ||
137 | 148 | * @param socket The BluetoothSocket on which the connection was made |
138 | 149 | * @param device The BluetoothDevice that has been connected |
139 | 150 | */ |
140 | - public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { | |
141 | - if (D) Log.d(TAG, "connected"); | |
151 | + public synchronized void connected(BluetoothSocket socket, BluetoothDevice | |
152 | + device, final String socketType) { | |
153 | + if (D) Log.d(TAG, "connected, Socket Type:" + socketType); | |
142 | 154 | |
143 | 155 | // Cancel the thread that completed the connection |
144 | 156 | if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} |
@@ -147,10 +159,17 @@ public class BluetoothChatService { | ||
147 | 159 | if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} |
148 | 160 | |
149 | 161 | // Cancel the accept thread because we only want to connect to one device |
150 | - if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} | |
162 | + if (mSecureAcceptThread != null) { | |
163 | + mSecureAcceptThread.cancel(); | |
164 | + mSecureAcceptThread = null; | |
165 | + } | |
166 | + if (mInsecureAcceptThread != null) { | |
167 | + mInsecureAcceptThread.cancel(); | |
168 | + mInsecureAcceptThread = null; | |
169 | + } | |
151 | 170 | |
152 | 171 | // Start the thread to manage the connection and perform transmissions |
153 | - mConnectedThread = new ConnectedThread(socket); | |
172 | + mConnectedThread = new ConnectedThread(socket, socketType); | |
154 | 173 | mConnectedThread.start(); |
155 | 174 | |
156 | 175 | // Send the name of the connected device back to the UI Activity |
@@ -168,9 +187,26 @@ public class BluetoothChatService { | ||
168 | 187 | */ |
169 | 188 | public synchronized void stop() { |
170 | 189 | if (D) Log.d(TAG, "stop"); |
171 | - if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} | |
172 | - if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} | |
173 | - if (mAcceptThread != null) {mAcceptThread.cancel(); mAcceptThread = null;} | |
190 | + | |
191 | + if (mConnectThread != null) { | |
192 | + mConnectThread.cancel(); | |
193 | + mConnectThread = null; | |
194 | + } | |
195 | + | |
196 | + if (mConnectedThread != null) { | |
197 | + mConnectedThread.cancel(); | |
198 | + mConnectedThread = null; | |
199 | + } | |
200 | + | |
201 | + if (mSecureAcceptThread != null) { | |
202 | + mSecureAcceptThread.cancel(); | |
203 | + mSecureAcceptThread = null; | |
204 | + } | |
205 | + | |
206 | + if (mInsecureAcceptThread != null) { | |
207 | + mInsecureAcceptThread.cancel(); | |
208 | + mInsecureAcceptThread = null; | |
209 | + } | |
174 | 210 | setState(STATE_NONE); |
175 | 211 | } |
176 | 212 |
@@ -195,28 +231,30 @@ public class BluetoothChatService { | ||
195 | 231 | * Indicate that the connection attempt failed and notify the UI Activity. |
196 | 232 | */ |
197 | 233 | private void connectionFailed() { |
198 | - setState(STATE_LISTEN); | |
199 | - | |
200 | 234 | // Send a failure message back to the Activity |
201 | 235 | Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); |
202 | 236 | Bundle bundle = new Bundle(); |
203 | 237 | bundle.putString(BluetoothChat.TOAST, "Unable to connect device"); |
204 | 238 | msg.setData(bundle); |
205 | 239 | mHandler.sendMessage(msg); |
240 | + | |
241 | + // Start the service over to restart listening mode | |
242 | + BluetoothChatService.this.start(); | |
206 | 243 | } |
207 | 244 | |
208 | 245 | /** |
209 | 246 | * Indicate that the connection was lost and notify the UI Activity. |
210 | 247 | */ |
211 | 248 | private void connectionLost() { |
212 | - setState(STATE_LISTEN); | |
213 | - | |
214 | 249 | // Send a failure message back to the Activity |
215 | 250 | Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); |
216 | 251 | Bundle bundle = new Bundle(); |
217 | 252 | bundle.putString(BluetoothChat.TOAST, "Device connection was lost"); |
218 | 253 | msg.setData(bundle); |
219 | 254 | mHandler.sendMessage(msg); |
255 | + | |
256 | + // Start the service over to restart listening mode | |
257 | + BluetoothChatService.this.start(); | |
220 | 258 | } |
221 | 259 | |
222 | 260 | /** |
@@ -227,22 +265,32 @@ public class BluetoothChatService { | ||
227 | 265 | private class AcceptThread extends Thread { |
228 | 266 | // The local server socket |
229 | 267 | private final BluetoothServerSocket mmServerSocket; |
268 | + private String mSocketType; | |
230 | 269 | |
231 | - public AcceptThread() { | |
270 | + public AcceptThread(boolean secure) { | |
232 | 271 | BluetoothServerSocket tmp = null; |
272 | + mSocketType = secure ? "Secure":"Insecure"; | |
233 | 273 | |
234 | 274 | // Create a new listening server socket |
235 | 275 | try { |
236 | - tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); | |
276 | + if (secure) { | |
277 | + tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, | |
278 | + MY_UUID_SECURE); | |
279 | + } else { | |
280 | + tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord( | |
281 | + NAME_INSECURE, MY_UUID_INSECURE); | |
282 | + } | |
237 | 283 | } catch (IOException e) { |
238 | - Log.e(TAG, "listen() failed", e); | |
284 | + Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e); | |
239 | 285 | } |
240 | 286 | mmServerSocket = tmp; |
241 | 287 | } |
242 | 288 | |
243 | 289 | public void run() { |
244 | - if (D) Log.d(TAG, "BEGIN mAcceptThread" + this); | |
245 | - setName("AcceptThread"); | |
290 | + if (D) Log.d(TAG, "Socket Type: " + mSocketType + | |
291 | + "BEGIN mAcceptThread" + this); | |
292 | + setName("AcceptThread" + mSocketType); | |
293 | + | |
246 | 294 | BluetoothSocket socket = null; |
247 | 295 | |
248 | 296 | // Listen to the server socket if we're not connected |
@@ -252,7 +300,7 @@ public class BluetoothChatService { | ||
252 | 300 | // successful connection or an exception |
253 | 301 | socket = mmServerSocket.accept(); |
254 | 302 | } catch (IOException e) { |
255 | - Log.e(TAG, "accept() failed", e); | |
303 | + Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e); | |
256 | 304 | break; |
257 | 305 | } |
258 | 306 |
@@ -263,7 +311,8 @@ public class BluetoothChatService { | ||
263 | 311 | case STATE_LISTEN: |
264 | 312 | case STATE_CONNECTING: |
265 | 313 | // Situation normal. Start the connected thread. |
266 | - connected(socket, socket.getRemoteDevice()); | |
314 | + connected(socket, socket.getRemoteDevice(), | |
315 | + mSocketType); | |
267 | 316 | break; |
268 | 317 | case STATE_NONE: |
269 | 318 | case STATE_CONNECTED: |
@@ -278,15 +327,16 @@ public class BluetoothChatService { | ||
278 | 327 | } |
279 | 328 | } |
280 | 329 | } |
281 | - if (D) Log.i(TAG, "END mAcceptThread"); | |
330 | + if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType); | |
331 | + | |
282 | 332 | } |
283 | 333 | |
284 | 334 | public void cancel() { |
285 | - if (D) Log.d(TAG, "cancel " + this); | |
335 | + if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this); | |
286 | 336 | try { |
287 | 337 | mmServerSocket.close(); |
288 | 338 | } catch (IOException e) { |
289 | - Log.e(TAG, "close() of server failed", e); | |
339 | + Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e); | |
290 | 340 | } |
291 | 341 | } |
292 | 342 | } |
@@ -300,24 +350,32 @@ public class BluetoothChatService { | ||
300 | 350 | private class ConnectThread extends Thread { |
301 | 351 | private final BluetoothSocket mmSocket; |
302 | 352 | private final BluetoothDevice mmDevice; |
353 | + private String mSocketType; | |
303 | 354 | |
304 | - public ConnectThread(BluetoothDevice device) { | |
355 | + public ConnectThread(BluetoothDevice device, boolean secure) { | |
305 | 356 | mmDevice = device; |
306 | 357 | BluetoothSocket tmp = null; |
358 | + mSocketType = secure ? "Secure" : "Insecure"; | |
307 | 359 | |
308 | 360 | // Get a BluetoothSocket for a connection with the |
309 | 361 | // given BluetoothDevice |
310 | 362 | try { |
311 | - tmp = device.createRfcommSocketToServiceRecord(MY_UUID); | |
363 | + if (secure) { | |
364 | + tmp = device.createRfcommSocketToServiceRecord( | |
365 | + MY_UUID_SECURE); | |
366 | + } else { | |
367 | + tmp = device.createInsecureRfcommSocketToServiceRecord( | |
368 | + MY_UUID_INSECURE); | |
369 | + } | |
312 | 370 | } catch (IOException e) { |
313 | - Log.e(TAG, "create() failed", e); | |
371 | + Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e); | |
314 | 372 | } |
315 | 373 | mmSocket = tmp; |
316 | 374 | } |
317 | 375 | |
318 | 376 | public void run() { |
319 | - Log.i(TAG, "BEGIN mConnectThread"); | |
320 | - setName("ConnectThread"); | |
377 | + Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType); | |
378 | + setName("ConnectThread" + mSocketType); | |
321 | 379 | |
322 | 380 | // Always cancel discovery because it will slow down a connection |
323 | 381 | mAdapter.cancelDiscovery(); |
@@ -328,15 +386,14 @@ public class BluetoothChatService { | ||
328 | 386 | // successful connection or an exception |
329 | 387 | mmSocket.connect(); |
330 | 388 | } catch (IOException e) { |
331 | - connectionFailed(); | |
332 | 389 | // Close the socket |
333 | 390 | try { |
334 | 391 | mmSocket.close(); |
335 | 392 | } catch (IOException e2) { |
336 | - Log.e(TAG, "unable to close() socket during connection failure", e2); | |
393 | + Log.e(TAG, "unable to close() " + mSocketType + | |
394 | + " socket during connection failure", e2); | |
337 | 395 | } |
338 | - // Start the service over to restart listening mode | |
339 | - BluetoothChatService.this.start(); | |
396 | + connectionFailed(); | |
340 | 397 | return; |
341 | 398 | } |
342 | 399 |
@@ -346,14 +403,14 @@ public class BluetoothChatService { | ||
346 | 403 | } |
347 | 404 | |
348 | 405 | // Start the connected thread |
349 | - connected(mmSocket, mmDevice); | |
406 | + connected(mmSocket, mmDevice, mSocketType); | |
350 | 407 | } |
351 | 408 | |
352 | 409 | public void cancel() { |
353 | 410 | try { |
354 | 411 | mmSocket.close(); |
355 | 412 | } catch (IOException e) { |
356 | - Log.e(TAG, "close() of connect socket failed", e); | |
413 | + Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e); | |
357 | 414 | } |
358 | 415 | } |
359 | 416 | } |
@@ -367,8 +424,8 @@ public class BluetoothChatService { | ||
367 | 424 | private final InputStream mmInStream; |
368 | 425 | private final OutputStream mmOutStream; |
369 | 426 | |
370 | - public ConnectedThread(BluetoothSocket socket) { | |
371 | - Log.d(TAG, "create ConnectedThread"); | |
427 | + public ConnectedThread(BluetoothSocket socket, String socketType) { | |
428 | + Log.d(TAG, "create ConnectedThread: " + socketType); | |
372 | 429 | mmSocket = socket; |
373 | 430 | InputStream tmpIn = null; |
374 | 431 | OutputStream tmpOut = null; |