摇动发声

时间:2013-04-04 00:38:30

标签: java android accelerometer android-mediaplayer

我正在尝试制作它,以便我摇动它时我的应用会发出声音。我认为我的摇动代码有效,但我遇到了媒体播放器的问题。我跟着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

}

}

2 个答案:

答案 0 :(得分:0)

我的猜测是你在这里混淆了interfaceclass

您的OnCompletionListener 完全没必要。您可以安全地删除它,除非您在代码中的其他位置使用它。

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();
        }
    });
}

答案 1 :(得分:0)

获取以下代码并将其移至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声明是错误的。