3

を使用してAndroidデータをarduinoに送信しようとしています。私のGUIには加速度計の読み取り値Bluetoothが含まれています。fromメソッドにデータを書き込むと、すべてが正常に形成され、すべてが正常に機能しているため、データはいつでもarduinoに転送されます。 SeekBarを変更します。SeekBarSocketsOutputStreamSocketonSeekBarChanged()

 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        if(seekBar.getId() == R.id.seekBar)
        {
            speed.setText(String.valueOf(progress));
            String outputData = String.valueOf(progress)+",";
            try
            {
            streams.write(outputData.getBytes());//writes data to OutputStream of Socket
            }catch (Exception e){
                Log.d("RTR","Sockets not yet formed");
            }

        }
    }

問題は、現在の値とAccelerometer一緒にデータを継続的に送信する必要があることです。そこで、加速度計のfromメソッドSeekBarに書き込みを試みました。OutputStreamSocketonSensorChanged(SensorEvent event)Result:Program not responding.

public void onSensorChanged(SensorEvent event) {

        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
        {
            float accXYZ[] = event.values;

            float accX = accXYZ[0];
            float accY = accXYZ[1];
            float accZ = accXYZ[2];

            x.setText(String.format("%.2f",accX));
            y.setText(String.format("%.2f",accY));
            z.setText(String.format("%.2f",accZ));

            String outputData = x.getText().toString()+","+speed.getText().toString()+";";

            try{
                  streams.write(outputData.getBytes());
            }catch (Exception e){
                //Log.d("RTR","X");
            }

        }
    }

これは過負荷になりすぎることを理解しています。データを継続的に送信するには、メソッドに無限ループをUI Thread使用してを作成する必要があると思います。加速度計とSeekBarデータをこの新しいスレッドに継続的に送信するにはどうすればよいですか。new Threadrun()

または、この新しいスレッドからUIThreadの加速度計とSeekBarのデータを収集する必要があります。

In Short, how do I get data from UIThread to this new Thread.

私の問題と私の現在の手順の合併症についてあなたが知っているすべての可能な解決策を提供してください。

4

1 に答える 1

6

これを行う良い方法は、組み込みのLooperクラスを使用することです。Looperは、AndroidのUIスレッドを強化するメッセージキューシステムであり、独自のスレッドでも使用できます。設計方法の優れている点は、ガベージコレクションの負荷がほとんど発生しないことです(使用する引数の種類によっては、何も発生しない場合があります)。

私はこのフリーハンドを書いているので、それを機能させるには少しハックする必要がありますが、最終的には次のようになります。

class LooperThread extends Thread {
    private static final int MSG_TYPE_OUTPUT_DATA = 0;
    private Handler mHandler;
    private volatile OutputStream mOutputStream;

    public void run() {
        Looper.prepare();

        mHandler = new Handler() {
            public void handleMessage(Message msg) {
                if (msg.what == MSG_TYPE_OUTPUT_DATA
                    && mOutputStream != null) {
                    //try-catch left out for brevity
                    mOutputStream.write(msg.obj.getBytes());
                }
            }
        };

        Looper.loop();
    }

    public void submitReading(String outputData) {
        mHandler.sendMessage(mHandler.obtainMessage(MSG_TYPE_OUTPUT_DATA, outputData);
    }
}

セットアップコードは次のようになります。

private void setup() {
    Socket sock = setupBluetoothConnection();
    this.looperThread = new LooperThread();
    this.looperThread.setOutputStream(sock.getOutputStream());
    this.looperThread.start();
}

最後に、センサーイベントハンドラー:

public void onSensorChanged(SensorEvent event) {

    if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
    {
        // snip...
        String outputData = x.getText().toString()+","+speed.getText().toString()+";";

        this.looperThread.submitReading(outputData);
    }
}

これにより、メッセージを可能な限り高速に処理し、他のスレッドからスレッドセーフな方法でメッセージを送信できる単一のバックグラウンドスレッドが提供されます。それらは順番に処理されます。

完了したら、ルーパースレッドを適切にシャットダウンするように注意し、ソケット接続が失われた場合に処理できることを確認する必要があります。

1秒あたりのメッセージの特定の速度に調整する必要がある場合は、状況が少し複雑になります。OutputStream.writeはブロッキング操作であるため、便宜上省略しました。最後にメッセージを処理したことをインスタンスフィールドに登録しSystem.nanoTime()、handleMessage()メソッド内で、十分な時間が経過する前に次のメッセージが届くたびに、待機できるまでの待機時間を計算します。メッセージを処理します。これは、sendMessageDelayed()を使用して「送信」側で処理するよりもはるかに簡単です。

于 2013-02-17T14:30:39.453 に答える