0

我正在努力做到这一点,以便我的应用程序在我摇动它时播放声音。我认为我的抖动代码有效,但我在使用媒体播放器时遇到了问题。我按照peceps 对震动的回答,并使用Chris 对声音的最终回答。显然我没有把它变成 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

}

}
4

2 回答 2

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();
        }
    });
}
于 2013-04-04T01:11:28.500 回答
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 文档

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

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

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

于 2013-04-04T03:02:56.327 回答