Android: 如何通过蓝牙连接从输入流中读取字符串?
Android: How to read a string from input stream via bluetooth connection?
我正在制作一个应用程序,我需要让我的 PC 和 phone 通过蓝牙进行通信。我已经让应用程序和我的电脑成功连接,当我从我的电脑发送“Hello World”时,我的应用程序正在接收输入流。但是,我似乎无法弄清楚如何从输入流中获取可读字符串。这是我到目前为止的代码:
private static class BluetoothAcceptThread extends Thread {
private final Context CONTEXT;
private final BluetoothAdapter BLUETOOTH_ADAPTER = BluetoothAdapter.getDefaultAdapter();
private final BluetoothServerSocket BLUETOOTH_SERVER_SOCKET;
private final java.util.UUID UUID;
public BluetoothAcceptThread(Context context, java.util.UUID uuid) {
this.CONTEXT = context;
this.UUID = uuid;
BluetoothServerSocket tmp = null;
try {
tmp = BLUETOOTH_ADAPTER.listenUsingRfcommWithServiceRecord(
CONTEXT.getString(R.string.app_name), UUID);
} catch (IOException e) {
e.printStackTrace();
}
BLUETOOTH_SERVER_SOCKET = tmp;
}
@Override
public void run() {
while (true) {
BluetoothSocket socket = null;
try {
System.out.println("Accepting incoming connections");
socket = BLUETOOTH_SERVER_SOCKET.accept();
System.out.println("Found connection!");
} catch (IOException e) {
System.out.println(1);
e.printStackTrace();
}
if (socket != null) {
manageConnectedSocket(socket);
}
try {
assert socket != null;
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void cancel() {
try {
BLUETOOTH_SERVER_SOCKET.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.read() == -1) {
inputStream = socket.getInputStream();
}
String string = CharStreams.toString( new InputStreamReader(inputStream, "UTF-8"));
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果相关,这是我 运行 从我的 PC 获得的测试代码:
import bluetooth
import pydbus
def list_connected_devices():
bus = pydbus.SystemBus()
mngr = bus.get('org.bluez', '/')
mngd_objs = mngr.GetManagedObjects()
connected_devices = []
for path in mngd_objs:
con_state = mngd_objs[path].get('org.bluez.Device1', {}).get('Connected', False)
if con_state:
addr = mngd_objs[path].get('org.bluez.Device1', {}).get('Address')
name = mngd_objs[path].get('org.bluez.Device1', {}).get('Name')
connected_devices.append({'name': name, 'address': addr})
return connected_devices
def main():
address = list_connected_devices()[0]["address"]
uuid = "38b9093c-ff2b-413b-839d-c179b37d8528"
service_matches = bluetooth.find_service(uuid=uuid, address=address)
first_match = service_matches[0]
port = first_match["port"]
host = first_match["host"]
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((host, port))
message = input("Enter message to send: ")
sock.send(message)
if __name__ == '__main__':
main()
编辑:
尝试使用 Sajeel 建议的解决方案,使用 IO utils,但出现错误:
W/System.err: java.io.IOException: bt socket closed, read return: -1
W/System.err: at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:550)
at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:88)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:291)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:355)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:181)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2369)
W/System.err: at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2348)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2325)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2273)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:1041)
at com.example.app.BluetoothSyncService$BluetoothAcceptThread.manageConnectedSocket(BluetoothSyncService.java:278)
at com.example.app.BluetoothSyncService$BluetoothAcceptThread.run(BluetoothSyncService.java:251)
编辑 2:
我妈搞定了!这是让它工作的代码:
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.available() == 0) {
inputStream = socket.getInputStream();
}
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes, 0, available);
String string = new String(bytes);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
尝试
String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
为了使用IOUtils.toString()
添加以下内容
在 build.gradle
应用程序模块中
implementation group: 'commons-io', name: 'commons-io', version: '2.5' //Add this line
之后import
import org.apache.commons.io.IOUtils;
终于找到解决办法了。您需要创建一个与输入流的可用字节长度相同的字节数组,然后调用输入流的 .read() 方法。然后输入流会将接收到的字节写入字节数组,然后您可以将其解码为字符串。
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.available() == 0) {
inputStream = socket.getInputStream();
}
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes, 0, available);
String string = new String(bytes);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
我正在制作一个应用程序,我需要让我的 PC 和 phone 通过蓝牙进行通信。我已经让应用程序和我的电脑成功连接,当我从我的电脑发送“Hello World”时,我的应用程序正在接收输入流。但是,我似乎无法弄清楚如何从输入流中获取可读字符串。这是我到目前为止的代码:
private static class BluetoothAcceptThread extends Thread {
private final Context CONTEXT;
private final BluetoothAdapter BLUETOOTH_ADAPTER = BluetoothAdapter.getDefaultAdapter();
private final BluetoothServerSocket BLUETOOTH_SERVER_SOCKET;
private final java.util.UUID UUID;
public BluetoothAcceptThread(Context context, java.util.UUID uuid) {
this.CONTEXT = context;
this.UUID = uuid;
BluetoothServerSocket tmp = null;
try {
tmp = BLUETOOTH_ADAPTER.listenUsingRfcommWithServiceRecord(
CONTEXT.getString(R.string.app_name), UUID);
} catch (IOException e) {
e.printStackTrace();
}
BLUETOOTH_SERVER_SOCKET = tmp;
}
@Override
public void run() {
while (true) {
BluetoothSocket socket = null;
try {
System.out.println("Accepting incoming connections");
socket = BLUETOOTH_SERVER_SOCKET.accept();
System.out.println("Found connection!");
} catch (IOException e) {
System.out.println(1);
e.printStackTrace();
}
if (socket != null) {
manageConnectedSocket(socket);
}
try {
assert socket != null;
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void cancel() {
try {
BLUETOOTH_SERVER_SOCKET.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.read() == -1) {
inputStream = socket.getInputStream();
}
String string = CharStreams.toString( new InputStreamReader(inputStream, "UTF-8"));
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果相关,这是我 运行 从我的 PC 获得的测试代码:
import bluetooth
import pydbus
def list_connected_devices():
bus = pydbus.SystemBus()
mngr = bus.get('org.bluez', '/')
mngd_objs = mngr.GetManagedObjects()
connected_devices = []
for path in mngd_objs:
con_state = mngd_objs[path].get('org.bluez.Device1', {}).get('Connected', False)
if con_state:
addr = mngd_objs[path].get('org.bluez.Device1', {}).get('Address')
name = mngd_objs[path].get('org.bluez.Device1', {}).get('Name')
connected_devices.append({'name': name, 'address': addr})
return connected_devices
def main():
address = list_connected_devices()[0]["address"]
uuid = "38b9093c-ff2b-413b-839d-c179b37d8528"
service_matches = bluetooth.find_service(uuid=uuid, address=address)
first_match = service_matches[0]
port = first_match["port"]
host = first_match["host"]
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((host, port))
message = input("Enter message to send: ")
sock.send(message)
if __name__ == '__main__':
main()
编辑:
尝试使用 Sajeel 建议的解决方案,使用 IO utils,但出现错误:
W/System.err: java.io.IOException: bt socket closed, read return: -1
W/System.err: at android.bluetooth.BluetoothSocket.read(BluetoothSocket.java:550)
at android.bluetooth.BluetoothInputStream.read(BluetoothInputStream.java:88)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:291)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:355)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:181)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.Reader.read(Reader.java:140)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2369)
W/System.err: at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2348)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2325)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:2273)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:1041)
at com.example.app.BluetoothSyncService$BluetoothAcceptThread.manageConnectedSocket(BluetoothSyncService.java:278)
at com.example.app.BluetoothSyncService$BluetoothAcceptThread.run(BluetoothSyncService.java:251)
编辑 2:
我妈搞定了!这是让它工作的代码:
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.available() == 0) {
inputStream = socket.getInputStream();
}
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes, 0, available);
String string = new String(bytes);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}
尝试
String str = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
为了使用IOUtils.toString()
添加以下内容
在 build.gradle
应用程序模块中
implementation group: 'commons-io', name: 'commons-io', version: '2.5' //Add this line
之后import
import org.apache.commons.io.IOUtils;
终于找到解决办法了。您需要创建一个与输入流的可用字节长度相同的字节数组,然后调用输入流的 .read() 方法。然后输入流会将接收到的字节写入字节数组,然后您可以将其解码为字符串。
public void manageConnectedSocket(BluetoothSocket socket) {
try {
InputStream inputStream = socket.getInputStream();
while(inputStream.available() == 0) {
inputStream = socket.getInputStream();
}
int available = inputStream.available();
byte[] bytes = new byte[available];
inputStream.read(bytes, 0, available);
String string = new String(bytes);
System.out.println(string);
} catch (IOException e) {
e.printStackTrace();
}