The post 참조하는 것은 실제로 일부 삼성 장치 (Galaxy S4, Galaxy Note 3)의 버그를 나타냅니다 (this Android Developer list post 참조). 이 코드가 일반 장치에서 작동하려면 SDK 수준간에 특별한 처리를하지 않아도됩니다. 크기가 큰 4보다 클 경우, 배열을 절단함으로써하지만, 슬프게도, 조각 ...
Chromium handles this issue 그러나
if (values.length > 4) {
// On some Samsung devices SensorManager.getRotationMatrixFromVector
// appears to throw an exception if rotation vector has length > 4.
// For the purposes of this class the first 4 values of the
// rotation vector are sufficient (see crbug.com/335298 for details).
if (mTruncatedRotationVector == null) {
mTruncatedRotationVector = new float[4];
}
System.arraycopy(values, 0, mTruncatedRotationVector, 0, 4);
getOrientationFromRotationVector(mTruncatedRotationVector);
} else {
getOrientationFromRotationVector(values);
}
,이 솔루션에 작동하지 않았다 내 응용 프로그램 GPSTest에서 발견 갤럭시 S3 (Github issue here 참조).
따라서, IllegalArgumentException
을 던지는 장치에서만 배열을 자르려고했습니다. 또한 절대적으로 필요한 경우가 아니면 추가 System.arraycopy()를 피할 수 있습니다.
다음은 코드 레벨입니다 (API 레벨이 진저 브레드보다 작은 기기에서 방향 센서도 지원합니다.
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@Override
public void onSensorChanged(SensorEvent event) {
double orientation = Double.NaN;
double tilt = Double.NaN;
switch (event.sensor.getType()) {
case Sensor.TYPE_ROTATION_VECTOR:
// Modern rotation vector sensors
if (!mTruncateVector) {
try {
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
} catch (IllegalArgumentException e) {
// On some Samsung devices, an exception is thrown if this vector > 4 (see #39)
// Truncate the array, since we can deal with only the first four values
Log.e(TAG, "Samsung device error? Will truncate vectors - " + e);
mTruncateVector = true;
// Do the truncation here the first time the exception occurs
getRotationMatrixFromTruncatedVector(event.values);
}
} else {
// Truncate the array to avoid the exception on some devices (see #39)
getRotationMatrixFromTruncatedVector(event.values);
}
int rot = getWindowManager().getDefaultDisplay().getRotation();
switch (rot) {
case Surface.ROTATION_0:
// No orientation change, use default coordinate system
SensorManager.getOrientation(mRotationMatrix, mValues);
// Log.d(TAG, "Rotation-0");
break;
case Surface.ROTATION_90:
// Log.d(TAG, "Rotation-90");
SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_Y,
SensorManager.AXIS_MINUS_X, mRemappedMatrix);
SensorManager.getOrientation(mRemappedMatrix, mValues);
break;
case Surface.ROTATION_180:
// Log.d(TAG, "Rotation-180");
SensorManager
.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_MINUS_X,
SensorManager.AXIS_MINUS_Y, mRemappedMatrix);
SensorManager.getOrientation(mRemappedMatrix, mValues);
break;
case Surface.ROTATION_270:
// Log.d(TAG, "Rotation-270");
SensorManager
.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_MINUS_Y,
SensorManager.AXIS_X, mRemappedMatrix);
SensorManager.getOrientation(mRemappedMatrix, mValues);
break;
default:
// This shouldn't happen - assume default orientation
SensorManager.getOrientation(mRotationMatrix, mValues);
// Log.d(TAG, "Rotation-Unknown");
break;
}
orientation = Math.toDegrees(mValues[0]); // azimuth
tilt = Math.toDegrees(mValues[1]);
break;
case Sensor.TYPE_ORIENTATION:
// Legacy orientation sensors
orientation = event.values[0];
break;
default:
// A sensor we're not using, so return
return;
}
}
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
private void getRotationMatrixFromTruncatedVector(float[] vector) {
System.arraycopy(vector, 0, mTruncatedRotationVector, 0, 4);
SensorManager.getRotationMatrixFromVector(mRotationMatrix, mTruncatedRotationVector);
}
및 onResume()
상기 센서 등록 :
등) ROTATION_VECTOR 센서가 도입되었을 때 이전 및
false
초기화된다 반원
mTruncateVector
을 사용하여 방향 변경 좌표계)를 리매핑 핸들
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
// Use the modern rotation vector sensors
Sensor vectorSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
mSensorManager.registerListener(this, vectorSensor, 16000); // ~60hz
} else {
// Use the legacy orientation sensors
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (sensor != null) {
mSensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_GAME);
}
}
전체 구현은 here on Github입니다.
흥미 롭습니다 -이 오류가 Galaxy S3의 어떤 변형에 나타 났습니까? Android 4.3이 포함 된 미국의 Sprint 변형 SPH-L710에서는이 문제가 발생하지 않았습니다. –