我是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/

10-08 21:09