私が作成しているアプリケーションには、カメラとコンパスが必要です。アプリケーションは、マニフェストでランドスケープ モードに設定されています。
まず、コンパスを実装しました。Android Developers で提案されているように、AccelerometerとMagnetic Fieldの 2 つのセンサーを使用しました。これが私がやった方法です:
私は自分の活動を実装していSensorEventListener
ます。onCreate()
私は以下を使用して初期化しますsensorManager
:
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()
。
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);
}
これは私がインターフェースを実装する方法です:
@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;
}
プロジェクトにカメラ コードを追加し、電話の画面にカメラを表示すると、電話が突然垂直になるとセンサーが正しく動作しません。電話がテーブルの上に平らに置かれている場合、取得している方位角の値は正しいです。電話がテーブルに対して垂直に保持されている場合、方位角の値は約 40 度ずれています (安定していますが)。
私は解決策を探してみました (自分自身とオンラインの両方で) が、これまでのところ私の努力は無駄でした. この問題に対処する方法について、何らかの方向性を示したいと思います。
ありがとう!