Android:在Shake Listener类中使用SharedPreferences

时间:2013-01-31 18:21:16

标签: android sharedpreferences

首先,我对Android和编程很新,所以请轻松一下;-) 其次,我认为这个网站是一个救星! 好的,现在问题的关键......

在努力学习更多关于Android开发和使用用户首选项的过程中,我创建了一个可以正常运行的小应用程序,并且有许多选项可供用户更改以使其看起来不同。然而,我遇到了一些小问题试图让它设置为允许定制震动检测的灵敏度和震动检测之间的时间。

我有一切正常工作,以便如果用户摇动手机它会做我想要的。以下是我为Shake Detection所做的基础知识(基于stackoverflow(Android: I want to shake it)上的精彩帖子):

创建一个名为ShakeDetector的新类,并将以下代码放入其中:

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

public class ShakeDetector implements SensorEventListener {

/*
 * The gForce that is necessary to register as shake.
 * Must be greater than 1G (one earth gravity unit).
 * You can install "G-Force", by Blake La Pierre
 * from the Google Play Store and run it to see how
 *  many G's it takes to register a shake
 */
private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;
private static final int SHAKE_SLOP_TIME_MS = 500;
private static final int SHAKE_COUNT_RESET_TIME_MS = 3000;

private OnShakeListener mListener;
private long mShakeTimestamp;
private int mShakeCount;

public void setOnShakeListener(OnShakeListener listener) {
    this.mListener = listener;
}

public interface OnShakeListener {
    public void onShake(int count);
}

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

@Override
public void onSensorChanged(SensorEvent event) {

    if (mListener != null) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        float gX = x / SensorManager.GRAVITY_EARTH;
        float gY = y / SensorManager.GRAVITY_EARTH;
        float gZ = z / SensorManager.GRAVITY_EARTH;

        // gForce will be close to 1 when there is no movement.
        float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);

        if (gForce > SHAKE_THRESHOLD_GRAVITY) {
            final long now = System.currentTimeMillis();
            // ignore shake events too close to each other (500ms)
            if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
                return;
            }

            // reset the shake count after 3 seconds of no shakes
            if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
                mShakeCount = 0;
            }

            mShakeTimestamp = now;
            mShakeCount++;

            mListener.onShake(mShakeCount);
        }
    }
}
}

接下来,我将以下内容放在我的主要活动的onCreate方法中:

        // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager
            .getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mShakeDetector = new ShakeDetector();
    mShakeDetector.setOnShakeListener(new OnShakeListener() {

        @Override
        public void onShake(int count) {
            /*
             * The following method, "handleShakeEvent(count):" is a stub //
             * method you would use to setup whatever you want done once the
             * device has been shook.
             */
            handleShakeEvent(count);
        }
    });

同样,在这一点上,一切都按预期工作。但是,我不知道该怎么做是在ShakeDetector类中设置SHAKE_THRESHOLD_GRAVITY和SHAKE_COUNT_RESET_TIME_MS来使用我已经在应用程序中设置的共享首选项。所有内容都在应用程序中配置(并且可以正常工作)以允许用户进入并为这两个设置选择不同的值,但我不确定如何将SharedPreferences设置从活动传递到此类。我尝试了许多不同的事情而没有运气,我似乎无法在网上找到任何有关如何做到这一点的信息。这可能是相当简单的事情,但我没有太多运气搞清楚。

简而言之,我尝试在ShakeDetector类中创建另一个方法(例如setShakePreferences()),然后在其中放入类似于以下内容的代码:

    public void setShakePreferences() {

    shake_sensitivity = myPrefs.getString(SHAKE_THRESHOLD_GRAVITY2, "2.7");
    shake_time_between = myPrefs.getString(SHAKE_COUNT_RESET_TIME_MS2, "3000");
    float shake_threshold_gravity = Float.valueOf(shake_sensitivity);
    int shake_count_reset_time_ms = Integer.valueOf(shake_time_between);

}

我尝试过各种不同的方式传递SharedPreferences(例如setShakePreferences(SharedPreferences myPrefs)),然而,我试图让myPrefs实际上只包含SharedPreferences的所有内容似乎最终都是以null为空myPrefs。我的主要活动中有一些设置是通过用户首选项控制的,我有类似于上面的方法,工作得很好。我只是不确定如何将myPrefs设置为ShakeDetector类中的实际SharedPreferences值。

请帮忙。详细的解决方案代码示例最能帮助我了解如何实现这一目标。谢谢!

1 个答案:

答案 0 :(得分:0)

在阅读了有关如何实现接口的更多内容后想出这个。一旦我弄明白这一点,实际上非常简单(不知道为什么我没有抓住它开始)。

基本上,我修改onCreate()以传递sharedPreferences,如下所示(只是添加了“this.myPrefs”作为参数):

        // ShakeDetector initialization
    mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    mShakeDetector = new ShakeDetector();
    mShakeDetector.setOnShakeListener(new OnShakeListener() {

        @Override
        public void onShake(int count) {
            /*
             * The following method, "handleShakeEvent(count):" is a stub //
             * method you would use to setup whatever you want done once the
             * device has been shook.
             */
            handleShakeEvent(count);
        }
    }, this.myPrefs); // <<<--- ADDED IT HERE

然后我必须修改ShakeDetector类中的setOnShakeListener以接受myPrefs作为参数并添加所有内容以便它能正确处理变量。这就是我最终的结果:

import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.FloatMath;
import android.util.Log;

public class ShakeDetector implements SensorEventListener {

/*
 * The gForce that is necessary to register as shake.
 * Must be greater than 1G (one earth gravity unit).
 * You can install "G-Force", by Blake La Pierre
 * from the Google Play Store and run it to see how
 *  many G's it takes to register a shake
 */
private static final String SHAKE_THRESHOLD_GRAVITY = "<replace this with the android:key value you have configured in you preferences XML file.>";
private static final String SHAKE_COUNT_RESET_TIME_MS = "<replace this with the android:key value you have configured in you preferences XML file.>";
private static final String SHAKE_SLOP_TIME_MS = "<replace this with the android:key value you have configured in you preferences XML file.>";

private OnShakeListener mListener;
private long mShakeTimestamp;
private int mShakeCount;
private SharedPreferences myPrefs;

public void setOnShakeListener(OnShakeListener listener, SharedPreferences myPrefs) {
    this.mListener = listener;
    this.myPrefs = myPrefs;
}

public interface OnShakeListener {
    public void onShake(int count);
}

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

@Override
public void onSensorChanged(SensorEvent event) {

    if (mListener != null) {
        float x = event.values[0];
        float y = event.values[1];
        float z = event.values[2];

        float gX = x / SensorManager.GRAVITY_EARTH;
        float gY = y / SensorManager.GRAVITY_EARTH;
        float gZ = z / SensorManager.GRAVITY_EARTH;

        // gForce will be close to 1 when there is no movement.
        float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);

        if (gForce > Float.parseFloat(myPrefs.getString(SHAKE_THRESHOLD_GRAVITY, "2.7F"))) {
            final long now = System.currentTimeMillis();
            // ignore shake events too close to each other (500ms)
            if (mShakeTimestamp + Integer.parseInt(myPrefs.getString(SHAKE_SLOP_TIME_MS, "500")) > now) {
                return;
            }

            // reset the shake count after 3 seconds of no shakes
            if (mShakeTimestamp + Integer.parseInt(myPrefs.getString(SHAKE_COUNT_RESET_TIME_MS, "3000")) < now) {
                mShakeCount = 0;
            }

            mShakeTimestamp = now;
            mShakeCount++;

            mListener.onShake(mShakeCount);
        }
    }
}
}

希望如果有人想知道这会有所帮助。