Android開発初心者です。データを分析accelerometer sensor
してサウンドを再生する単純な Android アプリケーションを作成していMediaPlayer
ます。SensorEventListener
実装のためのコード:
class AccelListener implements SensorEventListener {
boolean firstUpdate = true;
volatile boolean stopped = true;
private MediaPlayer mplayer;
//some variables to store calculations
public AccelListener(MediaPlayer mediaplayer) {
mplayer = mediaplayer;
mplayer.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
if (mplayer == mp) {
synchronized (AccelListener.this) {
stopped = true;
}
Log.d("MediaPlayer Callback", "stopped=" + stopped);
}
}
});
}
public void onSensorChanged(SensorEvent event) {
updateAccel(event.values);
if (isAccelChanged()) {
Log.d("Accel Listener", "stopped_before=" + stopped);
synchronized (this) {
if (stopped) {
stopped = false;
firstUpdate = true;
mplayer.start();
Log.d("Accel Listener", "stopped_after=" + stopped);
}
}
}
}
}
問題は、アプリケーションを起動して電話を振ると、音が同時に数回再生されることです。音声ファイルの長さは約 3 ~ 4 秒なので、最後まで再生してから次の揺れに反応するということはありません。
Logcat は次のことを示しています。
08-12 22:16:24.693: D/Accel Listener(5382): stopped_before=true
08-12 22:16:24.693: D/Accel Listener(5382): stopped_after=false
08-12 22:16:24.693: D/Accel Listener(5382): stopped_before=true
08-12 22:16:24.703: D/Accel Listener(5382): stopped_after=false
08-12 22:16:28.777: D/MediaPlayer Callback(5382): stopped=true
08-12 22:16:28.777: D/MediaPlayer Callback(5382): stopped=true
とのクリティカル セクションは同じオブジェクトでロックされているため (プログラムで のインスタンスを 1 つだけ作成しますonSensorChanged()
) 、 への並列アクセスはありません。onCompletion()
AccelListener
stopped
さらに、この変数は として宣言されてvolatile
いるため、クリティカルを入力する人は誰でも新鮮で最新の値を持つ必要があります。しかし、実際には 2 つの異なるスレッドが同時にクリティカル セクションに入るようで、両方とも同じフラグ値を持っています。これはどのように発生する可能性があり、どこが間違っていますか?
PSここにいる男も同じ問題を抱えているようですが、彼の場合の解決策(別のオブジェクトでの同期や の同じインスタンスの使用などMediaPlayer
)はどれもうまくいきませんでした。