3

首先,我对 Android 和编程很陌生,所以请放轻松 ;-) 其次,我认为这个网站是救命稻草!好的,现在进入问题的实质......

在我努力尝试更多地了解 Android 开发和使用用户偏好的过程中,我创建了一个运行良好的小应用程序,并且有许多选项可供用户更改以使其看起来不同。但是,我在尝试设置它以允许自定义抖动检测的灵敏度和抖动检测之间的时间时遇到了一些障碍。

我让一切正常,所以如果用户摇晃手机,它就会做我想做的事。以下是我为摇晃检测所做的基础知识(基于 stackoverflow 上的一篇很棒的帖子(Android:我想摇晃它)):

创建了一个名为 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 所做的一切似乎最终都以 myPrefs 的空值结束。我的主要活动中有一些设置是通过用户首选项控制的,并且我有与上面类似的方法工作得很好。我只是不确定如何将 myPrefs 设置为 ShakeDetector 类中的实际 SharedPreferences 值。

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

4

1 回答 1

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

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

于 2013-02-05T04:11:08.473 回答