私が作っているアプリケーションについては、カメラとコンパスが必要です。アプリケーションはマニフェストのランドスケープモードに設定されています。
まずコンパスを実装しました。 Androidデベロッパーに示唆されているように、私は2つのセンサー - 加速度センサーと磁場を使用しました。これは私がそれをした方法です:
私は自分の活動を実装してSensorEventListener
です。 onCreate()
では、私は私のsensorManager
使用して初期化します。Androidカメラはセンサー(加速度計と磁場)に影響します。電話機ユーザーの場合
sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
私はそうのようなonResume()
で私のリスナーを登録:
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
sManager.registerListener(this, sManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),SensorManager.SENSOR_DELAY_NORMAL);
とonPause()
でその登録解除もちろん
onAccuracyChanged()
を使用しません。これは私が
onSensorChanged()
に何をすべきかです:
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_MAGNETIC_FIELD:
mags = event.values.clone();
break;
case Sensor.TYPE_ACCELEROMETER:
accels = event.values.clone();
break;
}
if (mags != null && accels != null) {
gravity = new float[9];
magnetic = new float[9];
SensorManager.getRotationMatrix(gravity, magnetic, accels, mags);
float[] outGravity = new float[9];
float inclination = (float) Math.acos(gravity[8]);
if (inclination < Math.toRadians(25)
|| inclination > Math.toRadians(155)) {
// device is close to flat. Remap for landscape.
SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_Y,SensorManager.AXIS_MINUS_X, outGravity);
SensorManager.getOrientation(outGravity, values);
} else {
// device is not flat. Remap for landscape and perpendicular
SensorManager.remapCoordinateSystem(gravity, SensorManager.AXIS_X,SensorManager.AXIS_Z, outGravity);
SensorManager.getOrientation(outGravity, values);
}
azimuth = Math.round(Math.toDegrees(values[0]));
}
}
あなたが見ることができるように、私は電話がテーブルの上に平らに置かれたときに区別し、(あなたが写真を撮るだろうというときのように)、ユーザーがそれを保持しているとき。このコードだけを使用すると、すべてが多かれ少なかれ動作します。私は、電話機がテーブルに横たわっているときと、テーブルに垂直に(約5-10度の違いがありますが、それと一緒に暮らすことができます)、正しい方位角の値を得ています。
問題は、カメラプレビューをアプリケーションに追加するときに開始されます。 私は自分の活動にSurfaceHolder.Callback
を実装しています。私はonCreate()
に私のカメラを初期化:私は私のプロジェクトにカメラコードを追加すると
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
camera = Camera.open();
camera.setDisplayOrientation(0);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
if (isCameraOn) {
camera.stopPreview();
isCameraOn = false;
}
if (camera != null) {
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
isCameraOn = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
camera.stopPreview();
camera.release();
camera = null;
}
、および携帯電話の画面、私のセンサーにカメラを示しています。
SurfaceView cameraView = (SurfaceView)findViewById(R.id.camera_view);
surfaceHolder = cameraView.getHolder();
surfaceHolder.addCallback(this);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
これは私がインターフェイスを実装する方法であります電話機が突然垂直になると正しく動作しません。電話機がテーブルの上に横になっていると、私が得ている方位角の値は正しいです。電話がテーブルに対して垂直に保持されているとき、方位角の値は約40度ずれています(安定していますが)。
私は解決策を探してみましたが(自分でもオンラインでも)、これまでの努力は無駄でした。私はこの問題にどのように取り組むべきかについていくつか指導をしたいと思う。
ありがとう!
これは同じデバイスですか? –
同じデバイスでチェックしています。それまでの間、私はいくつかの友人に自分のアプリケーションを送ってチェックしてもらいました(「コンパス」とカメラの両方で)。たいていの場合、違いは約5-10(私と一緒に暮らすことができます)でしたが、30度の差がある小切手はほとんどありませんでした(小切手の約10%)。彼らがカメラなしでチェックしたとき、最大差は約5-10でした。だから私の携帯電話のように悪くないが、まだ少し信頼性の低い。解決策が見つからない場合、私はおそらく今のところそれを残して、将来的にはより正確な精度が必要かどうかを確認します。 – Ungoliant
問題は、カメラとコンパスの両方のコールバックがメイン(UI)スレッド上でCPUを競合する可能性があることです。セカンダリHandlerThreadでカメラを開く必要があります。 –