ありがとう:(1)PCBluetooth開発 https://www.cnblogs.com/zeussbook/p/12827479.html
https://blog.csdn.net/svizzera/article/details/77434917
(2)データ読み取りの障害を解決する https://blog.csdn.net/clliu_hust/article/details/80874272
1.Bluetoothプロセス
BluetoothクライアントSocketとSokcetのプロセスは同じですが、パラメーターが異なります。次のように:
1。クライアントBluetoothSokcetを作成します
2.接続を作成します
3.データの読み取りと書き込み
4.閉じる
2つ目は、jarパッケージをインポートすることです。
サードパーティのBluetoothbluecove.jarパッケージをインポートする必要があります。その中で、32ビットシステムと64ビットシステムは異なるパッケージをガイドするため、区別する必要があります。それ以外の場合は、エラーが報告されます。BlueCoveには、Apacheのcommons-ioパッケージも必要です。これはちなみに実行できます。
リンク:https
://pan.baidu.com/s/1tFixZRIRaN4HdlslDlKhuQ抽出コード:rr12
三、コード部分
3.1デバイス検索クラス
package com.jcsim;
/**
* Created with IntelliJ IDEA.
*
* @Author: Jcsim
* @Date: 2020/11/25 15:15
* @Description:设备查找类
*/
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<RemoteDevice> devicesDiscovered = new HashSet<RemoteDevice>();
public final static Vector<String> serviceFound = new Vector<String>();
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();
}
}
/**
* 发现设备
* @param remoteDevice
* @param deviceClass
*/
@Override
public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) {
devicesDiscovered.add(remoteDevice);
try {
System.out.println("#发现设备" + remoteDevice.getFriendlyName(false)+" 设备地址:"+remoteDevice.getBluetoothAddress());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 发现服务
* @param transID id
* @param servRecord 服务记录
*/
@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");
}
/**
* 服务搜索已完成
* @param arg0
* @param arg1
*/
@Override
public void serviceSearchCompleted(int arg0, int arg1) {
System.out.println("#" + "serviceSearchCompleted");
synchronized(serviceSearchCompletedEvent){
serviceSearchCompletedEvent.notifyAll();
}
}
};
/**
* 查找设备
* @throws IOException
* @throws InterruptedException
*/
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());
}
}
}
/**
* 获取设备
* @return
* @throws IOException
* @throws InterruptedException
*/
public static Set<RemoteDevice> getDevices() throws IOException, InterruptedException {
findDevices();
return devicesDiscovered;
}
/**
* 查找服务
* @param btDevice
* @param serviceUUID
* @return
* @throws IOException
* @throws InterruptedException
*/
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 "";
}
}
}
3.2Bluetoothクライアントクラス
package com.jcsim;
/**
* Created with IntelliJ IDEA.
*
* @Author: Jcsim
* @Date: 2020/11/25 15:14
* @Description:蓝牙客户端类
*/
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.bluetooth.BluetoothConnectionException;
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(DataInputStream inputStream, OutputStream outputStream);
void onConnectionFailed();
void onDisconnected();
void onClose();
}
/**
* 发现监听
*/
public interface OnDiscoverListener {
void onDiscover(RemoteDevice remoteDevice);
}
/**
* 无参构造函数
*/
public BluetoothClient() {
}
/**
* 查找所有
* @throws IOException
* @throws InterruptedException
*/
public void find() throws IOException, InterruptedException {
//附近所有的蓝牙设备,必须先执行 runDiscovery
Set<RemoteDevice> devicesDiscovered = RemoteDeviceDiscovery.getDevices();
Iterator<RemoteDevice> itr = devicesDiscovered.iterator();
//连接
while (itr.hasNext()) {
RemoteDevice remoteDevice = itr.next();
onDiscoverListener.onDiscover(remoteDevice);
}
}
/**
* 启动连接
* @param remoteDevice
* @throws IOException
* @throws InterruptedException
*/
public void startClient(RemoteDevice remoteDevice) throws IOException, InterruptedException {
// String url = RemoteDeviceDiscovery.searchService(remoteDevice, serviceUUID);
// System.out.println("url=="+url);
// 1 为通道;authenticate=true;encrypt=true表示需要验证pin码
// btspp://<蓝牙设备地址>:<通道号>
String url = "btspp://"+remoteDevice.getBluetoothAddress()+":1;authenticate=true;encrypt=true";
try{
streamConnection = (StreamConnection) Connector.open(url);
if (this.onClientListener != null) {
this.onClientListener.onConnected(streamConnection.openDataInputStream(), streamConnection.openOutputStream());
}else{
System.out.println("请打开蓝牙");
}
} catch (BluetoothConnectionException e){
e.printStackTrace();
System.out.println("蓝牙连接错误,请查看蓝牙是否打开。");
}catch (Exception e){
e.printStackTrace();
}
}
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;
}
}
3.3Bluetoothクライアントサービス
package com.jcsim;
/**
* Created with IntelliJ IDEA.
*
* @Author: Jcsim
* @Date: 2020/11/25 15:17
* @Description:蓝牙客户端业务类
*/
import javax.bluetooth.RemoteDevice;
import javax.microedition.io.ConnectionNotFoundException;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
public class BluetoothClientService {
public static void main(String[] argv) {
final String serverUUID = "1000110100001000800000805F9B34FB"; //需要与服务端相同
BluetoothClient client = new BluetoothClient();
Vector<RemoteDevice> remoteDevices = new Vector<>();
Boolean isConnect = false;
client.setOnDiscoverListener(new BluetoothClient.OnDiscoverListener() {
@Override
public void onDiscover(RemoteDevice remoteDevice) {
remoteDevices.add(remoteDevice);
}
});
client.setClientListener(new BluetoothClient.OnClientListener() {
@Override
public void onConnected(DataInputStream inputStream, OutputStream outputStream) {
System.out.printf("Connected");
// 开启线程读写蓝牙上接收和发送的数据。
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("客户端开始监听...");
// System.out.println("接收连接");
// System.out.println("开始读数据...");
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
while (true) {
byte[] buffer = new byte[1024];
int bytes=0;
int ch;
// inputStream.read(buffer)
while ((ch = inputStream.read()) != '\n') {
// 读数据。
// String s = new String(buffer);
// System.out.println("===========start=============");
// System.out.println(s.trim());
// System.out.println("------------end------------");
// Thread.sleep(1000);
if(ch!=-1){
buffer[bytes] = (byte) ch;
bytes++;
}
}
buffer[bytes] = (byte)'\n';
bytes++;
String s = new String(buffer);
System.out.println("===========start=============");
System.out.println(df.format(new Date())+"->"+s.trim());
System.out.println("------------end------------");
// inputStream.close();
// onClose();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void onConnectionFailed() {
System.out.printf("Connection failed");
}
@Override
public void onDisconnected() {
}
@Override
public void onClose() {
}
});
try {
client.find();
if (remoteDevices.size() > 0 ) {
for(int i=0;i<remoteDevices.size();i++){
System.out.println("第"+i+"个地址为:"+remoteDevices.get(i).getBluetoothAddress());
if( "所要连接的蓝牙的地址".equals(remoteDevices.get(i).getBluetoothAddress())){
isConnect = true;
client.startClient(remoteDevices.get(i));
break;
}
}
if (!isConnect){
System.out.println("请打开传感器蓝牙设备。");
}
// System.out.println("remoteDevices.firstElement="+remoteDevices.firstElement());
}else {
System.out.println("附件没有蓝牙设备");
}
} catch (ConnectionNotFoundException e){
System.out.println("当前蓝牙不在线");
e.printStackTrace();
} catch (InterruptedException | IOException e) {
e.printStackTrace();
}
}
}
4、データを読み取る
以前にデータを読み取ったとき、データは常に文字化けしているか、順序が狂っていました(文字のセグメントがいくつかのセグメントに分割されていました)。
文字化けした解決策:Bluetoothによって送信されるボーレートは通常9600です。
順序が正しくない:InputStreamを使用して読み取る場合、シリアルポートのようなターミネーターを設定することはできません(シリアルポートのターミネーターは通常、改行文字「\ r \ n」です)。したがって、スレッドの読み取りは非常にランダムです。それがいつであるかを知るそれを読んだ後、あなたの文字列は不完全になります。
古い方法(故障):
while (true) {
byte[] buffer = new byte[1024];
//
while (inputStream.read(buffer) != -1) {
// 读数据。
String s = new String(buffer);
System.out.println("===========start=============");
System.out.println(s.trim());
System.out.println("------------end------------");
Thread.sleep(1000);
}
// inputStream.close();
// onClose();
}
順不同の解決策:InputStream.read()を使用して、文字を1つずつ読み取り、それがターミネーターであるかどうかを判別し、ターミネーターに到達しない場合は読み取りと書き込みを続けます
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");
while (true) {
byte[] buffer = new byte[1024];
int bytes = 0; //字符串长度
int ch; // 读取字符的变量
while ((ch = inputStream.read()) != '\n') {
// 读数据。
if(ch!=-1){
buffer[bytes] = (byte) ch; // 将读取到的字符写入
bytes++;
}
}
buffer[bytes] = (byte)'\n'; //最后加上一个换行
bytes++;
String s = new String(buffer);
System.out.println("===========start=============");
System.out.println(df.format(new Date())+"->"+s.trim());
System.out.println("------------end------------");
}