现在的位置: 首页 > 综合 > 正文

android 蓝牙通信编程

2013年09月05日 ⁄ 综合 ⁄ 共 16108字 ⁄ 字号 评论关闭

公司项目涉及蓝牙通信,所以就简单的学了学,下面是自己参考了一些资料后的总结,希望对大家有帮助。

以下是开发中的几个关键步骤:

1,首先开启蓝牙

2,搜索可用设备

3,创建蓝牙socket,获取输入输出流

4,读取和写入数据

5,断开连接关闭蓝牙

下面是一个demo

效果图:

SearchDeviceActivity.java

package com.hello.project;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class SearchDeviceActivity extends Activity implements OnItemClickListener{


	private BluetoothAdapter blueadapter=null;
	private DeviceReceiver mydevice=new DeviceReceiver();
	private List<String> deviceList=new ArrayList<String>();
	private ListView deviceListview;
	private Button btserch;
	private ArrayAdapter<String> adapter;
	private boolean hasregister=false;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.finddevice);
		setView();
		setBluetooth();
		
	}
	
	private void setView(){
	
		deviceListview=(ListView)findViewById(R.id.devicelist);
		adapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceList);
		deviceListview.setAdapter(adapter);
		deviceListview.setOnItemClickListener(this);
		btserch=(Button)findViewById(R.id.start_seach);
		btserch.setOnClickListener(new ClinckMonitor());
		
	}

	@Override
	protected void onStart() {
		//注册蓝牙接收广播
		if(!hasregister){
			hasregister=true;
			IntentFilter filterStart=new IntentFilter(BluetoothDevice.ACTION_FOUND);	
			IntentFilter filterEnd=new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);	
			registerReceiver(mydevice, filterStart);
			registerReceiver(mydevice, filterEnd);
		}		
		super.onStart();
	}

	@Override
	protected void onDestroy() {
		if(blueadapter!=null&&blueadapter.isDiscovering()){
			blueadapter.cancelDiscovery();
		}
		if(hasregister){
			hasregister=false;
			unregisterReceiver(mydevice);
		}
		super.onDestroy();
	}
	/**
	 * Setting Up Bluetooth
	 */
	private void setBluetooth(){
		 blueadapter=BluetoothAdapter.getDefaultAdapter();
		 
			if(blueadapter!=null){	//Device support Bluetooth
				//确认开启蓝牙
				if(!blueadapter.isEnabled()){
					//请求用户开启
					Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
					startActivityForResult(intent, RESULT_FIRST_USER);
					//使蓝牙设备可见,方便配对
					Intent in=new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
					in.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 200);
					startActivity(in);
					//直接开启,不经过提示
					blueadapter.enable();
				}
			}
			else{	//Device does not support Bluetooth
				
				AlertDialog.Builder dialog = new AlertDialog.Builder(this);
				dialog.setTitle("No bluetooth devices");
				dialog.setMessage("Your equipment does not support bluetooth, please change device");
				
				dialog.setNegativeButton("cancel",
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog, int which) {
								
							}
						});
				dialog.show();
			}
	}
	
	/**
	 * Finding Devices
	 */
	private void findAvalibleDevice(){
		//获取可配对蓝牙设备
		Set<BluetoothDevice> device=blueadapter.getBondedDevices();
		
		if(blueadapter!=null&&blueadapter.isDiscovering()){
			deviceList.clear();
			adapter.notifyDataSetChanged();
		}
		if(device.size()>0){	//存在已经配对过的蓝牙设备
			for(Iterator<BluetoothDevice> it=device.iterator();it.hasNext();){
				BluetoothDevice btd=it.next();
				deviceList.add(btd.getName()+'\n'+btd.getAddress());
				adapter.notifyDataSetChanged();
			}
		}else{	//不存在已经配对过的蓝牙设备
			deviceList.add("No can be matched to use bluetooth");
			adapter.notifyDataSetChanged();
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		
		switch(resultCode){
		case RESULT_OK:
			findAvalibleDevice();
			break;
		case RESULT_CANCELED:
			break;
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	private class ClinckMonitor implements OnClickListener{

		@Override
		public void onClick(View v) {
			if(blueadapter.isDiscovering()){
				blueadapter.cancelDiscovery();
				btserch.setText("repeat search");
			}else{
				findAvalibleDevice();
				blueadapter.startDiscovery();
				btserch.setText("stop search");
			}
		}
	}
	/**
	 * 蓝牙搜索状态广播监听
	 * @author Andy
	 *
	 */
	private class DeviceReceiver extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {
			String action =intent.getAction();
			if(BluetoothDevice.ACTION_FOUND.equals(action)){	//搜索到新设备
				BluetoothDevice btd=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				//搜索没有配过对的蓝牙设备
				 if (btd.getBondState() != BluetoothDevice.BOND_BONDED) {
					 deviceList.add(btd.getName()+'\n'+btd.getAddress());
					 adapter.notifyDataSetChanged();
				 }
			}
			 else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){	//搜索结束
				 
	                if (deviceListview.getCount() == 0) {
	                	deviceList.add("No can be matched to use bluetooth");
	                	adapter.notifyDataSetChanged();
	                }
	                btserch.setText("repeat search");
	            }
		}	
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
		
		Log.e("msgParent", "Parent= "+arg0);
		Log.e("msgView", "View= "+arg1);
		Log.e("msgChildView", "ChildView= "+arg0.getChildAt(pos-arg0.getFirstVisiblePosition()));
		
			final String msg = deviceList.get(pos);
			
			if(blueadapter!=null&&blueadapter.isDiscovering()){
				blueadapter.cancelDiscovery();
				btserch.setText("repeat search");
			}
			
			AlertDialog.Builder dialog = new AlertDialog.Builder(this);// 定义一个弹出框对象
			dialog.setTitle("Confirmed connecting device");
			dialog.setMessage(msg);
			dialog.setPositiveButton("connect",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							BluetoothMsg.BlueToothAddress=msg.substring(msg.length()-17);
							
							if(BluetoothMsg.lastblueToothAddress!=BluetoothMsg.BlueToothAddress){
								BluetoothMsg.lastblueToothAddress=BluetoothMsg.BlueToothAddress;
							}
							
							Intent in=new Intent(SearchDeviceActivity.this,BluetoothActivity.class);
							startActivity(in);
						
						}
					});
			dialog.setNegativeButton("cancel",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							BluetoothMsg.BlueToothAddress = null;
						}
					});
			dialog.show();
	}
	
}

BluetoothMsg.java

package com.hello.project;

public class BluetoothMsg {
	/**
	 * 蓝牙连接类型
	 * @author Andy
	 *
	 */
	public enum ServerOrCilent{
		NONE,
		SERVICE,
		CILENT
	};
	//蓝牙连接方式
	public static ServerOrCilent serviceOrCilent = ServerOrCilent.NONE;
	//连接蓝牙地址
	public static String BlueToothAddress = null,lastblueToothAddress=null;
	//通信线程是否开启
	public static boolean isOpen = false;
		
}

finddevice.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id = "@+id/devices"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    
    <RelativeLayout
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content"
	  android:layout_alignParentBottom = "true"
	  android:id= "@+id/bt_bottombar">	  
					
		<Button android:id="@+id/start_seach"
			android:layout_width="match_parent" 
			android:layout_height="wrap_content"  
			android:layout_toRightOf="@+id/start_service"
			android:text="Began to search"/> 		
	</RelativeLayout>  

	 <ListView  
	    android:id="@+id/devicelist"
	    android:layout_width="fill_parent"  
	    android:layout_height="fill_parent" 
	    android:scrollingCache="false" 
	    android:divider="#ffc6c6c6" 
	    android:layout_weight="1.0" 
	    android:layout_above = "@id/bt_bottombar"
	    android:layout_below="@id/devices"
	    />
</RelativeLayout>

BluetoothActivity.java

package com.hello.project;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
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.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class BluetoothActivity extends  Activity{
	
	/* 一些常量,代表服务器的名称 */
	public static final String PROTOCOL_SCHEME_RFCOMM = "btspp";
	
	private ListView mListView;
	private Button sendButton;
	private Button disconnectButton;
	private EditText editMsgView;
	private ArrayAdapter<String> mAdapter;
	private List<String> msgList=new ArrayList<String>();
	Context mContext;
	
	private BluetoothServerSocket mserverSocket = null;
	private ServerThread startServerThread = null;
	private clientThread clientConnectThread = null;
	private BluetoothSocket socket = null;
	private BluetoothDevice device = null;
	private readThread mreadThread = null;;	
	private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
	
		@Override
	    public void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState); 
	        setContentView(R.layout.chat);
	        mContext = this;
	        init();
	    }
	
		private void init() {		   
			
			mAdapter=new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, msgList);
			mListView = (ListView) findViewById(R.id.list);
			mListView.setAdapter(mAdapter);
			mListView.setFastScrollEnabled(true);
			editMsgView= (EditText)findViewById(R.id.MessageText);	
			editMsgView.clearFocus();
			
			sendButton= (Button)findViewById(R.id.btn_msg_send);
			sendButton.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View arg0) {
				
					String msgText =editMsgView.getText().toString();
					if (msgText.length()>0) {
						sendMessageHandle(msgText);	
						editMsgView.setText("");
						editMsgView.clearFocus();
						//close InputMethodManager
						InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 
						imm.hideSoftInputFromWindow(editMsgView.getWindowToken(), 0);
					}else
					Toast.makeText(mContext, "发送内容不能为空!", Toast.LENGTH_SHORT).show();
				}
			});
			
			disconnectButton= (Button)findViewById(R.id.btn_disconnect);
			disconnectButton.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View arg0) {
					// TODO Auto-generated method stub
			        if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT) 
					{
			        	shutdownClient();
					}
					else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE) 
					{
						shutdownServer();
					}
					BluetoothMsg.isOpen = false;
					BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.NONE;
					Toast.makeText(mContext, "已断开连接!", Toast.LENGTH_SHORT).show();
				}
			});		
		}    

	    private Handler LinkDetectedHandler = new Handler() {
	        @Override
	        public void handleMessage(Message msg) {
	        	//Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();
	        	if(msg.what==1)
	        	{
	        		msgList.add((String)msg.obj);
	        	}
	        	else
	        	{
	        		msgList.add((String)msg.obj);
	        	}
				mAdapter.notifyDataSetChanged();
				mListView.setSelection(msgList.size() - 1);
	        }
	    };    
	    
	@Override
	protected void onResume() {
		
		BluetoothMsg.serviceOrCilent=BluetoothMsg.ServerOrCilent.CILENT;
		
		 if(BluetoothMsg.isOpen)
	        {
	        	Toast.makeText(mContext, "连接已经打开,可以通信。如果要再建立连接,请先断开!", Toast.LENGTH_SHORT).show();
	        	return;
	        }
	        if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.CILENT)
	        {
				String address = BluetoothMsg.BlueToothAddress;
				if(!address.equals("null"))
				{
					device = mBluetoothAdapter.getRemoteDevice(address);	
					clientConnectThread = new clientThread();
					clientConnectThread.start();
					BluetoothMsg.isOpen = true;
				}
				else
				{
					Toast.makeText(mContext, "address is null !", Toast.LENGTH_SHORT).show();
				}
	        }
	        else if(BluetoothMsg.serviceOrCilent==BluetoothMsg.ServerOrCilent.SERVICE)
	        {        	      	
	        	startServerThread = new ServerThread();
	        	startServerThread.start();
	        	BluetoothMsg.isOpen = true;
	        }
		super.onResume();
	}

	//开启客户端
		private class clientThread extends Thread { 		
			@Override
			public void run() {
				try {
					//创建一个Socket连接:只需要服务器在注册时的UUID号
					// socket = device.createRfcommSocketToServiceRecord(BluetoothProtocols.OBEX_OBJECT_PUSH_PROTOCOL_UUID);
					socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
					//连接
					Message msg2 = new Message();
					msg2.obj = "请稍候,正在连接服务器:"+BluetoothMsg.BlueToothAddress;
					msg2.what = 0;
					LinkDetectedHandler.sendMessage(msg2);
					
					socket.connect();
					
					Message msg = new Message();
					msg.obj = "已经连接上服务端!可以发送信息。";
					msg.what = 0;
					LinkDetectedHandler.sendMessage(msg);
					//启动接受数据
					mreadThread = new readThread();
					mreadThread.start();
				} 
				catch (IOException e) 
				{
					Log.e("connect", "", e);
					Message msg = new Message();
					msg.obj = "连接服务端异常!断开连接重新试一试。";
					msg.what = 0;
					LinkDetectedHandler.sendMessage(msg);
				} 
			}
		};

		//开启服务器
		private class ServerThread extends Thread { 
			@Override
			public void run() {
						
				try {
					/* 创建一个蓝牙服务器 
					 * 参数分别:服务器名称、UUID	 */	
					mserverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(PROTOCOL_SCHEME_RFCOMM,
							UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));		
					
					Log.d("server", "wait cilent connect...");
					
					Message msg = new Message();
					msg.obj = "请稍候,正在等待客户端的连接...";
					msg.what = 0;
					LinkDetectedHandler.sendMessage(msg);
					
					/* 接受客户端的连接请求 */
					socket = mserverSocket.accept();
					Log.d("server", "accept success !");
					
					Message msg2 = new Message();
					String info = "客户端已经连接上!可以发送信息。";
					msg2.obj = info;
					msg.what = 0;
					LinkDetectedHandler.sendMessage(msg2);
					//启动接受数据
					mreadThread = new readThread();
					mreadThread.start();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		};
		/* 停止服务器 */
		private void shutdownServer() {
			new Thread() {
				@Override
				public void run() {
					if(startServerThread != null)
					{
						startServerThread.interrupt();
						startServerThread = null;
					}
					if(mreadThread != null)
					{
						mreadThread.interrupt();
						mreadThread = null;
					}				
					try {					
						if(socket != null)
						{
							socket.close();
							socket = null;
						}
						if (mserverSocket != null)
						{
							mserverSocket.close();/* 关闭服务器 */
							mserverSocket = null;
						}
					} catch (IOException e) {
						Log.e("server", "mserverSocket.close()", e);
					}
				};
			}.start();
		}
		/* 停止客户端连接 */
		private void shutdownClient() {
			new Thread() {
				@Override
				public void run() {
					if(clientConnectThread!=null)
					{
						clientConnectThread.interrupt();
						clientConnectThread= null;
					}
					if(mreadThread != null)
					{
						mreadThread.interrupt();
						mreadThread = null;
					}
					if (socket != null) {
						try {
							socket.close();
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						socket = null;
					}
				};
			}.start();
		}
		
		//发送数据
		private void sendMessageHandle(String msg) 
		{		
			if (socket == null) 
			{
				Toast.makeText(mContext, "没有连接", Toast.LENGTH_SHORT).show();
				return;
			}
			try {				
				OutputStream os = socket.getOutputStream(); 
				os.write(msg.getBytes());
			} catch (IOException e) {
				e.printStackTrace();
			}			
			msgList.add(msg);
			mAdapter.notifyDataSetChanged();
			mListView.setSelection(msgList.size() - 1);
		}
		//读取数据
	    private class readThread extends Thread { 
	        @Override
			public void run() {
	        	
	            byte[] buffer = new byte[1024];
	            int bytes;
	            InputStream mmInStream = null;
	            
				try {
					mmInStream = socket.getInputStream();
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}	
	            while (true) {
	                try {
	                    // Read from the InputStream
	                    if( (bytes = mmInStream.read(buffer)) > 0 )
	                    {
		                    byte[] buf_data = new byte[bytes];
					    	for(int i=0; i<bytes; i++)
					    	{
					    		buf_data[i] = buffer[i];
					    	}
							String s = new String(buf_data);
							Message msg = new Message();
							msg.obj = s;
							msg.what = 1;
							LinkDetectedHandler.sendMessage(msg);
	                    }
	                } catch (IOException e) {
	                	try {
							mmInStream.close();
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
	                    break;
	                }
	            }
	        }
	    }
	    @Override
	    protected void onDestroy() {
	        super.onDestroy();

	        if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.CILENT) 
			{
	        	shutdownClient();
			}
			else if (BluetoothMsg.serviceOrCilent == BluetoothMsg.ServerOrCilent.SERVICE) 
			{
				shutdownServer();
			}
	        BluetoothMsg.isOpen = false;
			BluetoothMsg.serviceOrCilent = BluetoothMsg.ServerOrCilent.NONE;
	    }

	    
}

chat.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:id = "@+id/container"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    
    <RelativeLayout
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content"
	  android:id= "@+id/edit_bottombar"
	  android:layout_alignParentBottom = "true">

        <Button android:id="@+id/btn_disconnect"
			android:layout_width="65dp" 
			android:layout_height="wrap_content"  
			android:layout_alignParentLeft ="true"
			android:text="断开"/> 
			
		<Button android:id="@+id/btn_msg_send"
			android:layout_width="65dp" 
			android:layout_height="wrap_content"  
			android:layout_alignParentRight ="true"
			android:text="发送"/> 	
		<EditText
	         android:layout_width="fill_parent"
	      	 android:layout_height = "wrap_content"
	      	 android:layout_toLeftOf="@id/btn_msg_send"
	      	 android:layout_toRightOf="@+id/btn_disconnect"  	      	 
	      	 android:hint = "说点什么呢?"
	      	 android:textSize="15dip"
	      	 android:id = "@+id/MessageText"/>
	</RelativeLayout>  

	 <ListView  
	    android:id="@+id/list"
	    android:layout_width="fill_parent"  
	    android:layout_height="fill_parent" 
	    android:scrollingCache="false" 
	    android:divider="#ffc6c6c6" 
	    android:layout_weight="1.0" 
	    android:layout_above = "@id/edit_bottombar"
	    android:layout_below="@id/container"
	    />
</RelativeLayout>

最后别忘了加入权限

<uses-permission android:name="android.permission.BLUETOOTH"/>
	<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
	<uses-permission android:name="android.permission.READ_CONTACTS"/>

抱歉!评论已关闭.