J2ME 蓝牙 串口 连接PC
来源:互联网 发布:java json转字符串 编辑:程序博客网 时间:2024/05/02 06:06
package BTClient;//这是别人的代码 具体在那拷贝的 我忘记了,这不是我的原创,只是我学习半个月 才搞懂的 发上来 大家可以参考一下//对象主要调用两个方法 搜索 发送import java.io.*;import java.util.*;import javax.bluetooth.*;import javax.bluetooth.UUID;import javax.microedition.io.*; ////////////////////////////////////////////////////////////////////////////////////////////////////public class BTClient implements DiscoveryListener, Runnable { //接口 DiscoveryListener public static final String uuidString = "0123456789ABCDEF0123456789ABCDEF"; public static UUID uuid; private LocalDevice localDevice;// 本地设备实例 String localBTAddress;// 本地蓝牙地址 String localBTName;// 蓝牙名称 DiscoveryAgent discoveryAgent;// 发现代理 Thread th; Thread readWorkTh; Thread writeWorkTh; StreamConnection conn; boolean exitFlag; boolean BTReady;//状态标记 DataInputStream in; DataOutputStream out; String sendText = ""; Hashtable remoteDevices = new Hashtable();// 存储找到的远程设备 哈什表java.util.Hashtable String url = null; ServiceRecord serviceRecord; //////////////////////////////////////////////////////////////////////////////////////////////////// public BTClient() { th = new Thread(this); th.start(); } //////////////////////////////////////////////////////////////////////////////////////////////////// public void run() { if (!initBT()) { return; //返回 } try { // 等待启动服务搜索,看清下面的search()搜索这里先暂停它 synchronized (this) { //代码块中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁才能执行! try { wait();//会释放这个锁,让其它线程有机会运行。 } catch (InterruptedException e) { e.printStackTrace(); } }//// if (exitFlag) return;//返回 search(); ///////////////////////////// ///////////////////////////// // 等待URL准备好 synchronized (this) { //等到被唤醒后 再继续运行 try { wait();//会释放这个锁,让其它线程有机会运行。 } catch (InterruptedException e) { e.printStackTrace(); } }//// if (exitFlag) return;//返回 conn = (StreamConnection) Connector.open(url); in = conn.openDataInputStream(); out = conn.openDataOutputStream(); readWorkTh = new ReadWorkThread(); readWorkTh.start(); writeWorkTh = new WriteWorkThread(); writeWorkTh.start(); BTReady = true; } catch (IOException e) { return;//返回 } catch (SecurityException e) { return;//返回 } th = null;//Thread为空 } //////////////////////////////////////////////////////////////////////////////////////////////////// public boolean initBT() { //初始化蓝牙-文文风 这很简单 初始化就可以了主要是地址! boolean success = false; try { uuid = new UUID(uuidString, false);// 我们的UUID // 取得本地设备实例 localDevice = LocalDevice.getLocalDevice(); // 记录蓝牙地址 localBTAddress = localDevice.getBluetoothAddress(); // 记录蓝牙名称 localBTName = localDevice.getFriendlyName(); localDevice.setDiscoverable(DiscoveryAgent.GIAC); // 取得蓝牙代理 discoveryAgent = localDevice.getDiscoveryAgent(); success = true; } catch (Exception e) { System.err.println("初始化蓝牙设备失败:" + e); } return success; } //////////////////////////////////////////////////////////////////////////////////////////////////// public void search() {// 搜索设备,搜索服务 try { //remoteDevices哈什表 // 清除remoteDevices remoteDevices.clear(); // 将缓存的和已知的蓝牙设备加入cacheDevices++preDevices==remoteDevices RemoteDevice[] cacheDevices = discoveryAgent.retrieveDevices(DiscoveryAgent.CACHED); // class RemoteDevice//缓存的 if (cacheDevices != null) { for (int i = 0; i < cacheDevices.length; i++) { remoteDevices.put(cacheDevices[i].getBluetoothAddress(), cacheDevices[i]); //哈什表 } } RemoteDevice[] preDevices = discoveryAgent.retrieveDevices(DiscoveryAgent.PREKNOWN); // class RemoteDevice//已知的 if (preDevices != null) { for (int i = 0; i < preDevices.length; i++) { remoteDevices.put(cacheDevices[i].getBluetoothAddress(),cacheDevices[i]); //哈什表 这里好像写错了 应该是preDevices } } // 在缓存的和已知的设备上查询“服务”,函数定义在下面 searchServices(remoteDevices); if (serviceRecord != null)// 找到返回 return; // 开始搜索设备 discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);//这里的this是指本类.当然我们要在本类实现DiscoveryListener接口. // 在搜索到的设备上查询服务 searchServices(remoteDevices);//去下面看看这个函数的实现 remoteDevices.clear(); } catch (BluetoothStateException e) { e.printStackTrace(); } if (serviceRecord != null) { notify(); //叫醒谁??应该是下一个 就是上面等待URL的那个块,运行到这里 数据已经获取了 可以连接了 } else { } } //////////////////////////////////////////////////////////////////////////////////////////////////// private void searchServices(Hashtable remotes) throws BluetoothStateException //根据hash表查询设备 {// 搜索服务 // 创建我们感兴趣的UUID数组,我这里只搜索可以提供-蓝牙串口-的设备 UUID[] UUIDs = new UUID[1]; //UUIDs[1] = new UUID(uuidString, false);// 我们的UUID UUIDs[0] = new UUID(0x0003);// 必须支持RFCOMM // 取出每一个设备查询 for (Enumeration e = remotes.keys(); e.hasMoreElements();) { String key = (String) e.nextElement(); //我们用到了哈什表 这里要转换为remotes类型 RemoteDevice remoteDevice = (RemoteDevice) remotes.get(key); //看清楚了 这是remoteDevice 不是remoteDevices!!!!讨厌 // 查询服务-使用发现代理 到这里不用管它了 它会自动调用回调函数的 可以去休息了 discoveryAgent.searchServices(null, UUIDs, remoteDevice, this); }//这是循环尾 到这里了 } //////////////////////////////////////////////////////////////////////////////////////////////////// public void deviceDiscovered(RemoteDevice device, DeviceClass cod) { //如果搜索到了有新设备,它会调用deviceDiscoverd()方法接收! // 记录找到的设备 remoteDevices.put(device.getBluetoothAddress(), device); } //哈什表 //发现服务 //////////////////////////////////////////////////////////////////////////////////////////////////// public void servicesDiscovered(int transID, ServiceRecord[] servRecord) { // 发现感兴趣的服务,这里直接使用第一个 if (servRecord == null || servRecord.length == 0) { url = null; serviceRecord = null; return; } // 取得感兴趣的连接URL,这里直接使用第一个,其它的不要了,我用直接写入的。不要学我啊 //给大家看个例子 btspp://00195D0F4245:3;authenticate=false;encrypt=false;master=false //把地址改一下就可以用了,用不了 自己看参数呀 通道数我的机器有 2 3 7 你的电脑也许不是这些 serviceRecord = servRecord[0]; //服务记录是个接口 url = serviceRecord.getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); } //////////////////////////////////////////////////////////////////////////////////////////////////// public void inquiryCompleted(int discType) { //设备查询完成 try { searchServices(remoteDevices); //开始查询服务了, } catch (BluetoothStateException e) { e.printStackTrace(); } remoteDevices.clear();//这里清空哈什表,释放资源,以后不用了,其实不用也是可以的。 } //////////////////////////////////////////////////////////////////////////////////////////////////// public void serviceSearchCompleted(int transID, int respCode) {//服务查询完成 synchronized (this) { //同步 notifyAll(); //服务查询完成后 会叫醒所有线程。 } } //////////////////////////////////////////////////////////////////////////////////////////////////// public void close() { try { exitFlag = true; synchronized (this) { notify(); //这也有唤醒 但是不知道具体做什么用的?请教一下 } if (writeWorkTh != null) { synchronized (writeWorkTh) { writeWorkTh.notify(); //这也有唤醒,请教! } } if (in != null) { in.close(); } if (out != null) { out.close(); } if (conn != null) conn.close(); if (readWorkTh != null) { readWorkTh.join(); } if (writeWorkTh != null) writeWorkTh.join(); if (th != null) th.join(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } //////////////////////////////////////////////////////////////////////////////////////////////////// public void send(String str) { ////发送信息 外部对象会调用此方法 if (writeWorkTh == null) return; sendText = str; synchronized (writeWorkTh) { writeWorkTh.notify(); //指定线程唤醒 别睡了 干活了 } } //////////////////////////////////////////////////////////////////////////////////////////////////// class ReadWorkThread extends Thread { public void run() { try { while (!exitFlag) { String str = in.readUTF(); if (str != null) { } } } catch (IOException e) { } } } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// class WriteWorkThread extends Thread { public void run() { try { while (!exitFlag) { synchronized (this) {//// try { wait();//这等待一下 } catch (InterruptedException e) { e.printStackTrace(); } if (exitFlag)// 可能因为关闭操作被打断 break; if (sendText != null) out.writeUTF(sendText); }//// } } catch (IOException e) { } } } //////////////////////////////////////////////////////////////////////////////////////////////////// public void startSearch() { ////搜索 同样 外部对象会调用此方法 synchronized (this) { notifyAll();//这里是全部唤醒 } }}