Android蓝牙开发实例演示 图片看不了?点击切换HTTP 返回上层
在上一节《Android蓝牙(Bluetooth)连接与通讯》教程中我们已经了解如何探测并开启手机的蓝牙功能、蓝牙服务搜索和建立蓝牙连接。下面我们编写实例 BluetoothDemo。
实例 BluetoothDemo 演示了使用蓝牙功能对其他蓝牙设备进行搜寻、连接并进行数据传输的过程。该应用程序的运行效果如图 1 所示。

图 1 实例 BluetoothDemo 的运行效果
该视图整体使用 LinearLayout 布局,使用 ListView 显示聊天内容,下方的横向 LinearLayout 布局中放置了一个用于输入文本的 EditText 和一个按钮。对应的布局文件 main.xml 的内容如下:
实例 BluetoothDemo 的 AndroidManifest.xml 文件的内容如下:
实例 BluetoothDemo 的主 Activity 为 BluetoothChat,其对应的文件内容如下:
Activity BluetoothChat 的 onCreate() 方法检查当前设备是否支持蓝牙功能,并得到本地的 BluetoothAdapter 设备。
在 onStart() 中检查是否启用了蓝牙功能,若未启用,则请求启用,然后通过 setupChat() 方法对界面中的控件进行初始化、增加单击监听器等,BluetoothChat 创建了 ChatService 对象,该对象在整个应用过程中存在,并完成了蓝牙连接的建立、消息发送与接收等功能。
ChatService.java 的代码如下:
DeviceList 用于显示蓝牙设备列表,并返回蓝牙设备信息。DeviceList.java 的代码如下:
实例 BluetoothDemo 演示了使用蓝牙功能对其他蓝牙设备进行搜寻、连接并进行数据传输的过程。该应用程序的运行效果如图 1 所示。

图 1 实例 BluetoothDemo 的运行效果
该视图整体使用 LinearLayout 布局,使用 ListView 显示聊天内容,下方的横向 LinearLayout 布局中放置了一个用于输入文本的 EditText 和一个按钮。对应的布局文件 main.xml 的内容如下:
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 | <?xml version= "1.0" encoding= "utf-8" ?> <LinearLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:myapp= "http://schemas.android.com/apk/res/android.BluetoothChat" android:layout_width= "match_parent" android:layout_height= "match_parent" android:background= "@drawable/bg01" > <ListView android:id= "@+id/in" android:layout_width= "match_parent" android:layout_height= "match_parent" android:stackFromBottom= "true" android:transcriptMode= "alwaysScroll" android:layout_weight= "1" /> <LinearLayout android:layout_width= "match_parent" android:layout_height= "wrap_parent" android:orientation= "horizontal" > <EditText android:id= "@+id/edit_text_out" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:layout_weight= "1" android:layout_gravity= "bottom" /> <ListView android:id= "@+id/button_send" android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:text= "@string/send" /> </LinearLayout> </LinearLayout> |
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 | <?xml version= "1.0" encoding= "utf-8" ?> <manifest xmlns:android= "http://schemas.android.com/apk/res/android" package= "introduction.android.BluetoothChat" android:versionCode= "1" android:versionName= "1.0" > <uses-sdk android:minSdkVersion= "14" /> <uses-permission android: name = "android.permission.BLUE TOOTH_ADMIN" > <uses-permission android: name = "android.permission.BLUETOOTH" /> <application android:icon= "@drawable/app_icon" android:label= "@string/app_name" > <activity android: name = ".BluetoothChat" android:configChanges= "orientation\keyboardHidden" android:label= "@string/app_name" > <intent-filter> < action android: name = "android.in tent.action.MAIN" /> <category android: name = "android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android: name = ".DeviceList" android:configChanges= "orientation\keyboardHidden" android:label= "@string/select_device" android:theme= "@android:style/Theme.Dialog" /> </application> </manifest> |
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 | package introduction.android.mydbdemo; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android. view .KeyEvent; import android. view .Menu; import android. view .MenuInflater; import android. view .MenuItem; import android. view . View ; import android. view . View .OnClickListener; import android. view .Window; import android. view .inputmethod.EditorInfo; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; public class BluetoothChat extends Activity { 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; public static final String DEVICE_NAME = "device_name" ; public static final String TOAST = "toast" ; private static final int REQUEST_C0NNECT_DEVICE = 1; private static final int REQUEST_ENABLE_BT = 2; private TextView mTitle; private ListView mConversationView; private EditText mOutEditText; private Button mSendButton; private String mConnectedDeviceName = null ; private ArrayAdapter<String> mConversationArrayAdapter; private StringBuffer mOutStringBuffer; private BluetoothAdapter mBluetoothAdapter = null ; private ChatService mChatService = null ; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //设置窗口布局为自定义标题 requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); setContentView(R.layout.main); //设置窗口标题为布局文件 getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); mTitle = (TextView) findViewById(R.id.title_left_text); mTitle.setText(R.string.app_name); mTitle = (TextView) findViewById(R.id.title_right_text); // 得到本地蓝牙适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); //若当前设备不支持蓝牙功能 if (mBluetoothAdapter == null ) { Toast.makeText(this, "蓝牙不可用" , Toast.LENGTH_LONG).show(); finish(); return ; } } @Override public void onStart() { super.onStart(); if (!mBluetoothAdapter.isEnabled()) { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else { if (mChatService == null ) setupChat(); } } @Override public synchronized void onResume() { super.onResume(); if (mChatService != null ) { if (mChatService.getState() == ChatService.STATE_NONE) { mChatService.start(); } } } private void setupChat() { mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message); mConversationView = (ListView) findViewById(R.id. in ); mConversationView.setAdapter(mConversationArrayAdapter); mOutEditText = (EditText) findViewById(R.id.edit_text_out); mOutEditText.setOnEditorActionListener(mWriteListener); mSendButton = (Button) findViewById(R.id.button_send); mSendButton.setOnClickListener(new OnClickListener() { public void onClick( View v) { TextView view = (TextView) findViewById(R.id.edit_text_out); String message = view .getText().toString(); sendMessage(message); } }); mChatService = new ChatService(this, mHandler); mOutStringBuffer = new StringBuffer( "" ); } @Override public synchronized void onPause() { super.onPause(); } @Override public void onStop() { super.onStop(); } @Override public void onDestroy() { super.onDestroy(); if (mChatService != null ) mChatService.stop(); } private void ensureDiscoverable() { if (mBluetoothAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivity(discoverableIntent); } } private void sendMessage(String message) { if (mChatService.getState() != ChatService.STATE_CONNECTED) { Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show(); return ; } if (message.length() > 0) { byte[] send = message.getBytes(); mChatService.write(send); mOutStringBuffer.setLength(0); mOutEditText.setText(mOutStringBuffer); } } private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() { public boolean onEditorAction(TextView view , int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) { String message = view .getText().toString(); sendMessage(message); } return true ; } }; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_STATE_CHANGE: switch (msg.argl) { case ChatService.STATE_CONNECTED: mTitle.setText(R.string.title_connected_to); mTitle.append(mConnectedDeviceName); mConversationArrayAdapter.clear(); break; case ChatService.STATE_CONNECTING: mTitle.setText(R.string.title_connecting); break; case ChatService.STATE_LISTEN: case ChatService.STATE_NONE: mTitle.setText(R.string.title_not_connected); break; } break; case MESSAGE_WRITE: byte[] writeBuf = (byte[]) msg.obj; String writeMessage = new String(writeBuf); mConversationArrayAdapter. add ( "我: " + writeMessage); break; case MESSAGE_READ: byte[] readBuf = (byte[]) msg.obj; String readMessage = new String(readBuf, 0, msg.argl); mConversationArrayAdapter. add (mConnectedDeviceName + ":" + readMessage); break; case MESSAGE_DEVICE_NAME: mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); Toast.makeText(getApplicationContext(), "链接到" + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); break; case MESSAGE_TOAST: Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), Toast.LENGTH_SHORT).show(); break; } } }; public void onActivityResult( int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CONNECT_DEVICE: if (resultCode == Activity.RESULT_OK) { String address = data.getExtras().getString(DeviceList.EXTRA_DEVICE_ADDRESS); BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); mChatService. connect (device); } break; case REQUEST_ENABLE_BT: if (resultCode == Activity.RESULT_OK) { setupChat(); } else { Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show(); finish(); } } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.option_menu, menu); return true ; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.scan: Intent serverIntent = new Intent(this, DeviceList.class); startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); return true ; case R.id.discoverable: ensureDiscoverable(); return true ; case R.id.back: finish(); System.exit(0); return true ; } return false ; } } |
在 onStart() 中检查是否启用了蓝牙功能,若未启用,则请求启用,然后通过 setupChat() 方法对界面中的控件进行初始化、增加单击监听器等,BluetoothChat 创建了 ChatService 对象,该对象在整个应用过程中存在,并完成了蓝牙连接的建立、消息发送与接收等功能。
ChatService.java 的代码如下:
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 | package introduction.android.BluetoothChat; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; 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 introduction.android.mydbdemo.BluetoothChat; public class ChatService { private static final String NAME = "BluetoothChat" ; // UUID -->通用唯一识别码,能唯一辨识资讯 private static final UUID MY_UUID = UUID .fromString( "fa87c0d0-afac-llde-8a39-0800200c9a66" ); private final BluetoothAdapter mAdapter; private final Handler mHandler; private AcceptThread mAcceptThread; private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private int mState; public static final int STATE_NONE = 0; public static final int STATE_LISTEN = 1; public static final int STATE_CONNECTING = 2; public static final int STATE_CONNECTED = 3; public ChatService(Context context, Handler handler) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mState = STATE_NONE; mHandler = handler; } private synchronized void setState( int state) { mState = state; mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } public synchronized int getState() { return mState; } public synchronized void start() { if (mConnectThread != null ) { mConnectThread.cancel(); mConnectThread = null ; } if (mConnectedThread != null ) { mConnectedThread.cancel(); mConnectedThread = null ; } if (mAcceptThread == null ) { mAcceptThread = new AcceptThread(); mAcceptThread.start(); } setState(STATE_LISTEN); } //取消CONNECTING和CONNECTED状态下的相关线程,然后运行新的mConnectThread线程 public synchronized void connect (BluetoothDevice device) { if (mState == STATE_CONNECTING) { if (mConnectThread != null ) { mConnectThread.cancel(); mConnectThread = null ; } } if (mConnectedThread != null ) { mConnectedThread.cancel(); mConnectedThread = null ; } mConnectThread = new ConnectThread(device); mConnectThread.start(); setState(STATE_CONNECTING); } //开启一个ConnectedThread来管理对应的当前连接。之前先取消任意现存的mConnectThread、 //mConnectedThread 、mAcceptThread 线程,然后开启新 mConnectedThread ,传入当前刚刚接受的 //socket连接 //最后通过Handler来通知UI连接 public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { if (mConnectThread != null ) { mConnectThread.cancel(); mConnectThread = null ; } if (mConnectedThread != null ) { mConnectedThread.cancel(); mConnectedThread = null ; } if (mAcceptThread != null ) { mAcceptThread.cancel(); mAcceptThread = null ; } mConnectedThread = new ConnectedThread(socket); mConnectedThread.start(); 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); } //停止所有相关线程,设当前状态为NONE public synchronized void stop() { if (mConnectThread != null ) { mConnectThread.cancel(); mConnectThread = null ; } if (mConnectedThread != null ) { mConnectedThread.cancel(); mConnectedThread = null ; } if (mAcceptThread != null ) { mAcceptThread.cancel(); setState(STATE_NONE); } } //在 STATE_CONNECTED 状态下,调用 mConnectedThread 里的 write 方法,写入 byte public void write(byte[] out ) { ConnectedThread r; synchronized (this) { if (mState != STATE_CONNECTED) return ; r = mConnectedThread; } r.write( out ); } //连接失败的时候处理,通知ui ,并设为STATE一LISTEN状态 private void connectionFailed() { setState(STATE_LISTEN); Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "链接不到设备" ); msg.setData(bundle); mHandler.sendMessage(msg); } //当连接失去的时候,设为STATE_LISTEN状态并通知UI private void connectionLost() { setState(STATE_LISTEN); Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(BluetoothChat.TOAST, "设备链接中断" ); msg.setData(bundle); mHandler.sendMessage(msg); } //创建监听线程,准备接受新连接。使用阻塞方式调用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() { setName( "AcceptThread" ); BluetoothSocket socket = null ; while (mState != STATE_CONNECTED) { try { socket = mmServerSocket.accept(); } catch (IOException e) { break; } if (socket != null ) { synchronized (ChatService.this) { switch (mState) { case STATE_LISTEN: case STATE_CONNECTING: connected(socket, socket.getRemoteDevice()); break; case STATE_NONE: case STATE_CONNECTED: try { socket. close (); } catch (IOException e) { } break; } } } } } public void cancel() { try { mmServerSocket. close (); } catch (IOException e) { } } } // 连接进程,专门用来对外发出连接对方蓝牙的请求并进行处理 // 构造函数里,通过BluetoothDevice.createRfcommSocketToServiceRecord(), // 从待连接的device产生BluetoothSocket.然后在run方法中 connect , // 成功后调用BluetoothChatSevice的connected() 方法。定义cancel()再关闭线程时能关闭相关Socket private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { mmDevice = device; BluetoothSocket tmp = null ; try { tmp = device.createRfcommSocketToServiceRecord(MY_UUID); } catch (IOException e) { } mmSocket = tmp; } public void run() { setName( "ConnectThread" ); mAdapter.cancelDiscovery(); try { mmSocket. connect (); } catch (IOException e) { connectionFailed(); try { mmSocket. close (); } catch (IOException e2) { } ChatService.this.start(); return ; synchronized (ChatService.this) { mConnectThread = null ; } connected(mmSocket, mmDevice); } } public void cancel() { try { mmSocket. close (); } catch (IOException e) { } } } // 双方蓝牙连接后一直运行的线程。构造函数中设置输入输出流 // Run方法中使用阻塞模式的Inputstream. read ()循环读取输入流, // 然后post到UI线程中更新聊天信息。也提供了write()将聊天信息写入输出流传输至对方,传输成功后回写入UI线程,最后cancle()关闭连接的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 ; try { tmpIn = socket.getInputStream(); tmpOut = socket.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(BluetoothChat.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); } catch (IOException e) { connectionLost(); break; } } } public void write(byte[] buffer) { try { mmOutStream.write(buffer); mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); } catch (IOException e) { } } } public void cancel() { try { mmSocket. close (); } catch (IOException e) { } } } |
DeviceList 用于显示蓝牙设备列表,并返回蓝牙设备信息。DeviceList.java 的代码如下:
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 | package introduction.android.BluetoothChat; import java.util. Set ; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android. view . View ; import android. view .Window; import android. view . View .OnClickListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; import introduction.android.mydbdemo.R; public class DeviceList extends Activity { public static String EXTRA_DEVICE_ADDRESS = "device_address" ; private BluetoothAdapter mBtAdapter; private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.device_list); setResult(Activity.RESULT_CANCELED); Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick( View v) { doDiscovery(); v.setVisibility( View .GONE); } }); mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener); ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener); IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); mBtAdapter = BluetoothAdapter.getDefaultAdapter(); Set <BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices(); if (pairedDevices. size () > 0) { findViewById(R.id.title_paired_devices).setVisibility( View .VISIBLE); for (BluetoothDevice device : pairedDevices) { mPairedDevicesArrayAdapter. add (device.getName() + "\n" + device.getAddress()); } } else { String noDevices = getResources().getText(R.string.none_paired) .toString(); mPairedDevicesArrayAdapter. add (noDevices); } } @Override protected void onDestroy() { super.onDestroy(); if (mBtAdapter != null ) { mBtAdapter.cancelDiscovery(); } this.unregisterReceiver(mReceiver); } private void doDiscovery() { setProgressBarIndeterminateVisibility( true ); setTitle(R.string.scanning); findViewById(R.id.title_new_devices).setVisibility( View .VISIBLE); if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); } mBtAdapter.startDiscovery(); } private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) { mBtAdapter.cancelDiscovery(); String info = ((TextView) v).getText().toString(); String address = info. substring (info.length() - 17); Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address); setResult(Activity.RESULT_OK, intent); finish(); } }; 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); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter. add (device.getName() + "\n" + device.getAddress()); } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals( action )) { setProgressBarIndeterminateVisibility( false ); setTitle(R.string.select_device); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = getResources().getText( R.string.none_found).toString(); mNewDevicesArrayAdapter. add (noDevices); } } } }; } |