什么是蓝牙

蓝牙,是一种支持设备短距离通信(一般10m内)的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换。利用“蓝牙”技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与因特网Internet之间的通信,从而数据传输变得更加迅速高效,为无线通信拓宽道路。蓝牙技术是一种无线数据和语音通信开放的全球规范,它是基于低成本的近距离无线连接,为固定和移动设备建立通信环境的一种特殊的近距离无线技术连接。

开发环境

在PC平台上用JAVA实现蓝牙通信,我们一般要使用BlueCove包。BlueCove下载地址是:

官网地址是:

蓝牙通信的原理

蓝牙技术规定每一对设备之间进行蓝牙通讯时,必须一个为主角色,另一为从角色,才能进行通信,通信时,必须由主端进行查找,发起配对,建链成功后,双方即可收发数据。

蓝牙主端设备发起呼叫,首先是查找,找出周围处于可被查找的蓝牙设备。主端设备找到从端蓝牙设备后,与从端蓝牙设备进行配对,此时需要输入从端设备的PIN码,也有设备不需要输入PIN码。

配对完成后,从端蓝牙设备会记录主端设备的信任信息,此时主端即可向从端设备发起呼叫,已配对的设备在下次呼叫时,不再需要重新配对。

实现方法

在通信中,我们把主端成为客户端,从端称为服务端。这里给出用于蓝牙通信的客户端和服务端实现框架类,具体使用方法,见下一节。

(1)客户端框架类代码:

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Iterator;

import java.util.Set;

import javax.bluetooth.RemoteDevice;

import javax.microedition.io.Connector;

import javax.microedition.io.StreamConnection;

public class BluetoothClient {

private StreamConnection streamConnection;

private OnDiscoverListener onDiscoverListener = null;

private OnClientListener onClientListener = null;

public interface OnClientListener {

void onConnected(InputStream inputStream, OutputStream outputStream);

void onConnectionFailed();

void onDisconnected();

void onClose();

}

public interface OnDiscoverListener {

void onDiscover(RemoteDevice remoteDevice);

}

public BluetoothClient() {

}

public OnDiscoverListener getOnDiscoverListener() {

return onDiscoverListener;

}

public void setOnDiscoverListener(OnDiscoverListener onDiscoverListener) {

this.onDiscoverListener = onDiscoverListener;

}

public OnClientListener getClientListener() {

return onClientListener;

}

public void setClientListener(OnClientListener onClientListener) {

this.onClientListener = onClientListener;

}

public void find() throws IOException, InterruptedException {

Set devicesDiscovered = RemoteDeviceDiscovery.getDevices(); //附近所有的蓝牙设备,必须先执行 runDiscovery

Iterator itr = devicesDiscovered.iterator();

while (itr.hasNext()) { //连接

RemoteDevice remoteDevice = itr.next();

onDiscoverListener.onDiscover(remoteDevice);

}

}

public void startClient(RemoteDevice remoteDevice, String serviceUUID) throws IOException, InterruptedException {

String url = RemoteDeviceDiscovery.searchService(remoteDevice, serviceUUID);

streamConnection = (StreamConnection) Connector.open(url);

if (this.onClientListener != null) {

this.onClientListener.onConnected(streamConnection.openInputStream(), streamConnection.openOutputStream());

}

}

}

设备查找类代码:

import java.io.IOException;

import java.util.HashSet;

import java.util.Set;

import java.util.Vector;

import javax.bluetooth.DataElement;

import javax.bluetooth.DeviceClass;

import javax.bluetooth.DiscoveryAgent;

import javax.bluetooth.DiscoveryListener;

import javax.bluetooth.LocalDevice;

import javax.bluetooth.RemoteDevice;

import javax.bluetooth.ServiceRecord;

import javax.bluetooth.UUID;

public class RemoteDeviceDiscovery {

public final static Set devicesDiscovered = new HashSet();

public final static Vector serviceFound = new Vector();

final static Object serviceSearchCompletedEvent = new Object();

final static Object inquiryCompletedEvent = new Object();

private static DiscoveryListener listener = new DiscoveryListener() {

public void inquiryCompleted(int discType) {

System.out.println("#" + "搜索完成");

synchronized (inquiryCompletedEvent) {

inquiryCompletedEvent.notifyAll();

}

}

@Override

public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {

devicesDiscovered.add(remoteDevice);

try {

System.out.println("#发现设备" + remoteDevice.getFriendlyName(false));

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {

for (int i = 0; i < servRecord.length; i++) {

String url = servRecord[i].getConnectionURL(ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false);

if (url == null) {

continue;

}

serviceFound.add(url);

DataElement serviceName = servRecord[i].getAttributeValue(0x0100);

if (serviceName != null) {

System.out.println("service " + serviceName.getValue() + " found " + url);

} else {

System.out.println("service found " + url);

}

}

System.out.println("#" + "servicesDiscovered");

}

@Override

public void serviceSearchCompleted(int arg0, int arg1) {

System.out.println("#" + "serviceSearchCompleted");

synchronized(serviceSearchCompletedEvent){

serviceSearchCompletedEvent.notifyAll();

}

}

};

private static void findDevices() throws IOException, InterruptedException {

devicesDiscovered.clear();

synchronized (inquiryCompletedEvent) {

LocalDevice ld = LocalDevice.getLocalDevice();

System.out.println("#本机蓝牙名称:" + ld.getFriendlyName());

boolean started = LocalDevice.getLocalDevice().getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC,listener);

if (started) {

System.out.println("#" + "等待搜索完成...");

inquiryCompletedEvent.wait();

LocalDevice.getLocalDevice().getDiscoveryAgent().cancelInquiry(listener);

System.out.println("#发现设备数量:" + devicesDiscovered.size());

}

}

}

public static Set getDevices() throws IOException, InterruptedException {

findDevices();

return devicesDiscovered;

}

public static String searchService(RemoteDevice btDevice, String serviceUUID) throws IOException, InterruptedException {

UUID[] searchUuidSet = new UUID[] { new UUID(serviceUUID, false) };

int[] attrIDs = new int[] {

0x0100 // Service name

};

synchronized(serviceSearchCompletedEvent) {

System.out.println("search services on " + btDevice.getBluetoothAddress() + " " + btDevice.getFriendlyName(false));

LocalDevice.getLocalDevice().getDiscoveryAgent().searchServices(attrIDs, searchUuidSet, btDevice, listener);

serviceSearchCompletedEvent.wait();

}

if (serviceFound.size() > 0) {

return serviceFound.elementAt(0);

} else {

return "";

}

}

}

(2)服务端框架类代码:

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import javax.bluetooth.DiscoveryAgent;

import javax.bluetooth.LocalDevice;

import javax.microedition.io.Connector;

import javax.microedition.io.StreamConnection;

import javax.microedition.io.StreamConnectionNotifier;

public class BluetoothServer implements Runnable {

//本机蓝牙设备

private LocalDevice local = null;

// 流连接

private StreamConnection streamConnection = null;

// 输入流

private InputStream inputStream;

private OutputStream outputStream;

//接入通知

private StreamConnectionNotifier notifier;

//线程池

private final static ExecutorService service = Executors.newCachedThreadPool();

public String serverName;

public String serverUUID;

private OnServerListener mServerListener;

public interface OnServerListener {

void onConnected(InputStream inputStream, OutputStream outputStream);

void onDisconnected();

void onClose();

}

public BluetoothServer(String serverUUID, String serverName) {

this.serverUUID = serverUUID;

this.serverName = serverName;

}

public void start() {

try {

local = LocalDevice.getLocalDevice();

if (!local.setDiscoverable(DiscoveryAgent.GIAC))

System.out.println("请将蓝牙设置为可被发现");

/**

* 作为服务端,被请求

*/

String url = "btspp://localhost:" + serverUUID;// + ";name="+serverName;

notifier = (StreamConnectionNotifier)Connector.open(url);

service.submit(this);

} catch (IOException e) {

System.out.println(e.getMessage());;

}

}

public OnServerListener getServerListener() {

return mServerListener;

}

public void setServerListener(OnServerListener mServerListener) {

this.mServerListener = mServerListener;

}

@Override

public void run() {

try {

streamConnection = notifier.acceptAndOpen(); //阻塞的,等待设备连接

inputStream = streamConnection.openInputStream();

outputStream = streamConnection.openOutputStream();

if (mServerListener != null) {

mServerListener.onConnected(inputStream, outputStream);

}

} catch (IOException e) {

e.printStackTrace();

} catch (Exception e) {

e.printStackTrace();

} finally {

}

}

}

使用方式

本节给出如何使用以上框架类实现蓝牙通信。

服务端蓝牙通信框架类使用代码:

import java.io.InputStream;

import java.io.OutputStream;

public class BluetoothServerTest {

public static void main(String[] argv) {

final String serverName = "Bluetooth Server Test";

final String serverUUID = "1000110100001000800000805F9B34FB"; //根据需要自定义

BluetoothServer server = new BluetoothServer(serverUUID, serverName);

server.setServerListener(new BluetoothServer.OnServerListener() {

@Override

public void onConnected(InputStream inputStream, OutputStream outputStream) {

System.out.printf("Connected");

//添加通信代码

}

@Override

public void onDisconnected() {

}

@Override

public void onClose() {

}

});

server.start();

}

}

客户端通信框架类使用代码:

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.Vector;

import javax.bluetooth.RemoteDevice;

public class BluetoothClientTest {

public static void main(String[] argv) {

final String serverUUID = "1000110100001000800000805F9B34FB"; //需要与服务端相同

BluetoothClient client = new BluetoothClient();

Vector remoteDevices = new Vector<>();

client.setOnDiscoverListener(new BluetoothClient.OnDiscoverListener() {

@Override

public void onDiscover(RemoteDevice remoteDevice) {

remoteDevices.add(remoteDevice);

}

});

client.setClientListener(new BluetoothClient.OnClientListener() {

@Override

public void onConnected(InputStream inputStream, OutputStream outputStream) {

System.out.printf("Connected");

//添加通信代码

}

@Override

public void onConnectionFailed() {

System.out.printf("Connection failed");

}

@Override

public void onDisconnected() {

}

@Override

public void onClose() {

}

});

try {

client.find();

if (remoteDevices.size() > 0) {

client.startClient(remoteDevices.firstElement(), serverUUID);

}

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

更多推荐