为啥我的蓝牙套接字的文件描述符为空?
Posted
技术标签:
【中文标题】为啥我的蓝牙套接字的文件描述符为空?【英文标题】:Why is my file descriptor to a bluetooth socket null?为什么我的蓝牙套接字的文件描述符为空? 【发布时间】:2015-09-15 19:15:12 【问题描述】:谁能帮我弄清楚为什么我只能将空文件描述符获取到通过 BluetoothServerSocket.accept() 打开的蓝牙套接字?
我的目标是通过蓝牙在两个设备之间流式传输视频,方法是将视频写入一侧的文件描述符并从另一侧的文件描述符读取它。我的蓝牙连接很好,可以来回发送原始数据,但只能在客户端获取文件描述符。在服务器端,使用相同的代码,我只能得到一个空文件描述符。在调试器中,我可以在 mySocket.mSocketIS.this$0.fd 处看到服务器端的文件描述符,但我不知道如何访问它。任何人都可以帮忙吗?这是 android 4.4.2,这是我的代码:
首先是损坏的代码(服务器端):
// Listen for an incoming Bluetooth connection
class AcceptThread extends Thread
// Thread that accepts incoming bluetooth connections
public AcceptThread()
try
// Open a listening server socket. This is non-blocking
btServerSocket = BA.listenUsingRfcommWithServiceRecord("ServerApp", videoUUID);
catch(IOException e) btServerSocket = null;
// AcceptThread()
public void run()
BluetoothSocket btSocket = null;
// Listen until exception or we have a socket
while(true)
try
// Blocking call to accept an incoming connection. To get out of this, call cancel() which closes the socket, causing .accept() to throw an exception
btSocket = btServerSocket.accept();
// If we get here, we're connected!
Field pfdField = btSocket.getClass().getDeclaredField("mPfd");
pfdField.setAccessible(true);
ParcelFileDescriptor pfd = (ParcelFileDescriptor) pfdField.get(btSocket);
// >>> ERROR - pfd is null <<<< I can see a fd at mySocket.mSocketIS.this$0.fd;, but how do I access it?
FileDescriptor myFd = pfd.getFileDescriptor();
// ... blah blah...
现在工作代码(客户端):
// Connect to a remote device as the client (we are the client)
class ConnectThread extends Thread
// ctor
// remoteUUID - The UUID of the remote device that we want to connect to
public ConnectThread(BluetoothDevice btDevice, UUID remoteUUID)
// Get a BT socket to connect with the given BluetoothDevice
try
// MY_UUID is the app's UUID string, also used by the server code
btClientSocket = btDevice.createRfcommSocketToServiceRecord(remoteUUID);
catch(Exception e) postUIMessage("ConnectThread exception: " + e.toString());
// ConnectThread ctor
public void run()
// Cancel discovery because it will slow down the connection
BA.cancelDiscovery();
try
// Connect the device through the socket. This will block until it succeeds or throws an exception. To get out, call cancel() below, which will cause .connect() to throw an exception.
btClientSocket.connect();
Field pfdField = btClientSocket.getClass().getDeclaredField("mPfd");
pfdField.setAccessible(true);
ParcelFileDescriptor pfd = (ParcelFileDescriptor) pfdField.get(btClientSocket);
FileDescriptor myFd = pfd.getFileDescriptor(); // Pass this to Recorder.setOutputFile();
// Yay myFd is good!
【问题讨论】:
【参考方案1】:我找到了解决此问题的方法,我们也使用蓝牙作为服务器。我从 BluetoothSocket 的 LocalSocket 字段中找到了文件描述符。我的目标是获取文件并关闭它。
int mfd = 0;
Field socketField = null;
LocalSocket mSocket = null;
try
socketField = btSocket.getClass().getDeclaredField("mSocket");
socketField.setAccessible(true);
mSocket = (LocalSocket)socketField.get(btSocket);
catch(Exception e)
Log ( "Exception getting mSocket in cleanCloseFix(): " + e.toString());
if(mSocket != null)
FileDescriptor fileDescriptor =
mSocket.getFileDescriptor();
String in = fileDescriptor.toString();
//regular expression to get filedescriptor index id
Pattern p = Pattern.compile("\\[(.*?)\\]");
Matcher m = p.matcher(in);
while(m.find())
Log ( "File Descriptor " + m.group(1));
mfd = Integer.parseInt(m.group(1));
break;
//Shutdown the socket properly
mSocket.shutdownInput();
mSocket.shutdownOutput();
mSocket.close();
mSocket = null;
try socketField.set(btSocket, mSocket);
catch(Exception e)
Log ("Exception setting mSocket = null in cleanCloseFix(): " + e.toString());
//Close the file descriptor when we have it from the Local Socket
try
ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.adoptFd(mfd);
if (parcelFileDescriptor != null)
parcelFileDescriptor.close();
Log ( "File descriptor close succeed : FD = " + mfd);
catch (Exception ex)
Log ( "File descriptor close exception " + ex.getMessage());
【讨论】:
感谢您的信息!当我回到项目时,我会试试这个。以上是关于为啥我的蓝牙套接字的文件描述符为空?的主要内容,如果未能解决你的问题,请参考以下文章