蓝牙编程常用到的几个类 | |
类\接口 | 功能描述 |
BluetoothAdapter (1) | 本地的蓝牙适配器设备 |
BluetoothDevice (2) | 代表一个远程的蓝牙设备 |
BluetoothServerSocket (3) | 监听蓝牙服务的端口 |
BluetoothSocket (4) | 一个双向连接的蓝牙端口socket |
BluetoothClass (5) | 描述了设备通用特性和功能的蓝牙类 |
BluetoothClass.Device | 定义了所有设备类的常量 |
BluetoothClass.Device.Major | 定义了所有主要设备类的常量 |
BluetoothClass.Service | 定义了所有服务类的常量 |
各个类的文档网络上有不少,可以自己去360 的好搜上去搜索,在此不对其进行进一步的说明
UUID的说明 |
UUID(全局唯一标识符,Universally Unique Identifier)格式如下: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX UUID的格式被分成5段,其中中间3段的字符数都是4,第一段是8个字符,最后一段是12个字符,所有UUID实际上是一个8-4-4-4-12的字符串。 UUID相当于Socket的端口,而蓝牙的地址相当于Socket的IP |
实现如何在2个蓝牙之间传递信息 |
创建一个新工程LearnBluetoothSocket实现功能: n 本程既是蓝牙通信的客户端,也是蓝牙通信的服务端。 n 在两部手机上运行本程序,一部当做服务器,另外一部当作客户端 一个的Activity,上面放几个控件。
| ||||||||||||
在AndroidManifest.xml 文件中添加蓝牙的2个权限 <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
| ||||||||||||
MainActivity.java代码 | ||||||||||||
public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener { ListView lvDevices; //用于显示蓝牙设备的空间 EditText etSendInfo; //要发送的消息在此输入 BluetoothAdapter bluetoothAdapter; //蓝牙适配器 private List<String> bluetoothDevices = new ArrayList<String>(); //String数组 用于存储所有搜索到的蓝牙名称和地址 private ArrayAdapter<String> arrayAdapter; //数组适配器用于显示列表 private final UUID MY_UUID = UUID.fromString("1234abcd-12ab-7f25-aafe-59d03c27bae3"); private final String NAME = "Bluetooth_Socket"; //蓝牙服务端的名字,可以自己随便定义一个 private BluetoothSocket clientSocket; //客户端的BluetoothSocket private BluetoothDevice device; // 远程的蓝牙设备 private OutputStream os; //输出流(用于客户端向服务端输出) private AcceptThread acceptThread; //服务端线程类对象 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.activity_main); init(); } private void init() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); lvDevices = (ListView) findViewById(R.id.lvDevices); etSendInfo= (EditText) findViewById(R.id.etSendInfo); //已经配对的蓝牙设备显示出来(根据方法名称就可以知道,其实也叫做绑定好的蓝牙设备) Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { //把扫描到的蓝牙设备添加到 bluetoothDevices(String数组),后面可以用其绑定到Listview视图上 for (BluetoothDevice device : pairedDevices) { bluetoothDevices.add(device.getName() + ":" + device.getAddress() + "\n"); } } //arrayAdapter将所有 arrayList内的数据显示在指定的视图上(使用的是系统内部的View资源) arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, bluetoothDevices); lvDevices.setAdapter(arrayAdapter); lvDevices.setOnItemClickListener(this); //实现客户端代码,响应客户的单击事件 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(receiver, filter); filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(receiver, filter); acceptThread = new AcceptThread(); //创建一个线程用于接收客户端发来的信息 acceptThread.start(); //启动服务 } //实现客户端代码,响应客户的单击事件 @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //获取选择的蓝牙设备名(中间用“:”分开的) String s = arrayAdapter.getItem(position); //由于设备名用“:”分开的,所有要解析出蓝牙地址address String address = s.substring(s.indexOf(":") + 1).trim(); try { //如果蓝牙适配器还在扫描,则停止扫描 需要BLUETOOTH_ADMIN权限 if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } try { if (device == null) { //参数是地址,类似PC中的IP device = bluetoothAdapter.getRemoteDevice(address); } if (clientSocket == null) { clientSocket = device .createRfcommSocketToServiceRecord(MY_UUID); //相当于Socket的端口 //目前还没有配对,直接连接。(正常需要配对,我们把蓝牙配对的工作交给系统手工完成****) clientSocket.connect(); os = clientSocket.getOutputStream(); //获得输出流(由于客户端只向服务点输出文本,所有只要输出流即可) } } catch (Exception e) { // TODO: handle exception } //如果获得服务端的输出流,那么就向服务端写文本信息 if (os != null) { String strInfo=etSendInfo.getText().toString(); if (strInfo.length()<=0){ os.write("发送默认信息---》其他蓝牙设备".getBytes("utf-8")); }else { byte[] midbytes=strInfo.getBytes("utf-8"); //string转换为Byte os.write(midbytes); //return ByteBuffer.wrap(str.getBytes()); } } } catch (Exception e) { // TODO: handle exception } } //服务端线程收到客户端发来的消息会通过本handle进行处理消息。为了监听客户端发来的信息,我们需要创建一个线程 private Handler handler = new Handler(){ public void handleMessage(Message msg) { Toast.makeText(MainActivity.this, "收到其他蓝牙设备发来的消息:"+String.valueOf(msg.obj), Toast.LENGTH_LONG).show(); super.handleMessage(msg); } }; //定义线程服务类 private class AcceptThread extends Thread { private BluetoothServerSocket serverSocket; private BluetoothSocket socket; private InputStream is; //输入流 private OutputStream os; public AcceptThread() { try { serverSocket = bluetoothAdapter .listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { // TODO: handle exception } } //服务线程run中 截取客户端蓝牙发来的消息 public void run() { try { socket = serverSocket.accept(); //如果客户端没有发来请求,程序会一直停留再次等待客户端发来的请求消息,收到客户端请求后才会继续后续代码 is = socket.getInputStream(); os = socket.getOutputStream(); while(true) { byte[] buffer =new byte[128]; //每次只发128个字节 int count = is.read(buffer); //从蓝牙读取数据,客户端没有发生数据过来,则会堵塞在此 //让Hander处理消息 Message msg = new Message(); msg.obj = new String(buffer, 0, count, "utf-8"); handler.sendMessage(msg); } } catch (Exception e) { // TODO: handle exception } } } public void onClick_Search(View view) { setProgressBarIndeterminateVisibility(true); setTitle("正在扫描..."); if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } bluetoothAdapter.startDiscovery(); } //广播接受器,用于搜索系统发来的蓝牙设备扫描信息情况 //定义广播接受器 处理BluetoothDevice的ACTION_FOUND(发现蓝牙设备)、ACTION_DISCOVERY_FINISHED(搜索结束)消息 private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); //当扫描到蓝牙设备 if (BluetoothDevice.ACTION_FOUND.equals(action)) { //获得设备 BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); //判断设备是否已经被绑定 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { bluetoothDevices.add(device.getName() + ":" + device.getAddress() + "\n"); arrayAdapter.notifyDataSetChanged(); } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED .equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle("连接蓝牙设备"); } } }; }
|