您的位置:首页 > 其它

J2ME 蓝牙 串口 连接PC

2008-06-28 16:46 134 查看
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();//这里是全部唤醒

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: