まず、少しの理論
Androidのドキュメントでは、SENSOR_ORIENTATIONの代わりにメソッドを使用するように提供されています
getOrientation (float[] R, float[] values)
このメソッドは2つのパラメーターを取ります。
- R-RotationMatrixまたはデバイス回転行列。
- 値-ラジアン単位のデバイスの傾斜角が書き込まれる、float型の3つの要素の配列。
したがって、目標を達成するには、まさに回転行列を取得する必要があります。 そして、あなたは別の方法からそれを得ることができます:
getRotationMatrix (float[] R, float[] I, float[] gravity, float[] geomagnetic)
最初の2つの配列のこのメソッドは、(地球の磁極?)からのデバイスの回転行列と偏差行列を配置します。 これを行うには、加速度センサーと地磁気センサーからデータを転送する必要もあります。 幸いなことに、TYPE_ACCELEROMETERとTYPE_MAGNETIC_FIELDは非推奨ではありません。 したがって、私たちは彼らから証言を取ります。
練習に移りましょう
前の例と同じレイアウトを取ることができます。 ここにあります:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <LinearLayout android:id="@+id/linearLayout1" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/textView1" android:layout_width="60dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text=" XY" /> <TextView android:id="@+id/xyValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text="0" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout2" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/textView3" android:layout_width="60dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text=" XZ" /> /> <TextView android:id="@+id/xzValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text="0" /> </LinearLayout> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/textView5" android:layout_width="60dp" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text=" ZY" /> <TextView android:id="@+id/zyValue" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:textSize="25dp" android:text="0" /> </LinearLayout> </LinearLayout>
メインアクティビティで、変数を宣言します。
private final SensorManager msensorManager; // private float[] rotationMatrix; // private float[] accelData; // private float[] magnetData; // private float[] OrientationData; // private TextView xyView; private TextView xzView; private TextView zyView;
onCreateメソッドは、SensorEventListenerクラスのメソッドを実装する必要があるため、その宣言は変更されます。
public class Main extends Activity implements SensorEventListener{
また、2つの必須メソッドonAccuracyChangedおよびonSensorChangedが追加されます。
そして、 setContentViewの前に次のように記述します。
msensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); rotationMatrix = new float[16]; accelData = new float[3]; magnetData = new float[3]; OrientationData = new float[3]; xyView = (TextView) findViewById(R.id.xyValue); // xzView = (TextView) findViewById(R.id.xzValue); // zyView = (TextView) findViewById(R.id.zyValue); //
私の最後の投稿を読んだ場合、新しいものは何も見ていません。 そうでない場合は、最初の行でセンサーマネージャーのオブジェクトを取得することを知っておく必要があります。
次に、必要なセンサーデータを明確にするonResumeメソッドを作成します。
@Override protected void onResume() { super.onResume(); msensorManager.registerListener(this, msensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI ); msensorManager.registerListener(this, msensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_UI ); }
ここで、registerListenerメソッドに、必要なセンサーのタイプ( センサー指定の完全なリスト )とデータ更新の頻度(SENSOR_DELAY_NORMAL、SENSOR_DELAY_UI、SENSOR_DELAY_GAME、またはSENSOR_DELAY_FASTESTの頻度が高い順)を渡します。
プログラムがスマートフォンのリソースを使い果たしないように、onPauseイベントによって最小化され、センサーからデータを「削除」します。
@Override protected void onPause() { super.onPause(); msensorManager.unregisterListener(this); }
センサーからのデータがセンサーに対応する配列に入力される新しいメソッドを作成しましょう。 loadNewSensorDataメソッドを呼び出します。
private void loadNewSensorData(SensorEvent event) { final int type = event.sensor.getType(); // if (type == Sensor.TYPE_ACCELEROMETER) { // accelData = event.values.clone(); } if (type == Sensor.TYPE_MAGNETIC_FIELD) { // magnetData = event.values.clone(); } }
まあ、それはほとんどそれです! onSensorChangedイベントハンドラを記述するだけです。
public void onSensorChanged(SensorEvent event) { loadNewSensorData(event); // SensorManager.getRotationMatrix(rotationMatrix, null, accelData, magnetData); // SensorManager.getOrientation(rotationMatrix, OrientationData); // if((xyView==null)||(xzView==null)||(zyView==null)){ // . xyView = (TextView) findViewById(R.id.xyValue); xzView = (TextView) findViewById(R.id.xzValue); zyView = (TextView) findViewById(R.id.zyValue); } // xyView.setText(String.valueOf(Math.round(Math.toDegrees(OrientationData[0])))); xzView.setText(String.valueOf(Math.round(Math.toDegrees(OrientationData[1])))); zyView.setText(String.valueOf(Math.round(Math.toDegrees(OrientationData[2])))); }
すべて準備完了です! 今、私は間違いを訂正し、非推奨ではない方法でセンサーからデータを受信する方法を教えました。 :)
結論として、 ソース 、 完成したapk 、および情報源へのリンクを提供します。
PS:あなたはおそらく最後のリストのヌルとは対照的に、変数の余分なチェックに気づいたでしょう。 これがないと、コンパイラはjava.lang.NullPointerExceptionをスローします。 誰かがエラーを説明したり指摘したりしてくれたらありがたいです。
UPD: firexelのおかげで問題は解決しました 。
onCreateのfindViewByIdでsetContentViewと行を交換します
その後、余分なチェックを削除できます。