蓝牙opp文件传输底层其实是支持同时传输多个文件的,但考虑到蓝牙速度较慢,UI也不好展示,故在系统层屏蔽了重入,当有文件传输时,新的连接请求会被拒绝。

public void ObexServerSockets::run() { try { while (!mStopped) { BluetoothSocket connSocket; BluetoothDevice device;

  try {
    ... ...

    /\* Signal to the service that we have received an incoming connection.
     \*/
    // 触发service的onConnect()
    boolean isValid = ObexServerSockets.this.onConnect(device, connSocket);

    if (!isValid) {
      /\* Close connection if we already have a connection with another device
       \* by responding to the OBEX connect request.
       \*/
      // service拒绝连接则创建ObexRejectServer响应回复
      Log.i(mTag, "RemoteDevice is invalid - creating ObexRejectServer.");
      BluetoothObexTransport obexTrans =
          new BluetoothObexTransport(connSocket);
      // Create and detach a selfdestructing ServerSession to respond to any
      // incoming OBEX signals.
      new ServerSession(obexTrans,
          new ObexRejectServer(ResponseCodes.OBEX\_HTTP\_UNAVAILABLE,
              connSocket), null);
      // now wait for a new connect
    } else {
      // now wait for a new connect
    }
  } catch (IOException ex) {
    if (mStopped) {
      // Expected exception because of shutdown.
    } else {
      Log.w(mTag, "Accept exception for " + mServerSocket, ex);
      ObexServerSockets.this.onAcceptFailed();
    }
    mStopped = true;
  }
} // End while()

} finally { if (D) { Log.d(mTag, “AcceptThread ended for: " + mServerSocket); } } }

public boolean BluetoothOppService::onConnect(BluetoothDevice device, BluetoothSocket socket) {

if (D) { Log.d(TAG, " onConnect BluetoothSocket :” + socket + " \n :device :” + device); } // 有传输后拒绝新的连接请求 if (!mAcceptNewConnections) { Log.d(TAG, " onConnect BluetoothSocket :” + socket + " rejected”); return false; } BluetoothObexTransport transport = new BluetoothObexTransport(socket); Message msg = mHandler.obtainMessage(MSG_INCOMING_BTOPP_CONNECTION); msg.obj = transport; msg.sendToTarget(); mAcceptNewConnections = false; return true; }

public class ObexRejectServer extends ServerRequestHandler implements Callback {

private static final String TAG = "ObexRejectServer";
private static final boolean V = true;
private final int mResult;
private final HandlerThread mHandlerThread;
private final Handler mMessageHandler;
private static final int MSG\_ID\_TIMEOUT = 0x01;
private static final int TIMEOUT\_VALUE = 5 \* 1000; // ms
private final BluetoothSocket mSocket;

/\*\*
 \* @param result the ResponseCodes.OBEX\_HTTP\_ code to respond to an incoming connect request.
 \*/

// 5秒内onConnect响应错误码,之后自毁 public ObexRejectServer(int result, BluetoothSocket socket) { super(); mResult = result; mSocket = socket; mHandlerThread = new HandlerThread(“TestTimeoutHandler”, android.os.Process.THREAD_PRIORITY_BACKGROUND); mHandlerThread.start(); Looper timeoutLooper = mHandlerThread.getLooper(); mMessageHandler = new Handler(timeoutLooper, this); // Initiate self destruction. mMessageHandler.sendEmptyMessageDelayed(MSG_ID_TIMEOUT, TIMEOUT_VALUE); }

// OBEX operation handlers
@Override
public int onConnect(HeaderSet request, HeaderSet reply) {
    if (V) {
        Log.i(TAG, "onConnect() returning error");
    }
    return mResult;
}

public void shutdown() {
    mMessageHandler.removeCallbacksAndMessages(null);
    mHandlerThread.quit();
    try {
        // This will cause an exception in the ServerSession, causing it to shut down
        mSocket.close();
    } catch (IOException e) {
        Log.w(TAG, "Unable to close socket - ignoring", e);
    }
}

@Override
public boolean handleMessage(Message msg) {
    if (V) {
        Log.i(TAG, "Handling message ID: " + msg.what);
    }
    switch (msg.what) {
        case MSG\_ID\_TIMEOUT:
            shutdown();
            break;
        default:
            // Message not handled
            return false;
    }
    return true; // Message handled
}

}