3

私は、Bluetooth経由でデータP2Pを共有するAndroidアプリケーション(EDIT1:Nexsus Sで4.0.3で開発中)の作成に取り組んでおり、2つのデバイスを接続する際に厄介な問題に遭遇しました。このアプリは、NFCを使用して1つのデバイスのMACアドレスを別のデバイスに渡します。次に、送信者はBlueToothServerソケットインスタンスを作成し、acceptを呼び出します。一方、受信者は、受信したMACアドレスを使用してBluetoothDeviceインスタンスを作成し、接続を試みます。

私たちが抱えている問題は、accept()から返されたBluetoothSocketにあります。そのドキュメントには、接続されたソケットを返す必要があることが明確に記載されていますが、代わりに、connect()を呼び出しても接続できない切断されたソケットが返されます。ソケットが持っているMACアドレスを確認したところ、それがクリアされました。返された単なる事実accept()は、ソケットを作成するのに十分な時間接続に成功したことを意味するため、他に何を試すか迷っています。

この間、受信機のBluetoothSocketは、実際に接続されていると主張していることにも言及する価値があります。明らかに、他のデバイスから送信されないデータを待機している間は単にハングしますが、複数の場所でチェックポイントを使用すると、それまでは常に接続されていると主張していることがわかります。

これに関するヘルプやアドバイスをいただければ幸いです。

その他の関連情報:

送信者と受信者は同じアプリですが、異なるアクティビティを表します。このアプリは、ゲームに参加するために、ゲームを持っている人が他の人にゲームを渡す必要があるゲームです。これは、NFCによって開始されます(最終的にBluetooth経由で送信されると想定されるデータは、参加に必要なゲームデータです)。送信者はゲームを持っており、それを譲渡するアクティビティを行っています。一方、受信者はゲームを受け取り、他の誰かに渡すことができるように、ゲームを譲渡するアクティビティに移動します。これを明確にするために、現在これら2つのアクティビティをマージすることは可能ですが、両方がオンになっていることを確認できない実際のゲームの一部として、後で同じ手法を使用する予定です。同じ活動、

また、UUIDが正しく一致していることも確認しています。ある時点で生成して使用した定数UUIDを持つグローバルクラスがあります。目的によっては、特定のインスタンスでUUIDを特定する必要があるように見えますが、この特定の用途では、UUIDを独自に生成することも理解しました。

BluetoothServerSocketが作成され、NdefPushbackCompleteのコールバックの一部としてaccept()が呼び出されるため、送信者がサーバーソケットのセットアップを開始する前に、他の電話にNdefメッセージが確実に送信されます。

クライアントまたはサーバーのBluetoothコードは、オンラインで一般的に見られるように独自のスレッドで実行されていません。これは、どちらかの側が他のことを実行する前に交換を完全に実行するための設計によるものです。

重要なことをお伝えしなかった場合は、喜んで提供させていただきます。最後に、これがクライアント側とサーバー側のコードです。このバージョンは安全でないソケットを使用していますが、私は両方の方法で試しましたが、これをテストするために使用されている電話はペアになっています。

クライアント:

String s = new String(msg.getRecords()[0].getPayload());
otherBluetoothMACAddress = s;
Log.d(DEV, "WaitingToGetGame: Other BT Address... "
    + otherBluetoothMACAddress);


Toast.makeText(getApplicationContext(), s, Toast.LENGTH_LONG).show();

Log.d(DEV, "WaitingToGetGame: Getting remote device");
BluetoothDevice bluetoothDevice = bluetoothAdapter
    .getRemoteDevice(otherBluetoothMACAddress);

ObjectInputStream objectInputStream;
ObjectOutputStream objectOutputStream;


try
{
  Log.d(DEV, "WaitingToGetGame: Getting BluetoothSocket");
  bluetoothSocket = bluetoothDevice
      .createInsecureRfcommSocketToServiceRecord(SDP_UUID);

  Log.d(DEV, "WaitingToGetGame: Connecting...");
  bluetoothSocket.connect();

  Log.d(DEV,
      "WaitingToGetGame: Bluetooth "
          + ((bluetoothSocket.isConnected()) ? ("is ") : ("is NOT "))
          + "Connected.");

  Log.d(DEV, "WaitingToGetGame: Getting input stream");
  bluetoothInputStream = bluetoothSocket.getInputStream();

  Log.d(DEV,
      "WaitingToGetGame: Bluetooth "
          + ((bluetoothSocket.isConnected()) ? ("is ") : ("is NOT "))
          + "Connected.");
  Log.d(DEV, "WaitingToGetGame: Getting output stream");
  bluetoothOutputStream = bluetoothSocket.getOutputStream();

  Log.d(DEV,
      "WaitingToGetGame: Bluetooth "
          + ((bluetoothSocket.isConnected()) ? ("is ") : ("is NOT "))
          + "Connected.");
  objectInputStream = new ObjectInputStream(bluetoothInputStream);
  objectOutputStream = new ObjectOutputStream(bluetoothOutputStream);

  Log.d(DEV, this.getClass().getSimpleName() + ": Receiving game data");
  game = (Game) objectInputStream.readObject();

  Log.d(DEV, this.getClass().getSimpleName() + ": Sending acknowledgment.");
  objectOutputStream.writeObject(new Boolean(true));
  objectInputStream.close();
  objectOutputStream.close();
  bluetoothInputStream.close();
  bluetoothOutputStream.close();
  bluetoothInputStream = null; // GC
  bluetoothOutputStream = null; // GC
  bluetoothSocket.close();
  bluetoothSocket = null;

サーバ:

BluetoothServerSocket bluetoothServerSocket = null;
ObjectInputStream objectInputStream;
ObjectOutputStream objectOutputStream;

try
{

  Log.d(DEV, this.getClass().getSimpleName()
      + ": Getting BluetoothServerSocket");
  // bluetoothServerSocket = bluetoothAdapter
  // .listenUsingRfcommWithServiceRecord(user.getName(), SDP_UUID);
  bluetoothServerSocket = bluetoothAdapter
      .listenUsingInsecureRfcommWithServiceRecord(user.getName(), SDP_UUID);

  Log.d(DEV, this.getClass().getSimpleName() + ": Waiting for connection.");
  bluetoothSocket = bluetoothServerSocket.accept();
  bluetoothServerSocket.close();
  BluetoothDevice dev = bluetoothSocket.getRemoteDevice();
  Log.d(DEV, dev.getAddress());

  Log.d(DEV, this.getClass().getSimpleName() + ": Bluetooth "
      + ((bluetoothSocket.isConnected()) ? ("is ") : ("is NOT "))
      + "Connected.");
  // At this point bluetoothSocket should be ready to use.

  Log.d(DEV, this.getClass().getSimpleName() + ": Getting input stream");
  bluetoothInputStream = bluetoothSocket.getInputStream();

  Log.d(DEV, this.getClass().getSimpleName() + ": Bluetooth "
      + ((bluetoothSocket.isConnected()) ? ("is ") : ("is NOT "))
      + "Connected.");


  Log.d(DEV, this.getClass().getSimpleName() + ": Getting output stream");
  bluetoothOutputStream = bluetoothSocket.getOutputStream();

  // Log.d(DEV, this.getClass().getSimpleName()
  // + ": Attempting direct connect()");
  // bluetoothSocket.connect();

  objectInputStream = new ObjectInputStream(bluetoothInputStream);
  objectOutputStream = new ObjectOutputStream(bluetoothOutputStream);


  Log.d(DEV, this.getClass().getSimpleName() + ": Sending game data.");
  objectOutputStream.writeObject(game);

  Log.d(DEV, this.getClass().getSimpleName() + ": Waiting for response.");
  Boolean response = (Boolean) objectInputStream.readObject();

  objectInputStream.close();
  objectOutputStream.close();
  bluetoothInputStream.close();
  bluetoothOutputStream.close();
  bluetoothInputStream = null; // GC
  bluetoothOutputStream = null; // GC
  bluetoothSocket.close();
  bluetoothSocket = null;
}// try
catch( IOException e )
{
  Log.d(
      DEV,
      this.getClass().getSimpleName() + ": "
          + java.util.Arrays.toString(e.getStackTrace()));
  e.printStackTrace();
  return;
}
catch( ClassNotFoundException e )
{
  // TODO Auto-generated catch block
  e.printStackTrace();
}
4

1 に答える 1

1

これまでのところ、あなたのプログラムに問題は見つかりませんでしたが、

明らかに、他のデバイスから来ることのないデータを待っている間、単にハングアップするだけですが、複数の場所でチェックポイントを使用すると、それまでは常に接続されていると主張していることがわかります。

実際には、これは 2 つのデバイスが接続されていることを意味しますが、BT クライアント アプリがソケットを接続していないというだけで、別の場所に接続しています。

いくつかのことを試すことができます:

  • ブロッキング呼び出しを try/catch で囲む必要があります。そうしないと、コードが期待どおりに機能したとは言えません。そのため、bluetoothSocket.connect();を囲みます。 クライアントコードで、およびbluetoothSocket = bluetoothServerSocket.accept(); サーバーコードで。クライアント コードは、bt クライアント接続エラーで IOException をキャッチする必要があります。これは、クライアント接続が成功したかどうかを判断するための最良の方法だと思います! コードのように、 Ofc .isConnected() は後でそれを行うことができます。

  • (さらに良い) サービスでない場合は、ASyncTask 内で Bluetooth コードを実行します。やりたくないのはわかりますが、そうすることで多くの苦痛を和らげることができます。私の BT コードは ASyncTasks から完全に実行されます - カスタム UUID、2 つの Android 間、1 つの Android と 1 つの BT-USB ドングルの間、1 つの Android - 1 つの組み込みデバイスなど。

  • UUID を SDP に変更し、それが機能するかどうかを確認してください。

1 つ質問ですが、サーバー側から何かを送信しようとしましたか? それはうまくいくはずです..これがうまくいったかどうか教えてください!

于 2012-05-10T06:30:01.023 に答える