我是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
,因此任何输入严重阈值的人都应具有最新的值。但是,似乎两个不同的线程实际上同时进入了关键部分,两个线程都具有相同的标志值。这怎么可能发生,我在哪里错了?附言here上的那个人似乎有相同的问题,但是针对他的情况的任何解决方案(例如在单独的对象上进行同步或使用
MediaPlayer
的相同实例)都不适合我。 最佳答案
假设您在“ isAccelChanged()if”内部输入,则无论“ stop”的值是多少(无论是在if还是在同步块之外),您始终在“ onSensorChanged”内启动播放器中的声音。
如果您确定只有一个实例,则可以摆脱“同步”实例。
检查一下,然后回复。
关于java - 关键部分在onSensorChanged()中不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11924873/