How to refresh app upon shaking the device?

前端 未结 16 1742
眼角桃花
眼角桃花 2020-11-22 13:42

I need to add a shake feature that will refresh my Android application.

All I find of documentation involves implementing the SensorListener, but Eclips

相关标签:
16条回答
  • 2020-11-22 14:20

    I am developing a motion-detection and shake-detection app for my university project.

    Besides the original target of the application, I am splitting the library part (responsible for motion and shake detection) from the app. The code is free, available on SourceForge with the project name "BenderCatch". Documentation I am producing will be ready around mid-september. http://sf.net/projects/bendercatch

    It uses a more precise way to detect shake: watches BOTH the difference of force between SensorEvents AND the oscillations present in X and Y axis when you perform a shake. It can even make a sound (or vibrate) on each oscillation of the shake.

    Feel free to ask me more by e-mail at raffaele [at] terzigno [dot] com

    0 讨论(0)
  • 2020-11-22 14:21

    Here's yet another implementation that builds on some of the tips in here as well as the code from the Android developer site.

    MainActivity.java

    public class MainActivity extends Activity {
    
        private ShakeDetector mShakeDetector;
        private SensorManager mSensorManager;
        private Sensor mAccelerometer;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // ShakeDetector initialization
            mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
            mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            mShakeDetector = new ShakeDetector(new OnShakeListener() {
                @Override
                public void onShake() {
                    // Do stuff!
                }
            });
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
        }
    
        @Override
        protected void onPause() {
            mSensorManager.unregisterListener(mShakeDetector);
            super.onPause();
        }   
    }
    

    ShakeDetector.java

    package com.example.test;
    
    import android.hardware.Sensor;
    import android.hardware.SensorEvent;
    import android.hardware.SensorEventListener;
    
    public class ShakeDetector implements SensorEventListener {
    
        // Minimum acceleration needed to count as a shake movement
        private static final int MIN_SHAKE_ACCELERATION = 5;
    
        // Minimum number of movements to register a shake
        private static final int MIN_MOVEMENTS = 2;
    
        // Maximum time (in milliseconds) for the whole shake to occur
        private static final int MAX_SHAKE_DURATION = 500;
    
        // Arrays to store gravity and linear acceleration values
        private float[] mGravity = { 0.0f, 0.0f, 0.0f };
        private float[] mLinearAcceleration = { 0.0f, 0.0f, 0.0f };
    
        // Indexes for x, y, and z values
        private static final int X = 0;
        private static final int Y = 1;
        private static final int Z = 2;
    
        // OnShakeListener that will be notified when the shake is detected
        private OnShakeListener mShakeListener;
    
        // Start time for the shake detection
        long startTime = 0;
    
        // Counter for shake movements
        int moveCount = 0;
    
        // Constructor that sets the shake listener
        public ShakeDetector(OnShakeListener shakeListener) {
            mShakeListener = shakeListener;
        }
    
        @Override
        public void onSensorChanged(SensorEvent event) {
            // This method will be called when the accelerometer detects a change.
    
            // Call a helper method that wraps code from the Android developer site
            setCurrentAcceleration(event);
    
            // Get the max linear acceleration in any direction
            float maxLinearAcceleration = getMaxCurrentLinearAcceleration();
    
            // Check if the acceleration is greater than our minimum threshold
            if (maxLinearAcceleration > MIN_SHAKE_ACCELERATION) {
                long now = System.currentTimeMillis();
    
                // Set the startTime if it was reset to zero
                if (startTime == 0) {
                    startTime = now;
                }
    
                long elapsedTime = now - startTime;
    
                // Check if we're still in the shake window we defined
                if (elapsedTime > MAX_SHAKE_DURATION) {
                    // Too much time has passed. Start over!
                    resetShakeDetection();
                }
                else {
                    // Keep track of all the movements
                    moveCount++;
    
                    // Check if enough movements have been made to qualify as a shake
                    if (moveCount > MIN_MOVEMENTS) {
                        // It's a shake! Notify the listener.
                        mShakeListener.onShake();
    
                        // Reset for the next one!
                        resetShakeDetection();
                    }
                }
            }
        }
    
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // Intentionally blank
        }
    
        private void setCurrentAcceleration(SensorEvent event) {
            /*
             *  BEGIN SECTION from Android developer site. This code accounts for 
             *  gravity using a high-pass filter
             */
    
            // alpha is calculated as t / (t + dT)
            // with t, the low-pass filter's time-constant
            // and dT, the event delivery rate
    
            final float alpha = 0.8f;
    
            // Gravity components of x, y, and z acceleration
            mGravity[X] = alpha * mGravity[X] + (1 - alpha) * event.values[X];
            mGravity[Y] = alpha * mGravity[Y] + (1 - alpha) * event.values[Y];
            mGravity[Z] = alpha * mGravity[Z] + (1 - alpha) * event.values[Z];
    
            // Linear acceleration along the x, y, and z axes (gravity effects removed)
            mLinearAcceleration[X] = event.values[X] - mGravity[X];
            mLinearAcceleration[Y] = event.values[Y] - mGravity[Y];
            mLinearAcceleration[Z] = event.values[Z] - mGravity[Z];
    
            /*
             *  END SECTION from Android developer site
             */
        }
    
        private float getMaxCurrentLinearAcceleration() {
            // Start by setting the value to the x value
            float maxLinearAcceleration = mLinearAcceleration[X];
    
            // Check if the y value is greater
            if (mLinearAcceleration[Y] > maxLinearAcceleration) {
                maxLinearAcceleration = mLinearAcceleration[Y];
            }
    
            // Check if the z value is greater
            if (mLinearAcceleration[Z] > maxLinearAcceleration) {
                maxLinearAcceleration = mLinearAcceleration[Z];
            }
    
            // Return the greatest value
            return maxLinearAcceleration;
        }
    
        private void resetShakeDetection() {
            startTime = 0;
            moveCount = 0;
        }
    
        // (I'd normally put this definition in it's own .java file)
        public interface OnShakeListener {
            public void onShake();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 14:22

    I have tried several implementations, but would like to share my own. It uses G-force as unit for the threshold calculation. It makes it a bit easier to understand what is going on, and also with setting a good threshold.

    It simply registers a increase in G force and triggers the listener if it exceeds the threshold. It doesn't use any direction thresholds, cause you don't really need that if you just want to register a good shake.

    Of-course you need the standard registering and UN-registering of this listener in the Activity.

    Also, to check what threshold you need, I recommend the following app (I am not in any way connected to that app)

        public class UmitoShakeEventListener implements SensorEventListener {
    
        /**
         * The gforce that is necessary to register as shake. (Must include 1G
         * gravity)
         */
        private final float shakeThresholdInGForce = 2.25F;
    
        private final float gravityEarth = SensorManager.GRAVITY_EARTH;
    
        private OnShakeListener listener;
    
        public void setOnShakeListener(OnShakeListener listener) {
            this.listener = listener;
        }
    
        public interface OnShakeListener {
            public void onShake();
        }
    
        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // ignore
    
        }
    
        @Override
        public void onSensorChanged(SensorEvent event) {
    
            if (listener != null) {
                float x = event.values[0];
                float y = event.values[1];
                float z = event.values[2];
    
                float gX = x / gravityEarth;
                float gY = y / gravityEarth;
                float gZ = z / gravityEarth;
    
                //G-Force will be 1 when there is no movement. (gravity)
                float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ); 
    
    
    
                if (gForce > shakeThresholdInGForce) {
                    listener.onShake();
    
                }
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 14:24

    You should subscribe as a SensorEventListener, and get the accelerometer data. Once you have it, you should monitor for sudden change in direction (sign) of acceleration on a certain axis. It would be a good indication for the 'shake' movement of device.

    0 讨论(0)
提交回复
热议问题