7 package com.google.appinventor.components.runtime;
22 import android.content.Context;
23 import android.hardware.Sensor;
24 import android.hardware.SensorEvent;
25 import android.hardware.SensorEventListener;
26 import android.hardware.SensorManager;
27 import android.util.Log;
28 import android.view.Display;
29 import android.view.Surface;
30 import android.view.WindowManager;
53 @DesignerComponent(version = YaVersion.ORIENTATIONSENSOR_COMPONENT_VERSION,
54 description =
"<p>Non-visible component providing information about the " +
55 "device's physical orientation in three dimensions: <ul> " +
56 "<li> <strong>Roll</strong>: 0 degrees when the device is level, increases to " +
57 " 90 degrees as the device is tilted up on its left side, and " +
58 " decreases to -90 degrees when the device is tilted up on its right side. " +
60 "<li> <strong>Pitch</strong>: 0 degrees when the device is level, up to " +
61 " 90 degrees as the device is tilted so its top is pointing down, " +
62 " up to 180 degrees as it gets turned over. Similarly, as the device " +
63 " is tilted so its bottom points down, pitch decreases to -90 " +
64 " degrees, then further decreases to -180 degrees as it gets turned all the way " +
66 "<li> <strong>Azimuth</strong>: 0 degrees when the top of the device is " +
67 " pointing north, 90 degrees when it is pointing east, 180 degrees " +
68 " when it is pointing south, 270 degrees when it is pointing west, " +
70 " These measurements assume that the device itself is not moving.</p>",
71 category = ComponentCategory.SENSORS,
73 iconName =
"images/orientationsensor.png")
79 private static final String LOG_TAG =
"OrientationSensor";
81 private static final int AZIMUTH = 0;
82 private static final int PITCH = 1;
83 private static final int ROLL = 2;
84 private static final int DIMENSIONS = 3;
87 private boolean enabled;
88 private float azimuth;
94 private final SensorManager sensorManager;
95 private final Sensor accelerometerSensor;
96 private final Sensor magneticFieldSensor;
97 private boolean listening;
101 private final float[] accels =
new float[DIMENSIONS];
102 private final float[] mags =
new float[DIMENSIONS];
106 private boolean accelsFilled;
107 private boolean magsFilled;
111 private final float[] rotationMatrix =
new float[DIMENSIONS * DIMENSIONS];
112 private final float[] inclinationMatrix =
new float[DIMENSIONS * DIMENSIONS];
113 private final float[] values =
new float[DIMENSIONS];
121 super(container.
$form());
125 (SensorManager) container.
$context().getSystemService(Context.SENSOR_SERVICE);
126 accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
127 magneticFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
137 private void startListening() {
139 sensorManager.registerListener(
this, accelerometerSensor,
140 SensorManager.SENSOR_DELAY_NORMAL);
141 sensorManager.registerListener(
this, magneticFieldSensor,
142 SensorManager.SENSOR_DELAY_NORMAL);
147 private void stopListening() {
149 sensorManager.unregisterListener(
this);
153 accelsFilled =
false;
173 @SimpleEvent(description =
"Called when the orientation has changed.")
188 return sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() > 0
189 && sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).size() > 0;
211 defaultValue =
"True")
214 if (this.enabled != enabled) {
215 this.enabled = enabled;
292 static float computeAngle(
float pitch,
float roll) {
293 return (
float) Math.toDegrees(Math.atan2(Math.toRadians(pitch),
295 -Math.toRadians(roll)));
309 @SimpleProperty(category = PropertyCategory.BEHAVIOR)
319 final int MAX_VALUE = 90;
320 double npitch = Math.toRadians(Math.min(MAX_VALUE, Math.abs(pitch)));
321 double nroll = Math.toRadians(Math.min(MAX_VALUE, Math.abs(roll)));
322 return (
float) (1.0 - Math.cos(npitch) * Math.cos(nroll));
336 private int getScreenRotation() {
338 ((WindowManager)
form.getSystemService(Context.WINDOW_SERVICE)).
343 return display.getOrientation();
358 int eventType = sensorEvent.sensor.getType();
362 case Sensor.TYPE_ACCELEROMETER:
364 System.arraycopy(sensorEvent.values, 0, accels, 0, DIMENSIONS);
367 accuracy = sensorEvent.accuracy;
370 case Sensor.TYPE_MAGNETIC_FIELD:
372 System.arraycopy(sensorEvent.values, 0, mags, 0, DIMENSIONS);
377 Log.e(LOG_TAG,
"Unexpected sensor type: " + eventType);
382 if (accelsFilled && magsFilled) {
383 SensorManager.getRotationMatrix(rotationMatrix,
387 SensorManager.getOrientation(rotationMatrix, values);
391 (
float) Math.toDegrees(values[AZIMUTH]));
393 (
float) Math.toDegrees(values[PITCH]));
397 (
float) -Math.toDegrees(values[ROLL]));
400 int rotation = getScreenRotation();
402 case Surface.ROTATION_0:
404 case Surface.ROTATION_90:
409 case Surface.ROTATION_180:
412 case Surface.ROTATION_270:
418 Log.e(LOG_TAG,
"Illegal value for getScreenRotation(): " +