【问题标题】:Shake to play sound摇一摇播放声音
【发布时间】:2013-04-04 00:38:29
【问题描述】:

我正在努力让我的应用在我摇晃它时播放声音。我认为我的抖动代码有效,但我在使用媒体播放器时遇到了问题。我关注了peceps' answer for shake 并使用了Chris' final answer for sound. 显然我没有将其设为onClick 而是onShake。

这是我的活动代码。 (我得到的唯一错误是 mp)

package com.grifball.info;

import com.grifball.info.ShakeDetector.OnShakeListener;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;

public class HammerActivity extends Activity {

private ShakeDetector mShakeDetector;
private SensorManager mSensorManager;

// Declare the MediaPlayer object
private MediaPlayer mMediaPlayer;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.hammer_page);

    // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mShakeDetector = new ShakeDetector();  

    mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
        public void onShake() {
            // Initialize media player
            mMediaPlayer = MediaPlayer.create(HammerActivity.this, R.raw.hammer);

            // Add OnCompletionListener to release the 
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mMediaPlayer.release();
  }
            });
            mMediaPlayer.start();
    });
    };

    @Override
    protected void onResume() {
      super.onResume();
      mSensorManager.registerListener(mShakeDetector,
          mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
          SensorManager.SENSOR_DELAY_UI);
    }

    @Override
    protected void onPause() {
      mSensorManager.unregisterListener(mShakeDetector);
      super.onStop();
    }}

这是我的 ShakeDetector 代码。

package com.grifball.info;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;


/**
 * Listener that detects shake gesture.
 */
public class ShakeDetector implements SensorEventListener {


  /** Minimum movement force to consider. */
  private static final int MIN_FORCE = 10;

  /**
   * Minimum times in a shake gesture that the direction of movement needs to
   * change.
   */
  private static final int MIN_DIRECTION_CHANGE = 3;

  /** Maximum pause between movements. */
  private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;

  /** Maximum allowed time for shake gesture. */
  private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400;

  /** Time when the gesture started. */
  private long mFirstDirectionChangeTime = 0;

  /** Time when the last movement started. */
  private long mLastDirectionChangeTime;

  /** How many movements are considered so far. */
  private int mDirectionChangeCount = 0;

  /** The last x position. */
  private float lastX = 0;

  /** The last y position. */
  private float lastY = 0;

  /** The last z position. */
  private float lastZ = 0;

  /** OnShakeListener that is called when shake is detected. */
  private OnShakeListener mShakeListener;

  /**
   * Interface for shake gesture.
   */
  public interface OnShakeListener {

    /**
     * Called when shake gesture is detected.
     */
    void onShake();
  }

  public void setOnShakeListener(OnShakeListener listener) {
    mShakeListener = listener;
  }

  @Override
  public void onSensorChanged(SensorEvent se) {
    // get sensor data
    float x = se.values[SensorManager.DATA_X];
    float y = se.values[SensorManager.DATA_Y];
    float z = se.values[SensorManager.DATA_Z];

// calculate movement
float totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);

if (totalMovement > MIN_FORCE) {

  // get time
  long now = System.currentTimeMillis();

  // store first movement time
  if (mFirstDirectionChangeTime == 0) {
    mFirstDirectionChangeTime = now;
    mLastDirectionChangeTime = now;
  }

  // check if the last movement was not long ago
  long lastChangeWasAgo = now - mLastDirectionChangeTime;
  if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE) {

    // store movement data
    mLastDirectionChangeTime = now;
    mDirectionChangeCount++;

    // store last sensor data 
    lastX = x;
    lastY = y;
    lastZ = z;

    // check how many movements are so far
    if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE) {

      // check total duration
      long totalDuration = now - mFirstDirectionChangeTime;
      if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) {
        mShakeListener.onShake();
        resetShakeParameters();
      }
    }

  } else {
    resetShakeParameters();
  }
}
  }

  /**
   * Resets the shake parameters to their default values.
   */
  private void resetShakeParameters() {
    mFirstDirectionChangeTime = 0;
    mDirectionChangeCount = 0;
    mLastDirectionChangeTime = 0;
    lastX = 0;
    lastY = 0;
    lastZ = 0;
  }

  @Override
  public void onAccuracyChanged(Sensor sensor, int accuracy) {
  }

}

这是我的 OnCompletionListener 代码。 包 com.grifball.info;

import android.media.MediaPlayer;

public class OnCompletionListener {

public void onCompletion(MediaPlayer mp) {
    // TODO Auto-generated method stub

}

}

【问题讨论】:

  • “我得到的唯一错误是 mp”是什么意思?
  • 主活动中onShake下的所有mp和mp.。查看 chris 的音频设置,除了它是 under 和 onClick 而不是 onShake。 “mp 无法解析”
  • 嗯...你需要在private SensorManager mSensorManager;下面声明它private MediaPlayer mp;但这是一个编译错误...是你的问题吗?
  • 现在我收到错误“mp.setOnCompletionListener(new OnCompletionListener() {”MediaPlayer 类型中的方法 setOnCompletionListener(MediaPlayer.OnCompletionListener) 不适用于参数 (new OnCompletionListener(){} )

标签: java android accelerometer android-mediaplayer


【解决方案1】:

我猜你在这里混淆了interfaceclass

您的OnCompletionListener class 完全没有必要。除非您在代码中的其他地方使用它,否则您可以安全地删除它。

MediaPlayer.setOnCompletionListener()MediaPlayer.OnCompletionListener 类型的接口 作为参数。此界面已为您存在。

至于您的其余代码。你永远不会声明你的 MediaPlayer 对象mp。它只是突然出现在onShake() 中。

public class HammerActivity extends Activity {

private ShakeDetector mShakeDetector;
private SensorManager mSensorManager;

// Declare the MediaPlayer object
private MediaPlayer mMediaPlayer;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mShakeDetector = new ShakeDetector();  

    mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
        public void onShake() {
            // Initialize media player
            mMediaPlayer = MediaPlayer.create(HammerActivity.this, R.raw.hammer);

            // Add OnCompletionListener to release the 
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mMediaPlayer.release();
                }
            });
            mMediaPlayer.start();
        }
    });
}

【讨论】:

  • 我将有不止一个页面使用相同的方法,但我会尝试一下
  • 如果这是您的 OnCompletionListener 课程的目标,那么我建议您重命名它。目前它有点“接口名称”,这只会造成混乱;)
  • 是的,它仍然无法正常工作,我只是想让它在我摇晃它时发出声音 =(
  • 您遇到了什么样的错误?请在您的原始帖子中发布您更新的代码;)
  • 我没有收到任何错误,只是摇晃时它没有播放声音。
【解决方案2】:

获取下面的代码并将其移至您的 onCreate() 方法

  mMediaPlayer = MediaPlayer.create(HammerActivity.this, R.raw.hammer);

            // Add OnCompletionListener to release the 
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mMediaPlayer.release();
  }
            });

也可以看看SensorManager documentation

protected void onResume() {
         super.onResume();
         mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
     }

     protected void onPause() {
         super.onPause();
         mSensorManager.unregisterListener(this);
     }

请注意:我只是从 SensorManager 文档中剪切并粘贴代码。您必须使其适应您的代码;我的主要观点是您的 onPause 声明是错误的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-11
    • 1970-01-01
    • 2018-10-15
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多