Android蓝牙搜索设备,向其发送数据并接收-刘宇
2016-09-10 15:06
549 查看
通过蓝牙传输数据与Socket类似。在网络中使用Socket和ServerSocket控制客户端和服务端的数据读写。而蓝牙通讯也由客户端和服务端Socket来完成。蓝牙客户端Socket是BluetoothSocket,蓝牙服务端Socket是BluetoothServerSocket。这两个类都在android.bluetooth包中。
无论是BluetoothSocket,还是BluetoothServerSocket,都需要一个UUID(全局唯一标识符,UniversallyUnique
Identifier).格式如下:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
UUID的格式被分成5段,其中中间3段的字符数相同,都是4,第1段是8个字符,最后一段是12个字符。所以UUID实际上是一个8-4-4-4-12的字符串。
UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。
效果图:
搜索设备:
向一个设备发送数据
另一台设备收到了信息,并显示出来了:
——————————————————————————————————————
值得注意的是在建立连接的时候,设备、输出流、接口等变量需要是全局变量,否则方法执行完,就断开连接了。然后进行第二次发送数据就接收不到了。
下面我们就来做这个demo吧,在测试的时候需要手动开启蓝牙,如果需要自动开启蓝牙请查看我上一篇博客。
首先,必不可少的就是添加两个蓝牙权限:
布局文件,由一个搜索按钮和一个listview组成,用于显示搜到的设备
activity_main.xml:
代码文件
MainActivity.java:
By:Mr.Oak
无论是BluetoothSocket,还是BluetoothServerSocket,都需要一个UUID(全局唯一标识符,UniversallyUnique
Identifier).格式如下:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
UUID的格式被分成5段,其中中间3段的字符数相同,都是4,第1段是8个字符,最后一段是12个字符。所以UUID实际上是一个8-4-4-4-12的字符串。
UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。
效果图:
搜索设备:
向一个设备发送数据
另一台设备收到了信息,并显示出来了:
——————————————————————————————————————
值得注意的是在建立连接的时候,设备、输出流、接口等变量需要是全局变量,否则方法执行完,就断开连接了。然后进行第二次发送数据就接收不到了。
下面我们就来做这个demo吧,在测试的时候需要手动开启蓝牙,如果需要自动开启蓝牙请查看我上一篇博客。
首先,必不可少的就是添加两个蓝牙权限:
<uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
布局文件,由一个搜索按钮和一个listview组成,用于显示搜到的设备
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:onClick="onClick_Search" android:text="搜索" /> <ListView android:id="@+id/lvDevices" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>
代码文件
MainActivity.java:
package com.oak.learnbluetoothsocket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; import android.os.Bundle; import android.os.Handler; import android.os.Message; 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.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; public class MainActivity extends Activity implements OnItemClickListener { // 获取到蓝牙适配器 private BluetoothAdapter mBluetoothAdapter; // 用来保存搜索到的设备信息 private List<String> bluetoothDevices = new ArrayList<String>(); // ListView组件 private ListView lvDevices; // ListView的字符串数组适配器 private ArrayAdapter<String> arrayAdapter; // UUID,蓝牙建立链接需要的 private final UUID MY_UUID = UUID .fromString("db764ac8-4b08-7f25-aafe-59d03c27bae3"); // 为其链接创建一个名称 private final String NAME = "Bluetooth_Socket"; // 选中发送数据的蓝牙设备,全局变量,否则连接在方法执行完就结束了 private BluetoothDevice selectDevice; // 获取到选中设备的客户端串口,全局变量,否则连接在方法执行完就结束了 private BluetoothSocket clientSocket; // 获取到向设备写的输出流,全局变量,否则连接在方法执行完就结束了 private OutputStream os; // 服务端利用线程不断接受客户端信息 private AcceptThread thread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取到蓝牙默认的适配器 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 获取到ListView组件 lvDevices = (ListView) findViewById(R.id.lvDevices); // 为listview设置字符换数组适配器 arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, bluetoothDevices); // 为listView绑定适配器 lvDevices.setAdapter(arrayAdapter); // 为listView设置item点击事件侦听 lvDevices.setOnItemClickListener(this); // 用Set集合保持已绑定的设备 Set<BluetoothDevice> devices = mBluetoothAdapter.getBondedDevices(); if (devices.size() > 0) { for (BluetoothDevice bluetoothDevice : devices) { // 保存到arrayList集合中 bluetoothDevices.add(bluetoothDevice.getName() + ":" + bluetoothDevice.getAddress() + "\n"); } } // 因为蓝牙搜索到设备和完成搜索都是通过广播来告诉其他应用的 // 这里注册找到设备和完成搜索广播 IntentFilter filter = new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(receiver, filter); filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); // 实例接收客户端传过来的数据线程 thread = new AcceptThread(); // 线程开始 thread.start(); } public void onClick_Search(View view) { setTitle("正在扫描..."); // 点击搜索周边设备,如果正在搜索,则暂停搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } mBluetoothAdapter.startDiscovery(); } // 注册广播接收者 private BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context arg0, Intent intent) { // 获取到广播的action String action = intent.getAction(); // 判断广播是搜索到设备还是搜索完成 if (action.equals(BluetoothDevice.ACTION_FOUND)) { // 找到设备后获取其设备 BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 判断这个设备是否是之前已经绑定过了,如果是则不需要添加,在程序初始化的时候已经添加了 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { // 设备没有绑定过,则将其保持到arrayList集合中 bluetoothDevices.add(device.getName() + ":" + device.getAddress() + "\n"); // 更新字符串数组适配器,将内容显示在listView中 arrayAdapter.notifyDataSetChanged(); } } else if (action .equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) { setTitle("搜索完成"); } } }; // 点击listView中的设备,传送数据 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 获取到这个设备的信息 String s = arrayAdapter.getItem(position); // 对其进行分割,获取到这个设备的地址 String address = s.substring(s.indexOf(":") + 1).trim(); // 判断当前是否还是正在搜索周边设备,如果是则暂停搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } // 如果选择设备为空则代表还没有选择设备 if (selectDevice == null) { //通过地址获取到该设备 selectDevice = mBluetoothAdapter.getRemoteDevice(address); } // 这里需要try catch一下,以防异常抛出 try { // 判断客户端接口是否为空 if (clientSocket == null) { // 获取到客户端接口 clientSocket = selectDevice .createRfcommSocketToServiceRecord(MY_UUID); // 向服务端发送连接 clientSocket.connect(); // 获取到输出流,向外写数据 os = clientSocket.getOutputStream(); } // 判断是否拿到输出流 if (os != null) { // 需要发送的信息 String text = "成功发送信息"; // 以utf-8的格式发送出去 os.write(text.getBytes("UTF-8")); } // 吐司一下,告诉用户发送成功 Toast.makeText(this, "发送信息成功,请查收", 0).show(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); // 如果发生异常则告诉用户发送失败 Toast.makeText(this, "发送信息失败", 0).show(); } } // 创建handler,因为我们接收是采用线程来接收的,在线程中无法操作UI,所以需要handler Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); // 通过msg传递过来的信息,吐司一下收到的信息 Toast.makeText(MainActivity.this, (String) msg.obj, 0).show(); } }; // 服务端接收信息线程 private class AcceptThread extends Thread { private BluetoothServerSocket serverSocket;// 服务端接口 private BluetoothSocket socket;// 获取到客户端的接口 private InputStream is;// 获取到输入流 private OutputStream os;// 获取到输出流 public AcceptThread() { try { // 通过UUID监听请求,然后获取到对应的服务端接口 serverSocket = mBluetoothAdapter .listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { // TODO: handle exception } } public void run() { try { // 接收其客户端的接口 socket = serverSocket.accept(); // 获取到输入流 is = socket.getInputStream(); // 获取到输出流 os = socket.getOutputStream(); // 无线循环来接收数据 while (true) { // 创建一个128字节的缓冲 byte[] buffer = new byte[128]; // 每次读取128字节,并保存其读取的角标 int count = is.read(buffer); // 创建Message类,向handler发送数据 Message msg = new Message(); // 发送一个String的数据,让他向上转型为obj类型 msg.obj = new String(buffer, 0, count, "utf-8"); // 发送数据 handler.sendMessage(msg); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } }到这里,一个简单的蓝牙发送数据和接收数据就完成了,更多android方面的技术尽请期待。
By:Mr.Oak
相关文章推荐
- Android蓝牙搜索设备,向其发送数据并接收
- Android 低功耗蓝牙的多设备连接与数据接收,简单实现
- android 蓝牙编程重点---如何发送和接收16进制数据
- Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(一)
- android 蓝牙编程重点---如何发送和接收16进制数据
- android 蓝牙编程重点---如何发送和接收16进制数据
- android 蓝牙编程重点---如何发送和接收16进制数据
- android 蓝牙编程重点---如何发送和接收16进制数据
- android 蓝牙编程重点---如何发送和接收16进制数据
- Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(二)
- Android蓝牙搜索设备-刘宇
- Android之发送与接收JSON数据
- Android Socket 发送与接收数据问题: 发送后的数据接收到总是粘包
- Android下发送和接收OBD数据
- java后台接收android客户端通过http方式发送的数据
- android蓝牙(二)——接收数据
- android蓝牙(二)——接收数据
- android网络通信 接收和发送数据详解
- iOS学习,蓝牙,iOS设备模拟BLE发送数据
- Android蓝牙开发之数据窜位和数据接收错误以及重组字节数据