Android蓝牙:生成随机UUID后无法连接到侦听套接字
我的程序有两个不同的实例不打算连接到Android蓝牙:生成随机UUID后无法连接到侦听套接字,android,sockets,bluetooth,device,serversocket,Android,Sockets,Bluetooth,Device,Serversocket,我的程序有两个不同的实例不打算连接到BluetoothServerSocket 其中一个实例在使用scan\u mode\u CONNECTABLE\u DISCOVERABLE启动扫描模式之前,以及在使用相同生成的UUID创建用于侦听的BluetoothServerSocket之前,仅随机生成了1个UUID。另一个intance在Bluetooth设备尝试连接刚刚生成的UUID之前生成一个随机UUID 每个实例都无法完成蓝牙连接。在整个程序中,我放了很多日志,只是想看看为什么它无法连接 下面是
BluetoothServerSocket
其中一个实例在使用scan\u mode\u CONNECTABLE\u DISCOVERABLE
启动扫描模式之前,以及在使用相同生成的UUID创建用于侦听的BluetoothServerSocket
之前,仅随机生成了1个UUID。另一个intance在Bluetooth设备尝试连接刚刚生成的UUID之前生成一个随机UUID
每个实例都无法完成蓝牙连接。在整个程序中,我放了很多日志,只是想看看为什么它无法连接
下面是第一个实例的代码。(在应用程序启动时生成1个随机UUID。)如果有人想下载我的Eclipse项目只是为了看一看,比如第二个实例,那么在下面的代码中取消注释C风格的注释就会显示出来
我希望结果是在两台设备之间成功连接。成功的连接使用生成的UUID将设备连接到侦听套接字。观察结果表明这不太可能。
据我所知,获取UUID的唯一方法是从UUID.randomUUID()
获取它。如果还有其他方法,请在下面发表评论,我会检查一下。但现在,这不是我想要的答案
提前谢谢
package o.p;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
/**
* The purpose of this app is to create a server-only Bluetooth connection that
* only accepts incoming Bluetooth connections. It is used only for testing
* one device that needs Bluetooth tweaking in order to consistently work
* correctly on the other device. In short, 2 devices are required.
* */
public class Main extends Activity implements View.OnClickListener {
//Button
private Button acceptButton;
private Button scanButton;
//Bluetooth stuffs.
private BluetoothAdapter btAdapter;
private BluetoothServerSocket serverSocket;
private BluetoothSocket socket;
private BluetoothDevice targetDevice;
private final UUID uuid = UUID.randomUUID();
/*private UUID randomUUID;*/
//Accepting thread.
private class Accept implements Runnable {
private BluetoothServerSocket socket;
private BluetoothSocket result = null;
public Accept(BluetoothServerSocket s) {
socket = s;
result = null;
}
@Override
public void run() {
try {
Log.d("DEBUG", "Accepting.");
result = socket.accept();
Log.d("DEBUG", "Closing server socket.");
socket.close();
}
catch (IOException e) {
Log.d("DEBUG - onClick(), case Accept", "Unable to accept incoming connection.");
}
}
public BluetoothSocket getSocket() {
while (result == null);
return result;
}
}
//Connecting thread.
private class Connecting implements Runnable {
private BluetoothDevice device;
public Connecting(BluetoothDevice d) {
device = d;
}
@Override
public void run() {
try {
/*Log.d("DEBUG", "Generating a new random UUID.");
randomUUID = UUID.randomUUID();*/
Log.d("DEBUG", "Obtaining a socket.");
BluetoothSocket s = device.createRfcommSocketToServiceRecord(uuid);
Log.d("DEBUG", "Cancelling discovery, if it's still discovering.");
if (btAdapter.isDiscovering())
btAdapter.cancelDiscovery();
Log.d("DEBUG", "Connecting to listening socket with UUID: " + uuid.toString());
s.connect();
}
catch (IOException e) {
Log.d("DEBUG - Connecting.run()", "Unable to connect to the listening socket.");
}
}
}
//Thread executor
private ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
//BroadcastReceiver for accepting Bluetooth
private BroadcastReceiver receiver;
@Override
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.main);
init();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_accept:
Log.d("DEBUG", "Pressing the Accept button.");
Accept acceptThread = new Accept(serverSocket);
Connecting connectThread = new Connecting(targetDevice);
if (serverSocket != null) {
executor.execute(acceptThread);
executor.execute(connectThread);
socket = acceptThread.getSocket();
}
else {
Log.d("DEBUG", "Server socket isn't ready.");
Toast.makeText(this, "Server socket isn't ready.", Toast.LENGTH_LONG).show();
}
break;
case R.id.button_scan:
if (btAdapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Log.d("DEBUG", "Initiating discovery scan mode.");
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
this.startActivity(discoverableIntent);
Toast.makeText(this, "Being discovered...", Toast.LENGTH_LONG).show();
}
if (btAdapter.isDiscovering()) {
Toast.makeText(this, "Re-scanning...", Toast.LENGTH_SHORT).show();
Log.d("DEBUG", "Re-scanning.");
btAdapter.cancelDiscovery();
}
Log.d("DEBUG", "Scanning.");
Toast.makeText(this, "Scanning...", Toast.LENGTH_LONG).show();
btAdapter.startDiscovery();
break;
}
}
private void init() {
Log.d("DEBUG", "Initializing.");
Log.d("DEBUG", "Button initializing.");
acceptButton = (Button) findViewById(R.id.button_accept);
acceptButton.setOnClickListener(this);
scanButton = (Button) findViewById(R.id.button_scan);
scanButton.setOnClickListener(this);
Log.d("DEBUG", "Registering BroadcastReceiver.");
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
Log.d("DEBUG", "Device has been found.");
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.d("DEBUG", "Obtained a device from Intent.");
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
Log.d("DEBUG", "Removing paired device.");
try {
Method m = device.getClass().getMethod("removeBond", (Class[]) null);
m.invoke(device, (Object[]) null);
Log.d("DEBUG", "Removed " + device);
}
catch (NoSuchMethodException e) {
Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
}
catch (IllegalArgumentException e) {
Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
}
catch (IllegalAccessException e) {
Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
}
catch (InvocationTargetException e) {
Log.e("ERROR - DeviceReceiver.onReceive()", "", e);
}
}
else {
Log.d("DEBUG", "Obtaining remote device's address.");
btAdapter.getRemoteDevice(device.getAddress());
try {
serverSocket = btAdapter.listenUsingRfcommWithServiceRecord(device.getName(), uuid);
Log.d("DEBUG", "Listening to " + device.getName() + "...");
}
catch (IOException e) {
Log.d("DEBUG - onReceive()", "Unable to create a server socket after receiving a broadcast.", e);
serverSocket = null;
Log.d("DEBUG", "Server socket is set to null.");
}
}
targetDevice = device;
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
Log.d("DEBUG", "Scanning finished.");
}
}
};
Log.d("DEBUG", "Creating Bluetooth Adapter.");
btAdapter = BluetoothAdapter.getDefaultAdapter();
try {
Log.d("DEBUG", "Creating a server socket for listening using UUID: " + uuid.toString());
serverSocket = btAdapter.listenUsingRfcommWithServiceRecord("server", uuid);
}
catch (IOException e) {
Log.d("DEBUG - init()", "Error in creating a server socket from uuid.");
}
}
@Override
public void onResume() {
super.onResume();
//TODO: Not done with the receivers.
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(receiver, filter);
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(receiver, filter);
}
@Override
public void onPause() {
//TODO: Complete this one. Same for onResume().
super.onPause();
unregisterReceiver(receiver);
}
}
要能够连接,UUID应该匹配。 在服务器端,您所做的是正确的,即生成一个ramdom UUID并监听它, 但是客户端需要使用服务器正在侦听的相同UUID进行连接。
获取它的方法是从客户端使用服务器BluetoothDevice对象上的fetchUUIDSWithDP()并使用获得的UUID连接到服务器。要能够连接UUID,UUID应该匹配。 在服务器端,您所做的是正确的,即生成一个ramdom UUID并监听它, 但是客户端需要使用服务器正在侦听的相同UUID进行连接。
获取它的方法是从客户端使用服务器BluetoothDevice对象上的fetchUUIDSWithDP()并使用获得的UUID连接到服务器。我也做了同样的事情。你可以把它作为参考。这是答案。我也做了同样的事。你可以把它作为参考。下面是示例。您知道在使用
fetchUUIDSWITHDP()
后过滤掉parceluId
数组的方法吗,以便它与客户端的UUID匹配?使用fetchuuidwithdp()
,我能够获得parcelouids
,但它们实际上都不允许服务器接受连接。这就像客户端的UUID不在阵列中一样,并且同一个UUID与服务器的UUID不匹配。简而言之,UUID不能在编译时生成。无法使用UUID.randomUUID()
生成UUID,除非它们用于其他特定用途。即使使用BluetoothDevice.getUuids()
或BluetoothDevice.fetchUuidsWithSDP()
也没有用,因为uuid也是在编译时生成的。(这包括使用反射方法和调用这两个函数以用于Android 4.0之前的版本,它们没有用处。)感谢您链接到讨论并提出适合您的解决方案,在编译时生成UUID基本上可以确保应用程序客户机和服务器使用相同的UUID,而这是连接的基本要求。只要您同时连接服务器和客户端,这是可以的,但是连接到一些现有的服务器应用程序呢?操作系统从SDP获取UUID的唯一方法,这就是蓝牙的工作原理,我自己也曾使用过FetchUUIDSWithDP(),但奇怪的是它返回的UUID没有用处。一些消息来源提到,一些设备,特别是HTC设备,没有100%的蓝牙兼容性。他们认为,这些设备的蓝牙集成尚未完成,而且当API级别达到更高的数字时(比如18到20),蓝牙集成很可能已经完成。即便如此,如果使用SDP获取的UUID失败,旧的API级别将很难利用蓝牙功能,这正是我现在所经历的。您知道在使用fetchUUIDSWithDP()
后过滤掉parceluid
数组的方法吗,以便它与客户端的UUID匹配?使用fetchuuidwithdp()
,我能够获得parcelouids
,但它们实际上都不允许服务器接受连接。这就像客户端的UUID不在阵列中一样,并且同一个UUID与服务器的UUID不匹配。简而言之,UUID不能在编译时生成。无法使用UUID.randomUUID()
生成UUID,除非它们用于其他特定用途。即使使用BluetoothDevice.getUuids()
或BluetoothDevice.fetchUuidsWithSDP()
也没有用,因为uuid也是在编译时生成的。(这包括使用反射方法和调用这两个函数以用于Android 4.0之前的版本,它们没有用处。)感谢您链接到讨论并提出适合您的解决方案,在编译时生成UUID基本上可以确保应用程序客户机和服务器使用相同的UUID,而这是连接的基本要求。只要您同时连接服务器和客户端,这是可以的,但是连接到一些现有的服务器应用程序呢?操作系统从SDP获取UUID的唯一方法,这就是蓝牙的工作原理,我自己也曾使用过FetchUUIDSWithDP(),但奇怪的是它返回的UUID没有用处。一些消息来源提到,一些设备,特别是HTC设备,没有100%的蓝牙兼容性。他们表示,这些设备的蓝牙集成还不完善,而且很可能是我的