3

第一に、私は Android とプログラミング全般にかなり慣れていないので、簡単に行ってください ;-) 第二に、このサイトは命の恩人だと思います! さて、問題の本質に移りましょう...

Android 開発とユーザー設定の使用についてもっと学ぼうとする私の努力の中で、うまく動作し、ユーザーが変更して外観を変えることができる多くのオプションを持つ小さなアプリケーションを作成しました。ただし、シェイク検出の感度とシェイク検出間の時間をカスタマイズできるようにセットアップしようとして、少し問題が発生しました。

ユーザーが電話を振った場合、私が望むことを行うように、すべてが機能しています。シェイク検出のために私が行ったことの基本は次のとおりです (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 を含めるために試みたすべてのことは、myPrefs の null 値で終わるようです。メイン アクティビティには、ユーザー設定によって制御されるいくつかの設定があり、上記と同様の方法で問題なく動作します。ShakeDetector クラスで myPrefs を実際の 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 に答える