私は今この課題に取り組んでおり、さまざまな可能性を模索し、「キューイング」の発生場所を絞り込んでいます。私が何をしようとしているのかをまず説明しましょう。onSensorChanged()のキューイングが矛盾しないようにする
何をしたいですか?
ウェアラブルサービス(Sony Smartwatch 3で動作)を搭載したAndroidアプリ(Google Pixelで実行中)を作成して、スマートウォッチからできるだけ早くセンサーデータを取得し、その結果をVerboseとしてログに記録します。現在のところ、TYPE_ROTATION_VECTORのデータは約150Hzです。このデータは、PrintWriterを使用してチャネル(出力ストリーム)を介して送信され、BufferReaderを使用して同じチャネル(入力ストリーム)上の電話機によって収集されます。私はChannelApiを使用しています。DataApiは配信を確実にしますが、私の目的はできるだけ早くセンサーデータをリアルタイムで提供することです。データ損失はそれほど重要ではありません。私は現在、別のアプリケーションでこれを使用するためにノートパソコンのADBを読んでいます。
問題点は何ですか?
プログラムのいくつかの段階でシステム時間を取得した後、データのキューイングはADB接続の障害でもなく、入力ストリームまたは出力ストリームもプリントライタでもないことがわかりました。 sensorEvent
が発生したので、機能onSensorChanged()
は即座に呼び出されないようです。下記の時間はsensorListenerがSENSOR_DELAY_GAME(に設定し、各onSensorChanged()
イベントのために、データとして送信もSENSOR_DELAY_FASTESTを占めている、説明するために、
- を1行目:
onSensorChanged()
が - 第二と呼ばれている時計に
System.currentTimeMillis()
行:sensorEvent
から(ミリ秒ナノから行く1000000で割った値)event.timestamp
これは、いくつかのセンサ読取値の概要:
1479407287638; 687629;
1479407287638; 687649;
1479407287681; 687669;
1479407287681; 687689;
1479407287718; 687709;
1479407287718; 687729;
1479407287768; 687749;
1479407287768; 687769;
1479407287810; 687789;
1479407287811; 687809;
あなたが得る時間の間の違いを見てみると:
- -
0; 20
49; 20
0; 20
37; 20
0; 20
50; 20
0; 20
42; 20
1; 20
あなたが見ることができるように、sensorTimestamp
は読みが20msごとがあることを示しています。ただし、onSensorChanged()
は、同じ間隔で、または少なくとも一貫性で呼び出されません。指摘すると、たとえ高速であっても、チャネルとその入出力ライターは、より長い期間または時間であっても、バイト/メッセージの量に追いつくことができます。
私は何を試しましたか?
私はウェアラブルアプリを書いonSensorChanged
からすべてのタスクを削除しようとしましたが、最初は他の場所で開始されたスレッド
if (data_transfer) { // if interaction is initiated
new Thread(new convertAndSend(sensorName,timestamp,accuracy,values)).run();
}
でそれらを実行onSensorChanged
public void onSensorChanged(SensorEvent event) {
final int accuracy = event.accuracy;
final long timestamp = event.timestamp;
final float[] values = event.values;
final String sensorName = event.sensor.getStringType();
if (data_transfer) { // if interaction is initiated
printWriter.println(message);
}
}
からすべてのタスクを削除しようとしました活動として、私はまた(バックグラウンドで実行されている)サービスに変換
public class SensorService extends Service implements SensorEventListener {
...
public void onSensorChanged(SensorEvent event) {
client.sendSensorData(event.sensor.getType(), event.accuracy, event.timestamp/1000000, event.values); //client takes care of outputstream
}
}
最後に、を別のスレッド(thisとthisに基づいて実装することを考えました。そのため、アクティビティスレッドまたはサービススレッドの影響を受けません。しかし、これも前に述べたのと同じ課題/挑戦を示しました。
public class SensorListenerThread implements Runnable {
private static final String TAG = "SensorService";
private final static int SENS_ROTATION_VECTOR = Sensor.TYPE_ROTATION_VECTOR;
SensorManager mSensorManager;
@Override
public void run() {
Log.d("RunTag", Thread.currentThread().getName()); // To display thread
mSensorManager = ((SensorManager)getSystemService(SENSOR_SERVICE));
Looper.prepare();
Handler handler = new Handler(){
// process incoming messages here??
};
Sensor rotationVectorSensor = mSensorManager.getDefaultSensor(SENS_ROTATION_VECTOR);
MySensorListener msl = new MySensorListener();
mSensorManager.registerListener(msl, rotationVectorSensor, SensorManager.SENSOR_DELAY_FASTEST, handler);
Looper.loop();
}
private class MySensorListener implements SensorEventListener {
public void onAccuracyChanged (Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent sensorEvent) {
Log.d("ListenerTag", Thread.currentThread().getName()); // To display thread
}
}
}
ヘルプ!
私の理解は、onSensorChanged
イベントが呼び出されますが、センサーのタイムスタンプと同じ時刻に表示されないということです。速度とチャンネルの使用は非常にうまく動作しますが、この問題を回避する方法はありません。私は私の心の中に計画Bを持っています:私は私のラップトップで実行しているプログラムを計算/調整するためにセンサーのタイムスタンプを使用することができます。しかし、私は通信の遅れ(センサ - >ラップトップアプリケーションから調整するのが好きですが、これは毎回変更される変数である可能性があります)や、通信の不一致を調整しない方が望ましいです(値の印刷、各読みについて計算する必要があります)。
私はこの長い(申し訳ありません!)ストーリーが意味を持ち、誰かが私を助けたり正しい方向に向けることを願っています。
もっと複雑なやりとりを処理するには、[ワーカースレッド](https://developer.android.com/guide/components/processes-and-threads.html)の使用をチェックするとよいでしょう。与えられたドキュメントで述べたように、UIスレッドから渡されたメッセージを処理するには、ワーカースレッドで[Handler](https://developer.android.com/reference/android/os/Handler.html)を使用することを検討してください。おそらく最も良い解決策は、[AsyncTaskクラス](https://developer.android.com/reference/android/os/AsyncTask.html)を拡張することです。これは、UIと対話する必要があるワーカースレッドタスクの実行を簡略化します。 – Teyam
こんにちは@Teyam、私はonSensorchanged()メッセージを受け取るためだけにワーカースレッドを実装しました。もうUIスレッドに干渉しません。しかし、この場合にもメッセージは一定の時間間隔で受信されます。私は、センサーメッセージ(タイムスタンプ)とメッセージの受信(onSensorChanged)の間の時間が一貫しているような方法でコードを構築することが可能であることを期待していました。私は現在、センサーのタイムスタンプを見て、出現の対応する時間を計算する必要があります。 – Dave