赞
踩
通常情况下,我们对蓝牙的操作主要有:开启和关闭蓝牙、搜索周边设备、能被周边设备所发现、获取配对设备、蓝牙设备间的数据传输。
蓝牙设备主要分为两部分,一部分为本地设备,另一部分为远程设备。
它所包含的方法和BluetoothAdapter一样,不再累述。
- // 获取本地的蓝牙适配器实例
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- if(adapter!=null)
- {
- if(!adapter.isEnabled())
- {
- //通过这个方法来请求打开我们的蓝牙设备
- Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- startActivity(intent);
- }
- }
- else
- {
- System.out.println("本地设备驱动异常!");
- }
对于Android查找发现蓝牙设备使用BluetoothAdapter类的startDiscovery()方法就可以执行一个异步方式获取周边的蓝牙设备,因为是一个异步的方法所以我们不需要考虑线程被阻塞问题,整个过程大约需要12秒时间,这时我们可以注册一个 BroadcastReceiver 对象来接收查找到的蓝牙设备信息,我们通过Filter来过滤ACTION_FOUND这个 Intent动作以获取每个远程设备的详细信息,通过Intent字段EXTRA_DEVICE 和 EXTRA_CLASS可以获得包含了每个BluetoothDevice 对象和对象的该设备类型 BluetoothClass。
实现一个自己的BroadCastReceiver类,并注册这个类。
- private class BluetoothReciever 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)) {
- BluetoothDevice device = intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- System.out.println(device.getAddress());
- }
- }
- }
- IntentFilter intentFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
- bluetoothReceive = new BluetoothReciever();
- registerReceiver(bluetoothReceive, intentFilter);
因为在注册一个Receiver后,程序并不知道该何时去回收它,所以需要我们自己重写Activity类的onDestroy()方法。
- @Override
- protected void onDestroy() {
- // TODO Auto-generated method stub
- unregisterReceiver(bluetoothReceive);
- super.onDestroy();
- }
如果需要用户确认操作,不需要获取底层蓝牙服务实例,可以通过一个Intent来传递ACTION_REQUEST_DISCOVERABLE参数, 这里通过startActivity来请求开启。
- Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
- //50这个参数代表的是蓝牙设备能在多少秒内被发现
-
- discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 50);
-
- startActivity(discoverableIntent);
配对操作呢,一般都是发现设备后,由我们人工来进行选择后系统自动去配对。我们可以通过下面的方法来获得配对的设备:
- //通过getBondedDevices方法来获取已经与本设备配对的设备
- Set<BluetoothDevice> device= adapter.getBondedDevices();
- if(device.size()>0)
- {
- for(Iterator iterator=device.iterator();iterator.hasNext();)
- {
- BluetoothDevice bluetoothDevice=(BluetoothDevice)iterator.next();
- System.out.println(bluetoothDevice.getAddress());
- }
- }
在看过前面的启动、发现/搜索、配对这些操作后,下面来说说数据传输的问题。
在Android系统中,蓝牙设备间的数据传输问题和我们在PC上的网络编程颇为类似,有一端作为Server端监听Client端的连接请求,在二者建立了连接后,就可以使用普通的数据传输方式进行数据交换操作了。在这个过程中,我需要使用到BluetoothServerSocket和BluetoothSocket两个类来建立Server端和Client端,还需要使用到一些关于流(Stream)的知识。
可以看到,Accept方法是一个阻塞方法,所以在进行开发的时候,一般都需要用到多线程的知识。JAVA的多线程知识,可以在JAVA的JDK帮助文档中查看,就单纯的应用来说还是比较简单的。
在了解了这两个类后,可以着手来建立我们自己的Server端和Client端了。
如果一个设备需要和两个或多个设备连接时,就需要作为一个server来传输,服务器端套接字在接受(accepted) 一个客户发来的BluetoothSocket连接请求时作出相应的响应。服务器socket将监听进入的连接请求,一旦连接被接受,将产生一个BluetoothSocket。
使用BluetoothAdapter类的listenUsingRfcommWithServiceRecord方法来新建一个ServerSocket。在listenUsingRfcommWithServiceRecord中有一个参数叫做UUID,UUID(Universally Unique Identifier)是一个128位的字符串ID,被用于唯一标识我们的蓝牙服务。你可以使用web上的任何一款UUID产生器为你的程序获取一个UUID,然后使用fromString(String)初始化一个UUID。
使用ServerSocket实例的accept方法进行监听,当监听到带有我们初始化的UUID参数的连接请求后作出响应,连接成功后返回一个BluetoothSocket对象。连接完成后,调用close方法关闭该Socket监听。
- // Bluetooth的ServerSocket包装类
- class BluetoothServer {
- public BluetoothServer() throws IOException {
- }
-
- // 要建立一个ServerSocket对象,需要使用adapter.listenUsingRfcommWithServiceRecord方法
- // UUID可以在网上去申请
- private BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myServerSocket",
- UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));
- BluetoothSocket socket = serverSocket.accept();
-
- void m() throws IOException {
- if (socket != null) {
- InputStream inputStream = socket.getInputStream();
- int read = -1;
- final byte[] bytes = new byte[1024];
- for (; (read = inputStream.read(bytes)) > -1;) {
- final int count = read;
- Thread _start = new Thread(new Runnable() {
-
- @Override
- public void run() {
- // TODO Auto-generated method stub
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < count; i++) {
- if (i > 0) {
- sb.append(' ');
- }
- String _s = Integer.toHexString(bytes[i] & 0xFF);
- if (_s.length() < 2) {
- sb.append('0');
- }
- sb.append(_s);
- }
- System.out.println(sb.toString());
- }
- });
- _start.start();
- }
- }
- }
- }
创建一个Client端,首先需要我们使用BluetoothDevice的实例的createRfcommSocketToServiceRecord方法来创建一个BluetoothSocket实例。在创建的时候,需要给createRfcommSocketToServiceRecord方法传入我们服务端的UUID值。然后使用BluetoothSocket实例的Connect方法对Server端进行连接请求,当连接成功后,Client端和Server端的传输通道就被打开。最后在连接完成后使用该实例的close方法来关闭这个连接。
- class BluetoothClient {
- BluetoothDevice device = null;
-
- //通过构造函数来传入一个BluetoothDevice实例
- public BluetoothClient(BluetoothDevice device) {
- this.device = device;
- }
- BluetoothSocket socket = null;
- void connetServer() throws IOException {
- Thread _clientThread = new Thread(new Runnable() {
- public void run() {
- try {
- //通过BluetoothDevice实例的createRfcommSocketToServiceRecord方法可以返回一个带有UUID的BluetoothSocket实例
- socket = device.createRfcommSocketToServiceRecord(UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- try {
- socket.connect();
- } catch (IOException e1) {
- // TODO Auto-generated catch block
- e1.printStackTrace();
- }
- if (socket != null) {
- try {
- socket.close();
- } catch (Exception e) {
- // TODO: handle exception
- }
- }
- }
- });
- _clientThread.start();
- }
- }
getInputStream()——获得一个可读的流,该流在连接不成功的情况下依旧可以获得,但是对其操作的话就会报IOException的异常。需要从外部获取的数据都从该流中获取。
getOutputStrem()——获得一个可写的流,该流在连接不成功的情况下依旧可以获得,但是对其操作的话就会报IOException的异常。需要往外部传输的数据都可以写到该流中传输出去。
数据传输的大致流程如下:
还要补充一点,由于蓝牙设备是系统设备,所以需要有相应的权限支持。在AndroidManifest.xml文件中添加上权限。
- <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
- <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
常用类说明
首先调用静态方法getDefaultAdapter()获取蓝牙适配器bluetoothadapter, 如果返回为空,则表明此设备不支持蓝牙。
代表本地蓝牙适配器。BluetoothAdapter 让你进行基础的蓝牙操作,比如初始化搜索设备,对已配对设备进行检索,根据一直MAC地址 实例化一个 BluetoothDevice,建立一个监听其他设备连接请求的 BluetoothServerSocket,启动对蓝牙LE设备的搜索。
这是使用蓝牙的起点。获得了本地适配器后,可以调用getBondedDevices()获得代表配对设备的 BluetoothDevice 对象 startDiscovery()启动搜索蓝牙设备。或者建立一个BluetoothServerSocket , 调用listenUsingRfcommWithServiceRecord(String, UUID)来监听接入请求 startLeScan(LeScanCallback) 搜索Bluetooth LE 设备
相应的源码 BluetoothAdapter.java (frameworks/base/core/java/android/bluetooth)
- /**
- * Get a handle to the default local Bluetooth adapter.
- * <p>Currently Android only supports one Bluetooth adapter, but the API
- * could be extended to support more. This will always return the default
- * adapter.
- * @return the default local adapter, or null if Bluetooth is not supported
- * on this hardware platform
- */
-
- public static synchronized BluetoothAdapter getDefaultAdapter() {
-
- if (sAdapter == null) {
-
- IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
-
- if (b != null) {
-
- IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
-
- sAdapter = new BluetoothAdapter(managerService);
-
- } else {
-
- Log.e(TAG, "Bluetooth binder is null");
-
- }
-
- }
-
- return sAdapter;
-
- }
一个连接上或连接中的socket 使用BluetoothServerSocket来创建一个监听的服务socket。 对于服务端,当BluetoothServerSocket接收了一个连接,会返回一个新的BluetoothSocket来管理这个连接。 对于客户端,使用一个单独的BluetoothSocket来初始化一个发送连接并管理这个连接。 蓝牙socket最普通的模式是RFCOMM,这是Android API支持的模式。 RFCOMM面向连接,使用流传输。也称为Serial Port Profile (SPP)
建立一个到已知蓝牙设备的BluetoothSocket,使用BluetoothDevice.createRfcommSocketToServiceRecord() 然后调用connect()来连接这个远程设备。调用这个方法会阻塞程序直到建立连接或者连接失败。 一旦socket连接上,不论初始化为客户端或者服务端,调用getInputStream()和getOutputStream()打开IO流来分别接收 输入流和输出流对象。流对象自动连接到socket
BluetoothSocket是线程安全的。特别的是,close()会立刻关闭进行中的操作并关闭socket。
需要 BLUETOOTH 相关权限
一个监听的蓝牙socket 在服务端,使用BluetoothServerSocket来建立一个监听的服务socket。
使用BluetoothAdapter.listenUsingRfcommWithServiceRecord()来建立一个监听接入连接的BluetoothServerSocket 然后调用accept()监听连接请求。这个调用会阻塞,直到建立连接,并返回一个管理连接的BluetoothSocket 获得了 BluetoothSocket,并且不再需要连接,可以调用close()来关闭掉 BluetoothServerSocket 关闭 BluetoothServerSocket 并不会关闭返回的 BluetoothSocket
BluetoothServerSocket 是线程安全的,特别的是,close()会立刻关闭进行中的操作并关闭服务 socket。
代表一个远程蓝牙设备。BluetoothDevice 能让你与其他设备建立连接,或者查询设备信息,比如名称,地址,类别和连接状态等。 这是蓝牙硬件地址的简单包装类。找个类的对象都说不可变的。这个类的操作会在远程蓝牙硬件地址上体现。
通过一个已知的MAC地址(可用BluetoothDevice来发现),或是通过BluetoothAdapter.getBondedDevices()返回的已连接设备 调用BluetoothAdapter.getRemoteDevice(String)来获得一个 BluetoothDevice。 然后就可以打开 BluetoothSocket 来与远程设备建立连接,调用createRfcommSocketToServiceRecord(UUID)
搜索其他蓝牙设备
检索匹配到的蓝牙设备
建立RFCOMM频道
通过发现服务来连接其他设备
管理多个连接
使用蓝牙通信前,确定设备支持蓝牙,并将蓝牙打开
1.获取 BluetoothAdapter 使用静态方法BluetoothAdapter.getDefaultAdapter()获取机器的蓝牙适配器;若返回null,则表示机器不支持蓝牙
- BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
-
- if (mBluetoothAdapter == null) {
-
- // Device does not support Bluetooth
-
- }
2.激活蓝牙 检查蓝牙是否已经打开;若没打开,可以使用下面的方法打开蓝牙
- if (!mBluetoothAdapter.isEnabled()) {
-
- Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
-
- startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
-
- }
会弹出一个对话框,请求用户打开蓝牙。如果成功打开,activity 的 onActivityResult() 会收到 RESULT_OK , 如果未打开, 则收到 RESULT_CANCELED
可以让应用监听 ACTION_STATE_CHANGED ,当蓝牙状态改变时会发出这个广播。这个广播包括蓝牙原先状态和现在状态,分别装在 EXTRA_PREVIOUS_STATE 和 EXTRA_STATE 里。 状态可能是 STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, 和 STATE_OFF
使用 BluetoothAdapter,可以寻找远程蓝牙设备或检索匹配设备
搜索设备是搜索本地区域已开启的蓝牙设备程序。蓝牙设备有可见模式和不可见模式。如果一个设备是可发现的,它会相应搜索请求并 返回一些信息,比如设备名,类别,独立的MAC地址。利用这些信息,设备可以初始化一个到被发现设备的连接。
第一次与其他设备连接建立,会自动弹出一个配对请求给用户。成功配对后,设备的基本信息会被保存下来,并且可以被蓝牙API调用。 使用已知的远程设备的MAC地址,可以在不搜索设备的情况下建立连接。
配对和连接是不同的。配对表示两个设备知道对方的存在,有相互认证的key,能够与对方建立加密的连接。 连接意味着设备目前共享一个RFCOMM频道,并能相互发送数据。目前android蓝牙API要求设备先配对,再进行连接。
注意:Android设备并不是默认蓝牙可见的。用户可以在系统设置中让设备蓝牙可被搜索到。
搜索设备前,可以调用getBondedDevices()检索一下已配对的设备。这会返回配对设备的BluetoothDevices集合。 例如,你可以检索配对设备并把每个设备信息存入 ArrayAdapter :
- Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
-
- // If there are paired devices
-
- if (pairedDevices.size() > 0) {
-
- // Loop through paired devices
-
- for (BluetoothDevice device : pairedDevices) {
-
- // Add the name and address to an array adapter to show in a ListView
-
- mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
-
- }
-
- }
只需要MAC地址,就能够用BluetoothDevice对象建立连接。
Discovering devices 搜索设备
调用startDiscovery()搜索设备。这个异步进程会立刻返回是否启动成功的boolean值。搜索进程通常是inquiry scan进行12秒, 接下来是每个发现设备的 page scan 。
你的应用必须注册一个广播接收器来监听 ACTION_FOUND ,接收发现的每个设备的信息。每发现一个设备,系统会发送 ACTION_FOUND 这个 Intent 带有 EXTRA_DEVICE 和 EXTRA_CLASS,里面分别包含 BluetoothDevice 和一个 BluetoothClass 例如,注册一个广播接收器来监听被发现设备:
- // Create a BroadcastReceiver for ACTION_FOUND
-
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
- public void onReceive(Context context, Intent intent) {
-
- String action = intent.getAction();
-
- // When discovery finds a device
-
- if (BluetoothDevice.ACTION_FOUND.equals(action)) {
-
- // Get the BluetoothDevice object from the Intent
-
- BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- // Add the name and address to an array adapter to show in a ListView
-
- mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
-
- }
-
- }
-
- };
-
- // Register the BroadcastReceiver
-
- IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
-
- registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
警告:搜索设备对于蓝牙适配器来说是一个耗费资源的进程。发现目标设备后,一定要在连接前调用cancelDiscovery()停止搜索。 不要在与设备连接时启动搜索。搜索设备会减小连接的带宽。
Enabling discoverability 激活设备蓝牙可见
如果想让本地设备对其他设备蓝牙可见,调用startActivityForResult(Intent, int),传入ACTION_REQUEST_DISCOVERABLE 这会请求激活系统设置。默认激活120秒。可以用EXTRA_DISCOVERABLE_DURATION来请求别的时间。应用可设最长时间是3600秒。 0表示设备永远可见。在0~3600外的数字会被设置为120秒。比如,将时间设置为300秒:
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
会显示一个对话框来请求用户。如果用户点击“Yes”,设备会变得蓝牙可见。activity会收到onActivityResult()回调,并传回 设置蓝牙可见时间的数值。如果用户点击“No”或出现错误,返回代码会是 RESULT_CANCELED 。
注意:如果设备未开启蓝牙,将设备蓝牙设为可见会自动打开蓝牙
设备会在允许时间内保持沉默。可以注册广播接收器来监听 ACTION_SCAN_MODE_CHANGED 。这个Intent会带着 EXTRA_SCAN_MODE 和 EXTRA_PREVIOUS_SCAN_MODE,分别是新的和旧的状态。可能的状态值会是: SCAN_MODE_CONNECTABLE_DISCOVERABLE, SCAN_MODE_CONNECTABLE, 或 SCAN_MODE_NONE
如果要与远程设备连接,可以不激活设备可见。当应用想要建立服务socket获取接入时,必须打开设备可见。因为远程设备必须要发现 本地设备来建立连接。
服务端设备和客户端设备以不同的方式获取 BluetoothSocket。连接建立时,服务端获取一个 BluetoothSocket。 客户端打开一个RFCOMM时会得到 BluetoothSocket 。
Connecting as a server 在连接中作为服务端
当你要连接2个设备,其中一个必须作为服务器并持有一个打开的 BluetoothServerSocket 。服务socket的目的是获取接入请求并 给已连上设备一个 BluetoothSocket 。当从 BluetoothServerSocket 获取到 BluetoothSocket,BluetoothServerSocket 可以关闭掉,除非你想接入更多连接。
调用listenUsingRfcommWithServiceRecord(String, UUID)来获得一个 BluetoothServerSocket
调用accept() 来监听接入请求
如果不需要接入更多连接,调用close()
accept()不应该在UI线程中调用,因为它是阻塞式的。通常在应用中启动新的线程来操作BluetoothServerSocket 或 BluetoothSocket 在另一个线程调用BluetoothServerSocket (或 BluetoothSocket)的close()能跳出阻塞,并立刻返回
例子:
- private class AcceptThread extends Thread {
-
- private final BluetoothServerSocket mmServerSocket;
-
- public AcceptThread() {
-
- // Use a temporary object that is later assigned to mmServerSocket,
-
- // because mmServerSocket is final
-
- BluetoothServerSocket tmp = null;
-
- try {
-
- // MY_UUID is the app's UUID string, also used by the client code
-
- tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
-
- } catch (IOException e) { }
-
- mmServerSocket = tmp;
-
- }
-
- public void run() {
-
- BluetoothSocket socket = null;
-
- // Keep listening until exception occurs or a socket is returned
-
- while (true) {
-
- try {
-
- socket = mmServerSocket.accept();
-
- } catch (IOException e) {
-
- break;
-
- }
-
- // If a connection was accepted
-
- if (socket != null) {
-
- // Do work to manage the connection (in a separate thread)
-
- manageConnectedSocket(socket);
-
- mmServerSocket.close();
-
- break;
-
- }
-
- }
-
- }
-
- /** Will cancel the listening socket, and cause the thread to finish */
-
- public void cancel() {
-
- try {
-
- mmServerSocket.close();
-
- } catch (IOException e) { }
-
- }
-
- }
上面这个例子只需要一个接入连接。连接建立并获得 BluetoothSocket 后,应用将这个 BluetoothSocket 发给单独的线程来处理 并关闭 BluetoothServerSocket 结束循环。
当accept()返回 BluetoothSocket,这个socket已经是连接上的了。因此不必调用connect()(客户端也一样)
manageConnectedSocket()是一个虚构的方法,用来初始化传输数据的线程,在连接管理中来讨论它
监听接入连接结束后通常要立刻关闭 BluetoothServerSocket 。这个例子中,获取 BluetoothSocket 后立刻调用了close()。 可以在线程中写一个公共方法来关闭私有的 BluetoothSocket 。当需要停止监听服务socket时可以使用这个方法。
Connecting as a client 在连接中作为客户端
与远程设备(服务端)建立连接,先获取一个代表远程设备的 BluetoothDevice 对象。必须使用 BluetoothDevice 来获取 BluetoothSocket 并初始化连接。
基本流程:
调用BluetoothDevice的createRfcommSocketToServiceRecord(UUID)获取BluetoothSocket
调用connect()来初始化连接
注意:在调用connect()时必须确保设备不在搜索进行中。在搜索设备时,连接尝试会变慢并且很容易失败。
- private class ConnectThread extends Thread {
-
- private final BluetoothSocket mmSocket;
-
- private final BluetoothDevice mmDevice;
-
- public ConnectThread(BluetoothDevice device) {
-
- // Use a temporary object that is later assigned to mmSocket,
-
- // because mmSocket is final
-
- BluetoothSocket tmp = null;
-
- mmDevice = device;
-
- // Get a BluetoothSocket to connect with the given BluetoothDevice
-
- try {
-
- // MY_UUID is the app's UUID string, also used by the server code
-
- tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
-
- } catch (IOException e) { }
-
- mmSocket = tmp;
-
- }
-
- public void run() {
-
- // Cancel discovery because it will slow down the connection
-
- mBluetoothAdapter.cancelDiscovery();
-
- try {
-
- // Connect the device through the socket. This will block
-
- // until it succeeds or throws an exception
-
- mmSocket.connect();
-
- } catch (IOException connectException) {
-
- // Unable to connect; close the socket and get out
-
- try {
-
- mmSocket.close();
-
- } catch (IOException closeException) { }
-
- return;
-
- }
-
- // Do work to manage the connection (in a separate thread)
-
- manageConnectedSocket(mmSocket);
-
- }
-
- /** Will cancel an in-progress connection, and close the socket */
-
- public void cancel() {
-
- try {
-
- mmSocket.close();
-
- } catch (IOException e) { }
-
- }
-
- }
建立连接前,调用cancelDiscovery()。
manageConnectedSocket()是一个虚构的方法,在连接管理中讨论它。 使用完BluetoothSocket,一定要调用close()来结束
成功连接2个或更多的设备后,每个设备有一个 BluetoothSocket 。设备直接可以共享数据。使用BluetoothSocket传输任意数据
获取处理传输的 InputStream 和 OutputStream,分别调用 getInputStream() 和 getOutputStream() 调用read(byte[]) 和 write(byte[]) 来读写数据
线程的主循环中应该用于专门从InputStream中读数据。线程中要有专门的public方法来写数据到OutputStream
- private class ConnectedThread extends Thread {
-
- private final BluetoothSocket mmSocket;
-
- private final InputStream mmInStream;
-
- private final OutputStream mmOutStream;
-
- 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) { }
-
- mmInStream = tmpIn;
-
- mmOutStream = 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 = mmInStream.read(buffer);
-
- // Send the obtained bytes to the UI activity
-
- mHandler.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);
-
- } catch (IOException e) { }
-
- }
-
- /* Call this from the main activity to shutdown the connection */
-
- public void cancel() {
-
- try {
-
- mmSocket.close();
-
- } catch (IOException e) { }
-
- }
-
- }
构造方法需要数据流,一旦执行,线程会等InputStream中传来的数据。当read(byte[])返回数据流,通过handler将数据送往 主activity。然后等待数据流中更多的字节
向外发送数据调用write()
线程的cancel()方法很重要。完成了蓝牙连接的所有操作后,应当cancel掉
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。