2

私はAndroid向けのゲームを作成しています。このゲームでは、2つのデバイスが接続して少量のデータを交換し、そのデータを切断して使用します。Bluetoothチャットの例から始めました。この時点で、私はそれをほとんど機能させていますが、いくつかの(ほとんどの)場合、デバイスの1つがデータを受信しません。これは両方のデバイスで同じアプリであるため、両方の送信コードと受信コードは同じです。私はこのように接続しています:

    public BluetoothClientThread(BluetoothDevice get_device,boolean secure){
        BluetoothSocket temp=null;
        device=get_device;
        socket_type=secure?"Secure":"Insecure";

        try{
            if(secure){
                temp=device.createRfcommSocketToServiceRecord(UUID_SECURE);
            }
            else{
                temp=device.createRfcommSocketToServiceRecord(UUID_INSECURE);
            }
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"create() on "+socket_type+" client socket failed.",e);
        }

        socket=temp;
    }

    public void run(){
        bluetooth_adapter.cancelDiscovery();

        try{
            socket.connect();
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"Connection failed.",e);

            try{
                socket.close();
            }
            catch(IOException ioe){
                StorageManager.error_log_add(context,TAG,"close() on "+socket_type+" client socket failed during connection failure.",ioe);
            }

            connection_failed();

            return;
        }

        synchronized(BluetoothService.this){
            bluetooth_client_thread=null;
        }

        connected(socket,device,socket_type,false);
    }

接続したら、ソケットのgetInputStream()とgetOutputStream()を取得します。次に、次のコードを使用して、ソケットの入力を読み取ります。

    public void run(){
        String packet="";

        while(true){
            try{
                int get_byte=input.read();
                char get_char=(char)get_byte;

                if(get_char!='\u0003'){
                    StorageManager.error_log_add(context,"BluetoothService","Adding packet raw data: \""+get_char+"\"",null);
                    packet+=get_char;
                }
                else{
                    StorageManager.error_log_add(context,"BluetoothService","Packet received:\n"+packet,null);
                    handler.obtainMessage(Activity_Battle_Menu.HANDLER_READ,packet).sendToTarget();
                    packet="";
                }

                if(done && they_done){
                    handler.obtainMessage(Activity_Battle_Menu.HANDLER_READY).sendToTarget();
                }
            }
            catch(IOException e){
                StorageManager.error_log_add(context,TAG,"Connection lost.",e);

                connection_lost();

                break;
            }
        }
    }

一度に1バイトずつデータを読み取り、そのバイトをパケット文字列に追加します。ETX文字に到達すると(送信時にすべての最後に貼り付けます)、完全なパケットが受信され、ハンドラーを介してアクティビティに渡され、そこで処理されます。これが私の書き込みコードです:

    public void write(byte[] buffer){
        try{
            StorageManager.error_log_add(context,"BluetoothService","Writing data:\n"+new String(buffer),null);

            output.write(buffer);
        }
        catch(IOException e){
            StorageManager.error_log_add(context,TAG,"write() on "+socket_type+" connected socket failed.",e);
        }
    }

ご覧のとおり、データ「パケット」が送信されたとき、バイトが受信されたとき、および「パケット」全体が受信されたときに、ログに書き込みます。

これに関連するものがあるかどうかはわかりませんが、Cyanogenmod 7.1(Android 2.3.7)とVirtualBox(Android 2.3.5)で実行されているAndroidx86を使用してNookColorでテストしています。私のアプリのminSdkVersionは8(Android 2.2)です。コンピューターで実行されているAndroidの場合、RocketfishUSBBluetoothアダプターを使用しています。

各インスタンスから送信されるデータのパケットは2つであると想定されています。まず、必要なすべてのゲームデータを保持するデータパケットが送信されます。他のインスタンスのゲームデータが受信されると、アプリは独自のブール値doneをtrueに設定します。また、「完了」パケットを他のインスタンスに送信します。したがって、両方のインスタンスが実行され、もう一方が実行されたことがわかると、すべてのデータが送受信されたことがわかり、両方ともBluetoothスレッドを切断/停止して、データに作用します。

データの送受信時に両方のデバイスにログを記録しているので、ログは何が起こっているのかを教えてくれます。

-最初に、両方のゲームを開始し、Bluetoothアクティビティに移動します(明らかに)。

-次に、エミュレートされたインスタンスからNookインスタンスに接続します。

-エミュレートされたインスタンスは、ゲームデータパケットを送信します。

-Nookインスタンスは、エミュレートされたインスタンスのゲームデータを受信し、独自のデータを送信します(非同期で発生するという理由だけで、これら2つが順番に入れ替わる場合があります)。

-ゲームデータパケットを受信したため、Nookインスタンスは「完了」パケットを送信するようになりました。

-それだ。エミュレートされたインスタンスは、どちらのパケットも受信しません。1バイトも受信せず、input.read()はブロックするだけで、(本来あるべきように)決して到着しない入力を待ちます。

それが私の問題です。次の2つのいずれかが発生しているようです。

  1. データは、例外をスローしなくても、Nookインスタンスのoutput.write()によって送信されることはなく、ログはデータが呼び出されたことを確認します。

  2. エミュレートされたインスタンスのinput.read()によってデータが受信されることはありません。多分それは送信で失われますか?

私の知る限り、私のコードは堅実です。問題はBluetoothに関連しているようです。たぶん、一方または両方のAndroidインスタンスに厄介なBluetooth設定がありますか?

また、まれに(おそらく1/15回)、すべてのパケットが適切に送受信され、ゲームが正常に進行することも付け加えておきます。したがって、問題が発生した場合は通常のみ発生しますが、常に発生するとは限りません。

4

1 に答える 1

1

Bluetoothを搭載した別のAndroidデバイスにアクセスできました。それ以来、ゲームをテストしました。ゲームは接続され、デバイスはデータを正しく交換します。Bluetoothの後に発生するプログラムのバグを他にもいくつか見つけましたが、それはここにもそこにもありません。

以前のNookColorとHTCステータスが連携して機能しました。それで、私は自分のコンピュータに欠陥のあるBluetoothアダプタがあると公式に結論付けています。上記のコードは十分に機能します。

于 2012-05-20T21:13:24.443 に答える