由于近期正在开发一个通过蓝牙进行数据传递的模块,在参考了有关资料,并详细阅读了Android的官方文档后,总结了Android中蓝牙模块的使用。

1. 使用蓝牙的响应权限

  1. <uses-permissionandroid:name="android.permission.BLUETOOTH"/>
  2. <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>


2. 配置本机蓝牙模块

在这里首先要了解对蓝牙操作一个核心类BluetoothAdapter

  1. BluetoothAdapteradapter=BluetoothAdapter.getDefaultAdapter();
  2. //直接打开系统的蓝牙设置面板
  3. Intentintent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
  4. startActivityForResult(intent,0x1);
  5. //直接打开蓝牙
  6. adapter.enable();
  7. //关闭蓝牙
  8. adapter.disable();
  9. //打开本机的蓝牙发现功能(默认打开120秒,可以将时间最多延长至300秒)
  10. IntentdiscoveryIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
  11. discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);//设置持续时间(最多300秒)

3.搜索蓝牙设备

使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备

startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。

请求Discovery后,系统开始搜索蓝牙设备,在这个过程中,系统会发送以下三个广播:

ACTION_DISCOVERY_START:开始搜索

ACTION_DISCOVERY_FINISHED:搜索结束

ACTION_FOUND:找到设备,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,分别包含BluetooDevice和BluetoothClass。

我们可以自己注册相应的BroadcastReceiver来接收响应的广播,以便实现某些功能

  1. //创建一个接收ACTION_FOUND广播的BroadcastReceiver
  2. privatefinalBroadcastReceivermReceiver=newBroadcastReceiver(){
  3. publicvoidonReceive(Contextcontext,Intentintent){
  4. Stringaction=intent.getAction();
  5. //发现设备
  6. if(BluetoothDevice.ACTION_FOUND.equals(action)){
  7. //从Intent中获取设备对象
  8. BluetoothDevicedevice=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  9. //将设备名称和地址放入arrayadapter,以便在ListView中显示
  10. mArrayAdapter.add(device.getName()+"\n"+device.getAddress());
  11. }
  12. }
  13. };
  14. //注册BroadcastReceiver
  15. IntentFilterfilter=newIntentFilter(BluetoothDevice.ACTION_FOUND);
  16. registerReceiver(mReceiver,filter);//不要忘了之后解除绑定

4. 蓝牙Socket通信

如果打算建立两个蓝牙设备之间的连接,则必须实现服务器端与客户端的机制。当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。

服务器设备与客户端设备获取BluetoothSocket的途径是不同的。服务器设备是通过accepted一个incoming connection来获取的,而客户端设备则是通过打开一个到服务器的RFCOMM channel来获取的。

服务器端的实现

通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务器端之间的配对)

调用BluetoothServerSocket的accept()方法监听连接请求,如果收到请求,则返回一个BluetoothSocket实例(此方法为block方法,应置于新线程中)

如果不想在accept其他的连接,则调用BluetoothServerSocket的close()方法释放资源(调用该方法后,之前获得的BluetoothSocket实例并没有close。但由于RFCOMM一个时刻只允许在一条channel中有一个连接,则一般在accept一个连接后,便close掉BluetoothServerSocket

  1. privateclassAcceptThreadextendsThread{
  2. privatefinalBluetoothServerSocketmmServerSocket;
  3. publicAcceptThread(){
  4. //UseatemporaryobjectthatislaterassignedtommServerSocket,
  5. //becausemmServerSocketisfinal
  6. BluetoothServerSockettmp=null;
  7. try{
  8. //MY_UUIDistheapp'sUUIDstring,alsousedbytheclientcode
  9. tmp=mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);
  10. }catch(IOExceptione){}
  11. mmServerSocket=tmp;
  12. }
  13. publicvoidrun(){
  14. BluetoothSocketsocket=null;
  15. //Keeplisteninguntilexceptionoccursorasocketisreturned
  16. while(true){
  17. try{
  18. socket=mmServerSocket.accept();
  19. }catch(IOExceptione){
  20. break;
  21. }
  22. //Ifaconnectionwasaccepted
  23. if(socket!=null){
  24. //Doworktomanagetheconnection(inaseparatethread)
  25. manageConnectedSocket(socket);
  26. mmServerSocket.close();
  27. break;
  28. }
  29. }
  30. }
  31. /**Willcancelthelisteningsocket,andcausethethreadtofinish*/
  32. publicvoidcancel(){
  33. try{
  34. mmServerSocket.close();
  35. }catch(IOExceptione){}
  36. }
  37. }


客户端的实现

通过搜索得到服务器端的BluetoothService

调用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法获取BluetoothSocket(该UUID应该同于服务器端的UUID)

调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务器端的UUID匹配,并且连接被服务器端accept,则connect()方法返回

注意:在调用connect()方法之前,应当确定当前没有搜索设备,否则连接会变得非常慢并且容易失败

  1. privateclassConnectThreadextendsThread{
  2. privatefinalBluetoothSocketmmSocket;
  3. privatefinalBluetoothDevicemmDevice;
  4. publicConnectThread(BluetoothDevicedevice){
  5. //UseatemporaryobjectthatislaterassignedtommSocket,
  6. //becausemmSocketisfinal
  7. BluetoothSockettmp=null;
  8. mmDevice=device;
  9. //GetaBluetoothSockettoconnectwiththegivenBluetoothDevice
  10. try{
  11. //MY_UUIDistheapp'sUUIDstring,alsousedbytheservercode
  12. tmp=device.createRfcommSocketToServiceRecord(MY_UUID);
  13. }catch(IOExceptione){}
  14. mmSocket=tmp;
  15. }
  16. publicvoidrun(){
  17. //Canceldiscoverybecauseitwillslowdowntheconnection
  18. mBluetoothAdapter.cancelDiscovery();
  19. try{
  20. //Connectthedevicethroughthesocket.Thiswillblock
  21. //untilitsucceedsorthrowsanexception
  22. mmSocket.connect();
  23. }catch(IOExceptionconnectException){
  24. //Unabletoconnect;closethesocketandgetout
  25. try{
  26. mmSocket.close();
  27. }catch(IOExceptioncloseException){}
  28. return;
  29. }
  30. //Doworktomanagetheconnection(inaseparatethread)
  31. manageConnectedSocket(mmSocket);
  32. }
  33. /**Willcancelanin-progressconnection,andclosethesocket*/
  34. publicvoidcancel(){
  35. try{
  36. mmSocket.close();
  37. }catch(IOExceptione){}
  38. }
  39. }


连接管理(数据通信)

分别通过BluetoothSocket的getInputStream()和getOutputStream()方法获取InputStream和OutputStream

使用read(bytes[])和write(bytes[])方法分别进行读写操作

注意:read(bytes[])方法会一直block,知道从流中读取到信息,而write(bytes[])方法并不是经常的block(比如在另一设备没有及时read或者中间缓冲区已满的情况下,write方法会block)

  1. privateclassConnectedThreadextendsThread{
  2. privatefinalBluetoothSocketmmSocket;
  3. privatefinalInputStreammmInStream;
  4. privatefinalOutputStreammmOutStream;
  5. publicConnectedThread(BluetoothSocketsocket){
  6. mmSocket=socket;
  7. InputStreamtmpIn=null;
  8. OutputStreamtmpOut=null;
  9. //Gettheinputandoutputstreams,usingtempobjectsbecause
  10. //memberstreamsarefinal
  11. try{
  12. tmpIn=socket.getInputStream();
  13. tmpOut=socket.getOutputStream();
  14. }catch(IOExceptione){}
  15. mmInStream=tmpIn;
  16. mmOutStream=tmpOut;
  17. }
  18. publicvoidrun(){
  19. byte[]buffer=newbyte[1024];//bufferstoreforthestream
  20. intbytes;//bytesreturnedfromread()
  21. //KeeplisteningtotheInputStreamuntilanexceptionoccurs
  22. while(true){
  23. try{
  24. //ReadfromtheInputStream
  25. bytes=mmInStream.read(buffer);
  26. //SendtheobtainedbytestotheUIActivity
  27. mHandler.obtainMessage(MESSAGE_READ,bytes,-1,buffer)
  28. .sendToTarget();
  29. }catch(IOExceptione){
  30. break;
  31. }
  32. }
  33. }
  34. /*CallthisfromthemainActivitytosenddatatotheremotedevice*/
  35. publicvoidwrite(byte[]bytes){
  36. try{
  37. mmOutStream.write(bytes);
  38. }catch(IOExceptione){}
  39. }
  40. /*CallthisfromthemainActivitytoshutdowntheconnection*/
  41. publicvoidcancel(){
  42. try{
  43. mmSocket.close();
  44. }catch(IOExceptione){}
  45. }
  46. }

引用资料:Android官方SDK、《Android/OPhone完全开发讲义》

转自:http://blog.csdn.net/gd920129/article/details/7487761

更多相关文章

  1. Delphi XE5 Android 运行黑屏卡死的解决方法
  2. Android编程: 调试方法
  3. ListView常用属性、方法
  4. android蓝牙BLE(一) —— 扫描
  5. Android 控件(button)对齐方法实现详解
  6. android 设置支持pad等大屏幕、大分辨率的设备!!
  7. Android Studio更新升级方法
  8. android 实现 APP 保活且正常升级的方法
  9. 远程调试 Android 设备使用入门

随机推荐

  1. Android菜单详解(二)——创建并响应选项菜
  2. Android和PHP开发最佳实践
  3. android的测试工具CTS
  4. UI布局参数(持续更新)
  5. Android(安卓)SDK中 tools 工具介绍
  6. Android窗口治理机制
  7. Android应用资源总结二:Android的问号?和@
  8. 开放式Android联盟成立
  9. Android(安卓)源码分析 - 消息处理机制
  10. Android常见问题总结(二)