android蓝牙通信

首先我们先说一下,在android操作系统中可对蓝牙做得工作。
对蓝牙的操作分两种,一种是系统操作,一种是应用操作。
系统可对蓝牙做所有外部操作,包括开启,关闭,设置可见性,扫描周围设备,匹配及取消等等;应用可以对蓝牙做以上大部分操作,除了匹配操作不能在应用中使用代码完成。换句话说,如果您的应用程序中使用到蓝牙,则要保证使用前,手动在android操作系统中完成目标机之间的匹配工作。

接下来说一下,介绍一下两部android手机,使用蓝牙通信的过程。
两部手机通过蓝牙通信,则一定要其中一台是服务器端,另一台是客户端。蓝牙设备在本地叫BluetoothAdapter,本地获取到的其他蓝牙设备叫BluetoothDevice。下面分别介绍在服务器端和客户端上程序的操作过程。为方便理解两者分开介绍,但在具体实现过程中有些代码可以融合。具体代码可下载http://download.csdn.net/detail/eric41050808/6614225,参阅。

在服务器端,注意如下几点:
1.一定要保证通信双方已经手动完成匹配;
2.服务端要开启可见性,以便客户端搜索到;
3.使用BluetoothServerSocket的方法listenUsingRfcommWithServiceRecord()获取ServerSocket对象,再使用ServerSocket的accept()方法阻塞接收请求者的连接请求,成功后该方法返回BluetoothSocket对象;
4.使用获取到的socket对象的输入输出流方法操作数据通信,接收到的数据一定要通过handler处理显示。

在客户端,注意如下几点:
1.同样,一定要保证蓝牙开启,且通信双方已经手动完成匹配;
2.通过广播扫描周围可用设备,并确定该设备已与本机完成匹配;
3.使用上步扫描到的device对象,调用createRfcommSocketToServiceRecord()方法,获取BluetoothSocket对象,并用该对象调用connect()方法想服务器提出连接请求。注意此连接请求过程要循环请求,直至完成连接。

4.使用此连接的socket对象的输入输出流方法操作数据通信,接收到的数据一定要通过handler处理显示。


程序界面:


文件名Bluetooth_MainActivity.java:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package thu.wolf.bluetooth;  
  2.   
  3.   
  4.   
  5. import java.io.IOException;  
  6. import java.io.InputStream;  
  7. import java.io.OutputStream;  
  8. import java.util.ArrayList;  
  9. import java.util.UUID;  
  10.   
  11. import android.app.Activity;  
  12. import android.bluetooth.BluetoothAdapter;  
  13. import android.bluetooth.BluetoothDevice;  
  14. import android.bluetooth.BluetoothServerSocket;  
  15. import android.bluetooth.BluetoothSocket;  
  16. import android.content.BroadcastReceiver;  
  17. import android.content.Context;  
  18. import android.content.Intent;  
  19. import android.content.IntentFilter;  
  20. import android.os.Bundle;  
  21. import android.os.Handler;  
  22. import android.os.HandlerThread;  
  23. import android.os.Looper;  
  24. import android.os.Message;  
  25. import android.util.Log;  
  26. import android.view.Menu;  
  27. import android.view.View;  
  28. import android.view.View.OnClickListener;  
  29. import android.widget.Button;  
  30. import android.widget.EditText;  
  31. import android.widget.Toast;  
  32.   
  33. public class Bluetooth_MainActivity extends Activity {  
  34.   
  35.     private Button conn  = null;  
  36.     private Button server = null;  
  37.     private Button client = null;  
  38.     private Button send = null;  
  39.     private EditText msg = null;  
  40.     private BluetoothRev bluetoothRev = null;  
  41.     private BluetoothAdapter adapter = null;  
  42.     private BluetoothDevice device = null;  
  43.       
  44.   
  45.     private static final String S_NAME = "BluetoothChat";  
  46.     private static final UUID S_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");  
  47.     private InputStream m_InputStream = null;  
  48.     private OutputStream m_OutputStream = null;  
  49.     private String address = null;  
  50.     boolean serverflag ;  
  51.     private String TAG = "catch";  
  52.     private static final String MESSAGE_READ = "Message_Read";  
  53.     private ArrayList<String> blueToothNames = null;  
  54.     private ArrayList<BluetoothDevice> blutToothDevices = null;  
  55.     private HandlerThread handlerThread = null;  
  56.     private MyHandler transHandler = null;  
  57.       
  58.       
  59.     boolean isfound = false;  
  60.   
  61.   
  62.     @Override  
  63.     protected void onCreate(Bundle savedInstanceState) {  
  64.         super.onCreate(savedInstanceState);  
  65.         setContentView(R.layout.activity_bluetooth__main);  
  66.        
  67.         conn  = (Button)findViewById(R.id.conn);  
  68.         server = (Button)findViewById(R.id.server);  
  69.         client = (Button)findViewById(R.id.client);  
  70.        // client.setEnabled(false);  
  71.         send = (Button)findViewById(R.id.send);  
  72.         msg = (EditText)findViewById(R.id.msg);  
  73.           
  74.           
  75.         conn.setOnClickListener(new connOnClickListener());  
  76.         server.setOnClickListener(new serverOnClickListener());  
  77.         client.setOnClickListener(new clientOnClickListener());  
  78.         send.setOnClickListener(new sendOnClickListener());  
  79.           
  80.         blueToothNames = new ArrayList<String>();  
  81.         blutToothDevices = new ArrayList<BluetoothDevice>();      
  82.           
  83.           
  84.           
  85.       //获取一个蓝牙适配器  
  86.         adapter = BluetoothAdapter.getDefaultAdapter();  
  87.           
  88.         if( adapter != null)//判断是否为空  
  89.         {  
  90.             System.out.println("本机拥有蓝牙设备。");  
  91.                   
  92.             if(!adapter.isEnabled())//判断当前蓝牙设备是否可用  
  93.             {  
  94.         Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//创建一个Intent对象,用于启动一个activity,来提示用户开启蓝牙  
  95.                 startActivity(intent);//开启一个activity提醒有应用要开启蓝牙            
  96.             }         
  97.             else  
  98.                 Toast.makeText(this"蓝牙已开启,可以启动服务"50).show();  
  99.                   
  100.         }  
  101.         else  
  102.             System.out.println("没有蓝牙设备!");  
  103.           
  104.           
  105.           
  106.         //生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Android应用程序框架提供  
  107.         handlerThread = new HandlerThread("handler_thread");  
  108.         //在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();  
  109.         handlerThread.start();//只能在主线程中开启此线程          
  110.         transHandler = new MyHandler(handlerThread.getLooper());  
  111.   
  112.     }  
  113.       
  114.     class MyHandler extends Handler {  
  115.         public MyHandler() {    
  116.             }   
  117.   
  118.         public MyHandler(Looper L) {  
  119.                  super(L);  
  120.              }       
  121.         // 子类必须重写此方法,接受数据  
  122.         @Override  
  123.         public void handleMessage(Message msg) {  
  124.              // TODO Auto-generated method stub  
  125.              Log.d("MyHandler""handleMessage......");  
  126.              super.handleMessage(msg);  
  127.              // 此处可以更新UI  
  128.              byte[] buffer = new byte[1024];  
  129.              buffer = (byte[])msg.obj;  
  130.                
  131.              String str = new String(buffer, 0, msg.arg1);  
  132.              System.out.println(str);  
  133.          }  
  134.     }  
  135.       
  136.       
  137.     class serverOnClickListener implements OnClickListener{  
  138.   
  139.         @Override  
  140.         public void onClick(View v) {  
  141.             serverflag = true;  
  142.               
  143.             Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);  
  144.             intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 350);  
  145.             startActivity(intent);            
  146.               
  147.             client.setEnabled(false);  
  148.             conn.setEnabled(false);  
  149.               
  150.             RequestAcceptThread ServerThread = new RequestAcceptThread();  
  151.             ServerThread.start();  
  152.   
  153.         }  
  154.     }  
  155.     class clientOnClickListener implements OnClickListener{  
  156.   
  157.         @Override  
  158.         public void onClick(View v) {  
  159.               
  160.             bluetoothRev = new BluetoothRev();  
  161.             //创建intentfilter及广播接收函数  
  162.             IntentFilter discoveryfilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);  
  163.             registerReceiver(bluetoothRev, discoveryfilter);  
  164.             IntentFilter foundfilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);  
  165.             registerReceiver(bluetoothRev, foundfilter);  
  166.             adapter.startDiscovery();  
  167.             msg.setText("正在扫描");  
  168.               
  169.             server.setEnabled(false);  
  170.   
  171.         }  
  172.     }  
  173.       
  174.               
  175.     private class BluetoothRev extends BroadcastReceiver{  
  176.   
  177.         @Override  
  178.         public void onReceive(Context context, Intent intent) {  
  179.             // TODO Auto-generated method stub  
  180.               
  181.             String action = intent.getAction();  
  182.             if (BluetoothDevice.ACTION_FOUND.equals(action))   
  183.             {  
  184.                 // Get the BluetoothDevice object from the Intent  
  185.                 //BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
  186.                 device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
  187.                 //blutToothDevices.add(device);  
  188.                 //blueToothNames.add(device.getName());                  
  189.                 isfound = true;  
  190.                 Toast.makeText(Bluetooth_MainActivity.this"已获取设备,可连接"50).show();  
  191.             // When discovery is finished, change the Activity title  
  192.             }   
  193.             else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))   
  194.             {  
  195.                 if(isfound == false)  
  196.                     msg.setText("未发现设备,重新搜索");//此action只表示发现结束,可以是发现了设备,也可以是没有发现到设备  
  197.                 else  
  198.                 {  
  199.                     msg.setText("发现设备");  
  200.                 }                 
  201.                 adapter.cancelDiscovery();  
  202.                 Bluetooth_MainActivity.this.unregisterReceiver(this);  
  203.             }  
  204.         }  
  205.           
  206.     }  
  207.       
  208.     //获取bluetoothAdapter适配器  
  209.     class connOnClickListener implements OnClickListener{  
  210.       
  211.         @Override  
  212.         public void onClick(View v) {  
  213.         // TODO Auto-generated method stub  
  214.             RequestThread ClientThread = new RequestThread( device );  
  215.             ClientThread.start();         
  216.         }         
  217.     }       
  218.       
  219.       
  220.     class sendOnClickListener implements OnClickListener{  
  221.   
  222.         @Override  
  223.         public void onClick(View v) {  
  224.               
  225.             String data = "hello world!";  
  226.             try {  
  227.                 m_OutputStream.write(data.getBytes());            
  228.                 System.out.println(data);  
  229.             } catch (IOException e) {  
  230.                 // TODO Auto-generated catch block  
  231.                 e.printStackTrace();  
  232.                 System.out.println("数据发送失败!");  
  233.             }  
  234.             System.out.println("数据已发出");  
  235.         }  
  236.     }  
  237.   
  238.   /*作为服务端应答socket请求,得到socket */  
  239.   
  240.     public class RequestAcceptThread extends Thread{  
  241.         private BluetoothServerSocket m_BluetoothServersocket = null;  
  242.           
  243.         public RequestAcceptThread(){  
  244.             BluetoothServerSocket tmpBluetoothServersocket = null;  
  245.             try{  
  246.                 tmpBluetoothServersocket = adapter.listenUsingRfcommWithServiceRecord(S_NAME, S_UUID);  
  247.             }catch(IOException e){}  
  248.             m_BluetoothServersocket = tmpBluetoothServersocket;  
  249.             System.out.println("服务已开启");  
  250.             msg.setText("服务已开启");  
  251.    
  252.         }  
  253.         @Override  
  254.         public void run() {  
  255.             // TODO Auto-generated method stub  
  256.             super.run();  
  257.             //阻塞监听直到异常出现或者有socket返回  
  258.             BluetoothSocket socket = null;  
  259.               
  260.             while(true)  
  261.             {  
  262.                 try{  
  263.                     //System.out.println("waiting。。。。");  
  264.                     //msg.setText("等待请求");  
  265.                     socket = m_BluetoothServersocket.accept();  
  266.                     if(socket != nullbreak;  
  267.                       
  268.                 }catch(IOException e){  
  269.                     System.out.println("exception while waiting");  
  270.                     break;  
  271.                 }  
  272.             }  
  273.             System.out.println("接收到请求!");  
  274.                 if(socket != null){  
  275.                     System.out.println("连接已建立");  
  276.                       
  277.                     ConnectedThread readthread = new ConnectedThread(socket);  
  278.                     readthread.start();                       
  279.   
  280.                 }  
  281.               
  282.         }  
  283.         //取消socket监听,关闭线程  
  284.         public void cancel(){  
  285.             try{  
  286.                 m_BluetoothServersocket.close();  
  287.             }catch(IOException e){}  
  288.         }  
  289.     }  
  290.       
  291.     private class RequestThread extends Thread {    
  292.         private  BluetoothSocket mmSocket = null;    
  293.         private  BluetoothDevice mmDevice = null;    
  294.         
  295.         public RequestThread(BluetoothDevice device) {    
  296.             // Use a temporary object that is later assigned to mmSocket,    
  297.             // because mmSocket is final    
  298.             BluetoothSocket tmp = null;    
  299.             //mmDevice = device;    
  300.             msg.setText("开始申请连接");  
  301.             // Get a BluetoothSocket to connect with the given BluetoothDevice    
  302.             try {    
  303.                 // MY_UUID is the app's UUID string, also used by the server code    
  304.                 //System.out.println("ask for connection");  
  305.                 tmp = device.createRfcommSocketToServiceRecord(S_UUID);    
  306.             } catch (IOException e) { }    
  307.             if( tmp != null){  
  308.                 mmSocket = tmp;  
  309.                 Toast.makeText(Bluetooth_MainActivity.this"socket is ok!"100);  
  310.             }  
  311.         }    
  312.         
  313.         public void run() {    
  314.             // Cancel discovery because it will slow down the connection    
  315.           while(true){//必须多次连接以保证成功连接  
  316.             try {    
  317.                 // Connect the device through the socket. This will block    
  318.                 // until it succeeds or throws an exception    
  319.                 System.out.println("try to connection");  
  320.                 mmSocket.connect();    
  321.                 if(mmSocket != null)    
  322.                     {  
  323.                         //mSocketManage(mmSocket);  
  324.                         ConnectedThread readthread = new ConnectedThread(mmSocket);  
  325.                         readthread.start();                       
  326.                         break;                    
  327.                     }  
  328.                   
  329.             } catch (IOException connectException) {    
  330.                 // Unable to connect; close the socket and get out    
  331.                 System.out.println("unable to connection");  
  332.                 try {    
  333.                     mmSocket.close();    
  334.                 } catch (IOException closeException) { }    
  335.                   
  336.                 return;    
  337.             }    
  338.       }  
  339.       
  340.             System.out.println("连接成功,可发送数据");  
  341.         }    
  342.         
  343.         /** Will cancel an in-progress connection, and close the socket */    
  344.         public void cancel() {    
  345.             try {    
  346.                 mmSocket.close();    
  347.             } catch (IOException e) { }    
  348.         }    
  349.     }    
  350.       
  351.   
  352.   
  353.     @Override  
  354.     public boolean onCreateOptionsMenu(Menu menu) {  
  355.         // Inflate the menu; this adds items to the action bar if it is present.  
  356.         getMenuInflater().inflate(R.menu.bluetooth__main, menu);  
  357.         return true;  
  358.     }  
  359.   
  360.     @Override  
  361.     protected void onDestroy() {  
  362.         // TODO Auto-generated method stub  
  363.         unregisterReceiver(bluetoothRev);  
  364.         super.onDestroy();  
  365.           
  366.     }  
  367.       
  368.     //  
  369.     private class ConnectedThread extends Thread {    
  370.               
  371.             private final BluetoothSocket mmSocket;    
  372.               
  373.             Message msg = transHandler.obtainMessage();  
  374.             
  375.             public ConnectedThread(BluetoothSocket socket) {    
  376.                 mmSocket = socket;    
  377.                 InputStream tmpIn = null;    
  378.                 OutputStream tmpOut = null;    
  379.             
  380.                 // Get the input and output streams, using temp objects because    
  381.                 // member streams are final    
  382.                 try {    
  383.                     tmpIn = socket.getInputStream();    
  384.                     tmpOut = socket.getOutputStream();    
  385.                 } catch (IOException e) { }    
  386.             
  387.   
  388.                 m_InputStream = tmpIn;  
  389.                 m_OutputStream= tmpOut;  
  390.             }    
  391.             
  392.             public void run() {    
  393.                 byte[] buffer = new byte[1024]; // buffer store for the stream    
  394.                 int bytes; // bytes returned from read()    
  395.   
  396.                 // Keep listening to the InputStream until an exception occurs    
  397.                 while (true)  
  398.                 {    
  399.                     try {    
  400.                         // Read from the InputStream                          
  401.                         bytes = m_InputStream.read(buffer);  
  402.                           
  403.                         msg.obj = buffer;  
  404.                         msg.arg1 = bytes;  
  405.                         transHandler.sendMessage(msg);  
  406.                         // Send the obtained bytes to the UI Activity    
  407.                         //transHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();    
  408.                         
  409.                     } catch (IOException e) {    
  410.                         break;    
  411.                     }    
  412.                 }    
  413.   
  414.             }    
  415.             
  416.             /* Call this from the main Activity to send data to the remote device */    
  417.             public void write(byte[] bytes) {    
  418.                 try {    
  419.                     //mmOutStream.write(bytes);    
  420.                     m_OutputStream.write(bytes);  
  421.                 } catch (IOException e) { }    
  422.             }    
  423.             
  424.             /* Call this from the main Activity to shutdown the connection */    
  425.             public void cancel() {    
  426.                 try {    
  427.                     mmSocket.close();    
  428.                 } catch (IOException e) { }    
  429.             }    
  430.        }       
  431. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值