android 蓝牙学习笔记

蓝牙部分学习

蓝牙之间的通信需要四部分:

1设置蓝牙设备

BluetoothDevice类:本地蓝牙适配器,可以发现蓝牙设备,查询帮定的设备,

使用已知的MAC地址实例化一个蓝牙设备建立一个BluetoothServerSocket

BluetoothDevice:远端的蓝牙设备,使用它请求远端蓝牙设备连接或是取得远端蓝牙设备的一些属性(其信息封装在bluetoothsocket中)

bluetoothsocket:蓝牙的套接字接口

Bluetoothserversocket:打开服务连接来监听可能到来的请求

Bluttoothclass:描述一个蓝牙设备的一般特点和能力

2寻找设备

3连接设备

4设备之间的数据传输

具体编程实现

1启动蓝牙

在构造器中取得蓝牙造配器

BluetoothAdaptermBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();

查询蓝牙设备的状态(打开)

if(mBluetoothAdapter.isEnabled()){

Intentintent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

startActivityForResult(intent,REQUEST_ENABLE_BT);

}

2查找设备

3查询已配对设备

1Set<BluetoothDevice>pairedDevices=mBluetoothAdapter.getBondedDevices();2//Iftherearepaireddevices3if(pairedDevices.size()>0){4//Loopthroughpaireddevices5for(BluetoothDevicedevice:pairedDevices){6//AddthenameandaddresstoanarrayadaptertoshowinaListView7mArrayAdapter.add(device.getName()+"\n"+device.getAddress());8}9}

4扫描设备

1//CreateaBroadcastReceiverforACTION_FOUND2privatefinalBroadcastReceivermReceiver=newBroadcastReceiver(){3publicvoidonReceive(Contextcontext,Intentintent){4Stringaction=intent.getAction();5//Whendiscoveryfindsadevice6if(BluetoothDevice.ACTION_FOUND.equals(action)){7//GettheBluetoothDeviceobjectfromtheIntent8BluetoothDevicedevice=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);9//AddthenameandaddresstoanarrayadaptertoshowinaListView10mArrayAdapter.add(device.getName()+"\n"+device.getAddress());11}12}13};1415//RegistertheBroadcastReceiver16IntentFilterfilter=newIntentFilter(BluetoothDevice.ACTION_FOUND);17registerReceiver(mReceiver,filter);//Don'tforgettounregisterduringonDestroy

5使能被发现

IntentdiscoverableIntent=newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);2discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);3startActivity(discoverableIntent);

6.连接设备:

在应用程序中,想建立两个蓝牙设备之间的连接,必须实现客户端和服务器端的代码(因为任何一个设备都必须可以作为服务端或者客户端)。一个开启服务来监听,一个发起连接请求(使用服务器端设备的MAC地址)。当他们都拥有一个蓝牙套接字在同一RFECOMM信道上的时候,可以认为他们之间已经连接上了。服务端和客户端通过不同的方式或其他们的蓝牙套接字。当一个连接监听到的时候,服务端获取到蓝牙套接字。当客户可打开一个FRCOMM信道给服务器端的时候,客户端获取到蓝牙套接字。

注意:在此过程中,如果两个蓝牙设备还没有配对好的,android系统会通过一个通知或者对话框的形式来通知用户。RFCOMM连接请求会在用户选择之前阻塞。如下图:

7.服务端的连接:

当你想要连接两台设备时,一个必须作为服务端(通过持有一个打开的BluetoothServerSocket),目的是监听外来连接请求,当监听到以后提供一个连接上的BluetoothSocket给客户端,当客户端从BluetoothServerSocket得到BluetoothSocket以后就可以销毁BluetoothServerSocket,除非你还想监听更多的连接请求。

建立服务套接字和监听连接的基本步骤:

首先通过调用listenUsingRfcommWithServiceRecord(String,UUID)方法来获取BluetoothServerSocket对象,参数String代表了该服务的名称,UUID代表了和客户端连接的一个标识(128位格式的字符串ID,相当于PIN码),UUID必须双方匹配才可以建立连接。

其次调用accept()方法来监听可能到来的连接请求,当监听到以后,返回一个连接上的蓝牙套接字BluetoothSocket。

最后,在监听到一个连接以后,需要调用close()方法来关闭监听程序。(一般蓝牙设备之间是点对点的传输)

注意:accept()方法不应该放在主Acitvity里面,因为它是一种阻塞调用(在没有监听到连接请求之前程序就一直停在那里)。解决方法是新建一个线程来管理。例如:

1privateclassAcceptThreadextendsThread{2privatefinalBluetoothServerSocketmmServerSocket;3publicAcceptThread(){4//UseatemporaryobjectthatislaterassignedtommServerSocket,5//becausemmServerSocketisfinal6BluetoothServerSockettmp=null;7try{8//MY_UUIDistheapp'sUUIDstring,alsousedbytheclientcode9tmp=mAdapter.listenUsingRfcommWithServiceRecord(NAME,MY_UUID);10}catch(IOExceptione){}11mmServerSocket=tmp;12}1314publicvoidrun(){15BluetoothSocketsocket=null;16//Keeplisteninguntilexceptionoccursorasocketisreturned17while(true){18try{19socket=mmServerSocket.accept();20}catch(IOExceptione){21break;22}23//Ifaconnectionwasaccepted24if(socket!=null){25//Doworktomanagetheconnection(inaseparatethread)26manageConnectedSocket(socket);27mmServerSocket.close();28break;29}30}31}3233/**Willcancelthelisteningsocket,andcausethethreadtofinish*/34publicvoidcancel(){35try{36mmServerSocket.close();37}catch(IOExceptione){}38}39}

8.客户端的连接:

为了初始化一个与远端设备的连接,需要先获取代表该设备的一个BluetoothDevice对象。通过BluetoothDevice对象来获取BluetoothSocket并初始化连接,具体步骤:

使用BluetoothDevice对象里的方法createRfcommSocketToServiceRecord(UUID)来获取BluetoothSocket。UUID就是匹配码。然后,调用connect()方法来。如果远端设备接收了该连接,他们将在通信过程中共享RFFCOMM信道,并且connect()方法返回。例如:

1privateclassConnectThreadextendsThread{2privatefinalBluetoothSocketmmSocket;3privatefinalBluetoothDevicemmDevice;4publicConnectThread(BluetoothDevicedevice){5//UseatemporaryobjectthatislaterassignedtommSocket,6//becausemmSocketisfinal7BluetoothSockettmp=null;8mmDevice=device;9//GetaBluetoothSockettoconnectwiththegivenBluetoothDevice10try{11//MY_UUIDistheapp'sUUIDstring,alsousedbytheservercode12tmp=device.createRfcommSocketToServiceRecord(MY_UUID);13}catch(IOExceptione){}14mmSocket=tmp;15}161718publicvoidrun(){19//Canceldiscoverybecauseitwillslowdowntheconnection20mAdapter.cancelDiscovery();21try{22//Connectthedevicethroughthesocket.Thiswillblock23//untilitsucceedsorthrowsanexception24mmSocket.connect();25}catch(IOExceptionconnectException){26//Unabletoconnect;closethesocketandgetout27try{28mmSocket.close();29}catch(IOExceptioncloseException){}30return;31}32//Doworktomanagetheconnection(inaseparatethread)33manageConnectedSocket(mmSocket);34}35}

注意:conncet()方法也是阻塞调用,一般建立一个独立的线程中来调用该方法。在设备discover过程中不应该发起连接connect(),这样会明显减慢速度以至于连接失败。且数据传输完成只有调用close()方法来关闭连接,这样可以节省系统内部资源。

9.管理连接(主要涉及数据的传输):

当设备连接上以后,每个设备都拥有各自的BluetoothSocket。现在你就可以实现设备之间数据的共享了。

1>首先通过调用getInputStream()和getOutputStream()方法来获取输入输出流。然后通过调用read(byte[])和write(byte[]).方法来读取或者写数据。

2>实现细节:以为读取和写操作都是阻塞调用,需要建立一个专用现成来管理。

3>

1privateclassConnectedThreadextendsThread{2privatefinalBluetoothSocketmmSocket;3privatefinalInputStreammmInStream;4privatefinalOutputStreammmOutStream;56publicConnectedThread(BluetoothSocketsocket){7mmSocket=socket;8InputStreamtmpIn=null;9OutputStreamtmpOut=null;10//Gettheinputandoutputstreams,usingtempobjectsbecause11//memberstreamsarefinal12try{13tmpIn=socket.getInputStream();14tmpOut=socket.getOutputStream();15}catch(IOExceptione){}16mmInStream=tmpIn;17mmOutStream=tmpOut;18}1920publicvoidrun(){21byte[]buffer=newbyte[1024];//bufferstoreforthestream22intbytes;//bytesreturnedfromread()23//KeeplisteningtotheInputStreamuntilanexceptionoccurs24while(true){25try{26//ReadfromtheInputStream27bytes=mmInStream.read(buffer);28//SendtheobtainedbytestotheUIActivity29mHandler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();30}catch(IOExceptione){31break;32}33}34}3536/*CallthisfromthemainActivitytosenddatatotheremotedevice*/37publicvoidwrite(byte[]bytes){38try{39mmOutStream.write(bytes);40}catch(IOExceptione){}41}4243/*CallthisfromthemainActivitytoshutdowntheconnection*/44publicvoidcancel(){45try{46mmSocket.close();47}catch(IOExceptione){}48}49}

相关推荐