我是 Android 开发的新手。我正在构建一个简单的 Android 应用程序,它可以分析accelerometer sensor
数据并使用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
onSensorChanged()
和中的关键部分onCompletion()
被锁定在同一个对象上(我AccelListener
在程序中只创建了一个实例),所以不应该并行访问stopped
.
此外,此变量被声明为volatile
,因此任何输入关键变量的人都应该有一个新的、最新的值。但似乎两个不同的线程实际上同时进入了临界区,它们都具有相同的标志值。这怎么可能发生,我错在哪里?
PS这里的那个人似乎也有同样的问题,但没有一个解决方案MediaPlayer
适合我。