android蓝牙通信

android蓝牙调了几天,终于可以收发数据了,尽管还没有完全排除异常,至少在通信过程上算是已经打通了。下面就来总结一下,希望对于没有接触过蓝牙,和刚开始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:

package thu.wolf.bluetooth;



import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class Bluetooth_MainActivity extends Activity {

	private Button conn  = null;
	private Button server = null;
	private Button client = null;
	private Button send = null;
	private EditText msg = null;
	private BluetoothRev bluetoothRev = null;
	private BluetoothAdapter adapter = null;
	private BluetoothDevice device = null;
	

	private static final String S_NAME = "BluetoothChat";
	private static final UUID S_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	private InputStream m_InputStream = null;
	private OutputStream m_OutputStream = null;
	private String address = null;
	boolean serverflag ;
	private String TAG = "catch";
	private static final String MESSAGE_READ = "Message_Read";
	private ArrayList<String> blueToothNames = null;
    private ArrayList<BluetoothDevice> blutToothDevices = null;
    private HandlerThread handlerThread = null;
    private MyHandler transHandler = null;
    
    
    boolean isfound = false;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bluetooth__main);
     
        conn  = (Button)findViewById(R.id.conn);
        server = (Button)findViewById(R.id.server);
        client = (Button)findViewById(R.id.client);
       // client.setEnabled(false);
        send = (Button)findViewById(R.id.send);
        msg = (EditText)findViewById(R.id.msg);
        
        
        conn.setOnClickListener(new connOnClickListener());
        server.setOnClickListener(new serverOnClickListener());
        client.setOnClickListener(new clientOnClickListener());
        send.setOnClickListener(new sendOnClickListener());
        
        blueToothNames = new ArrayList<String>();
        blutToothDevices = new ArrayList<BluetoothDevice>();    
        
        
        
      //获取一个蓝牙适配器
        adapter = BluetoothAdapter.getDefaultAdapter();
        
		if( adapter != null)//判断是否为空
		{
			System.out.println("本机拥有蓝牙设备。");
				
			if(!adapter.isEnabled())//判断当前蓝牙设备是否可用
			{
		Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//创建一个Intent对象,用于启动一个activity,来提示用户开启蓝牙
				startActivity(intent);//开启一个activity提醒有应用要开启蓝牙			
			}		
			else
				Toast.makeText(this, "蓝牙已开启,可以启动服务", 50).show();
				
		}
		else
			System.out.println("没有蓝牙设备!");
		
		
        
		//生成一个HandlerThread对象,实现了使用Looper来处理消息队列的功能,这个类由Android应用程序框架提供
		handlerThread = new HandlerThread("handler_thread");
		//在使用HandlerThread的getLooper()方法之前,必须先调用该类的start();
		handlerThread.start();//只能在主线程中开启此线程		
        transHandler = new MyHandler(handlerThread.getLooper());

    }
    
    class MyHandler extends Handler {
        public MyHandler() {  
    		} 

    	public MyHandler(Looper L) {
                 super(L);
             }     
        // 子类必须重写此方法,接受数据
    	@Override
    	public void handleMessage(Message msg) {
    		 // TODO Auto-generated method stub
    		 Log.d("MyHandler", "handleMessage......");
    		 super.handleMessage(msg);
    		 // 此处可以更新UI
    		 byte[] buffer = new byte[1024];
    		 buffer = (byte[])msg.obj;
    		 
    		 String str = new String(buffer, 0, msg.arg1);
    		 System.out.println(str);
    	 }
    }
    
    
    class serverOnClickListener implements OnClickListener{

  		@Override
  		public void onClick(View v) {
  			serverflag = true;
  			
			Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
			intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 350);
			startActivity(intent); 			
			
			client.setEnabled(false);
			conn.setEnabled(false);
  			
  			RequestAcceptThread ServerThread = new RequestAcceptThread();
  			ServerThread.start();

  		}
    }
    class clientOnClickListener implements OnClickListener{

  		@Override
  		public void onClick(View v) {
  			
  			bluetoothRev = new BluetoothRev();
  			//创建intentfilter及广播接收函数
  	        IntentFilter discoveryfilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
  	        registerReceiver(bluetoothRev, discoveryfilter);
  	        IntentFilter foundfilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
  	        registerReceiver(bluetoothRev, foundfilter);
  			adapter.startDiscovery();
  			msg.setText("正在扫描");
  			
  			server.setEnabled(false);

  		}
    }
    
            
    private class BluetoothRev extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			// TODO Auto-generated method stub
			
			String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) 
            {
                // Get the BluetoothDevice object from the Intent
            	//BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            	device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            	//blutToothDevices.add(device);
            	//blueToothNames.add(device.getName());                
            	isfound = true;
				Toast.makeText(Bluetooth_MainActivity.this, "已获取设备,可连接", 50).show();
            // When discovery is finished, change the Activity title
            } 
            else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) 
            {
            	if(isfound == false)
            		msg.setText("未发现设备,重新搜索");//此action只表示发现结束,可以是发现了设备,也可以是没有发现到设备
            	else
            	{
            		msg.setText("发现设备");
            	}            	
        		adapter.cancelDiscovery();
        		Bluetooth_MainActivity.this.unregisterReceiver(this);
            }
		}
    	
    }
	
	//获取bluetoothAdapter适配器
	class connOnClickListener implements OnClickListener{
	
		@Override
		public void onClick(View v) {
		// TODO Auto-generated method stub
			RequestThread ClientThread = new RequestThread( device );
			ClientThread.start();		
		}    	
	}     
    
    
    class sendOnClickListener implements OnClickListener{

  		@Override
  		public void onClick(View v) {
  			
  			String data = "hello world!";
  			try {
				m_OutputStream.write(data.getBytes());  		
				System.out.println(data);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("数据发送失败!");
			}
  			System.out.println("数据已发出");
  		}
    }

  /*作为服务端应答socket请求,得到socket */

  	public class RequestAcceptThread extends Thread{
  		private BluetoothServerSocket m_BluetoothServersocket = null;
  		
  		public RequestAcceptThread(){
  			BluetoothServerSocket tmpBluetoothServersocket = null;
  			try{
  				tmpBluetoothServersocket = adapter.listenUsingRfcommWithServiceRecord(S_NAME, S_UUID);
  			}catch(IOException e){}
  			m_BluetoothServersocket = tmpBluetoothServersocket;
			System.out.println("服务已开启");
			msg.setText("服务已开启");
 
  		}
  		@Override
  		public void run() {
  			// TODO Auto-generated method stub
  			super.run();
  			//阻塞监听直到异常出现或者有socket返回
  			BluetoothSocket socket = null;
			
  			while(true)
  			{
  				try{
  					//System.out.println("waiting。。。。");
  					//msg.setText("等待请求");
  					socket = m_BluetoothServersocket.accept();
  					if(socket != null) break;
  					
  				}catch(IOException e){
  					System.out.println("exception while waiting");
  					break;
  				}
  			}
  			System.out.println("接收到请求!");
  				if(socket != null){
  					System.out.println("连接已建立");
  					
  			    	ConnectedThread readthread = new ConnectedThread(socket);
  			    	readthread.start(); 					

  				}
  			
  		}
  		//取消socket监听,关闭线程
  		public void cancel(){
  			try{
  				m_BluetoothServersocket.close();
  			}catch(IOException e){}
  		}
  	}
  	
    private class RequestThread extends Thread {  
        private  BluetoothSocket mmSocket = null;  
        private  BluetoothDevice mmDevice = null;  
      
        public RequestThread(BluetoothDevice device) {  
            // Use a temporary object that is later assigned to mmSocket,  
            // because mmSocket is final  
            BluetoothSocket tmp = null;  
            //mmDevice = device;  
            msg.setText("开始申请连接");
            // Get a BluetoothSocket to connect with the given BluetoothDevice  
            try {  
                // MY_UUID is the app's UUID string, also used by the server code  
                //System.out.println("ask for connection");
            	tmp = device.createRfcommSocketToServiceRecord(S_UUID);  
            } catch (IOException e) { }  
            if( tmp != null){
            	mmSocket = tmp;
            	Toast.makeText(Bluetooth_MainActivity.this, "socket is ok!", 100);
            }
        }  
      
        public void run() {  
            // Cancel discovery because it will slow down the connection  
          while(true){//必须多次连接以保证成功连接
            try {  
                // Connect the device through the socket. This will block  
                // until it succeeds or throws an exception  
            	System.out.println("try to connection");
                mmSocket.connect();  
                if(mmSocket != null)  
                	{
                		//mSocketManage(mmSocket);
                		ConnectedThread readthread = new ConnectedThread(mmSocket);
                		readthread.start();                		
                		break;                	
                	}
                
            } catch (IOException connectException) {  
                // Unable to connect; close the socket and get out  
            	System.out.println("unable to connection");
                try {  
                    mmSocket.close();  
                } catch (IOException closeException) { }  
                
                return;  
            }  
      }
	
			System.out.println("连接成功,可发送数据");
        }  
      
        /** Will cancel an in-progress connection, and close the socket */  
        public void cancel() {  
            try {  
                mmSocket.close();  
            } catch (IOException e) { }  
        }  
    }  
    


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.bluetooth__main, menu);
        return true;
    }

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		unregisterReceiver(bluetoothRev);
		super.onDestroy();
		
	}
	
	//
	private class ConnectedThread extends Thread {  
	        
			private final BluetoothSocket mmSocket;  
	        
	        Message msg = transHandler.obtainMessage();
	      
	        public ConnectedThread(BluetoothSocket socket) {  
	            mmSocket = socket;  
	            InputStream tmpIn = null;  
	            OutputStream tmpOut = null;  
	      
	            // Get the input and output streams, using temp objects because  
	            // member streams are final  
	            try {  
	                tmpIn = socket.getInputStream();  
	                tmpOut = socket.getOutputStream();  
	            } catch (IOException e) { }  
	      

	            m_InputStream = tmpIn;
	            m_OutputStream= tmpOut;
	        }  
	      
	        public void run() {  
	            byte[] buffer = new byte[1024]; // buffer store for the stream  
	            int bytes; // bytes returned from read()  

	            // Keep listening to the InputStream until an exception occurs  
	            while (true)
	            {  
	                try {  
	                    // Read from the InputStream  	                    
	                	bytes = m_InputStream.read(buffer);
	                	
	                    msg.obj = buffer;
	                    msg.arg1 = bytes;
	                    transHandler.sendMessage(msg);
	                    // Send the obtained bytes to the UI Activity  
	                    //transHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer).sendToTarget();  
	                  
	                } catch (IOException e) {  
	                    break;  
	                }  
	            }  

	        }  
	      
	        /* Call this from the main Activity to send data to the remote device */  
	        public void write(byte[] bytes) {  
	            try {  
	                //mmOutStream.write(bytes);  
	            	m_OutputStream.write(bytes);
	            } catch (IOException e) { }  
	        }  
	      
	        /* Call this from the main Activity to shutdown the connection */  
	        public void cancel() {  
	            try {  
	                mmSocket.close();  
	            } catch (IOException e) { }  
	        }  
	   }     
}

此程序仅供测试使用,还有异常没有调试,且操作不太方便,不建议直接运行,可下载源码参阅http://download.csdn.net/detail/eric41050808/6614225



评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值