Android SDK предоставляет доступ к различным устройствам ввода и датчикам, доступным в Glass EE2. На этой странице представлен обзор доступных функций, подробности реализации и полезные советы.
Сенсорные жесты
С помощью Android SDK можно получить доступ к необработанным данным с сенсорной панели Glass. Это достигается за счет детектора жестов, который автоматически распознает распространенные жесты на Glass, такие как касание, взмах и прокрутка.
Вы также можете использовать этот детектор жестов в своих приложениях для учета касаний, свайпов вперед, назад и вниз. Это похоже на то, что было реализовано в предыдущих устройствах Glass.
Эти жесты лучше всего использовать следующим образом:
- Нажмите : Подтвердите или введите.
- Проведите пальцем вперед , проведите пальцем назад : перемещайтесь по карточкам и экранам.
- Проведите пальцем вниз : Назад или выход.
Для получения подробной информации о реализации ознакомьтесь с примером детектора жестов .
Распознавайте жесты с помощью детектора жестов Android.
Android GestureDetector позволяет распознавать простые и сложные жесты, например, движения несколькими пальцами или прокрутку.
Обнаружение жестов на уровне активности.
Обнаруживайте жесты на уровне активности только тогда, когда не имеет значения, какая часть вашего пользовательского интерфейса находится в фокусе. Например, если вы хотите вызвать меню при касании пользователем сенсорной панели, независимо от того, какой элемент находится в фокусе, обрабатывайте MotionEvent внутри активности.
Ниже приведён пример обнаружения жестов на уровне активности, использующий GestureDetector и реализующий интерфейс GestureDetector.OnGestureListener для обработки распознанных жестов, которые затем обрабатываются и преобразуются в следующее:
-
TAP -
SWIPE_FORWARD -
SWIPE_BACKWARD -
SWIPE_UP -
SWIPE_DOWN
Котлин
class GlassGestureDetector(context: Context, private val onGestureListener: OnGestureListener) : GestureDetector.OnGestureListener { private val gestureDetector = GestureDetector(context, this) enum class Gesture { TAP, SWIPE_FORWARD, SWIPE_BACKWARD, SWIPE_UP, SWIPE_DOWN } interface OnGestureListener { fun onGesture(gesture: Gesture): Boolean } fun onTouchEvent(motionEvent: MotionEvent): Boolean { return gestureDetector.onTouchEvent(motionEvent) } override fun onDown(e: MotionEvent): Boolean { return false } override fun onShowPress(e: MotionEvent) {} override fun onSingleTapUp(e: MotionEvent): Boolean { return onGestureListener.onGesture(Gesture.TAP) } override fun onScroll( e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float ): Boolean { return false } override fun onLongPress(e: MotionEvent) {} /** * Swipe detection depends on the: * - movement tan value, * - movement distance, * - movement velocity. * * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement * angle is only between 60 and 120 degrees. * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends * on deltaX value sign. * * ______________________________________________________________ * | \ UP / | * | \ / | * | 60 120 | * | \ / | * | \ / | * | BACKWARD <------- 0 ------------ 180 ------> FORWARD | * | / \ | * | / \ | * | 60 120 | * | / \ | * | / DOWN \ | * -------------------------------------------------------------- */ override fun onFling( e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { val deltaX = e2.x - e1.x val deltaY = e2.y - e1.y val tan = if (deltaX != 0f) abs(deltaY / deltaX).toDouble() else java.lang.Double.MAX_VALUE return if (tan > TAN_60_DEGREES) { if (abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) { false } else if (deltaY < 0) { onGestureListener.onGesture(Gesture.SWIPE_UP) } else { onGestureListener.onGesture(Gesture.SWIPE_DOWN) } } else { if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) { false } else if (deltaX < 0) { onGestureListener.onGesture(Gesture.SWIPE_FORWARD) } else { onGestureListener.onGesture(Gesture.SWIPE_BACKWARD) } } } companion object { private const val SWIPE_DISTANCE_THRESHOLD_PX = 100 private const val SWIPE_VELOCITY_THRESHOLD_PX = 100 private val TAN_60_DEGREES = tan(Math.toRadians(60.0)) } }
Java
public class GlassGestureDetector implements GestureDetector.OnGestureListener { enum Gesture { TAP, SWIPE_FORWARD, SWIPE_BACKWARD, SWIPE_UP, SWIPE_DOWN, } interface OnGestureListener { boolean onGesture(Gesture gesture); } private static final int SWIPE_DISTANCE_THRESHOLD_PX = 100; private static final int SWIPE_VELOCITY_THRESHOLD_PX = 100; private static final double TAN_60_DEGREES = Math.tan(Math.toRadians(60)); private GestureDetector gestureDetector; private OnGestureListener onGestureListener; public GlassGestureDetector(Context context, OnGestureListener onGestureListener) { gestureDetector = new GestureDetector(context, this); this.onGestureListener = onGestureListener; } public boolean onTouchEvent(MotionEvent motionEvent) { return gestureDetector.onTouchEvent(motionEvent); } @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return onGestureListener.onGesture(Gesture.TAP); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } /** * Swipe detection depends on the: * - movement tan value, * - movement distance, * - movement velocity. * * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement * angle is only between 60 and 120 degrees. * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends * on deltaX value sign. * * ______________________________________________________________ * | \ UP / | * | \ / | * | 60 120 | * | \ / | * | \ / | * | BACKWARD <------- 0 ------------ 180 ------> FORWARD | * | / \ | * | / \ | * | 60 120 | * | / \ | * | / DOWN \ | * -------------------------------------------------------------- */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { final float deltaX = e2.getX() - e1.getX(); final float deltaY = e2.getY() - e1.getY(); final double tan = deltaX != 0 ? Math.abs(deltaY/deltaX) : Double.MAX_VALUE; if (tan > TAN_60_DEGREES) { if (Math.abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) { return false; } else if (deltaY < 0) { return onGestureListener.onGesture(Gesture.SWIPE_UP); } else { return onGestureListener.onGesture(Gesture.SWIPE_DOWN); } } else { if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) { return false; } else if (deltaX < 0) { return onGestureListener.onGesture(Gesture.SWIPE_FORWARD); } else { return onGestureListener.onGesture(Gesture.SWIPE_BACKWARD); } } } }
Пример использования
Для использования функции распознавания жестов на уровне активности необходимо выполнить следующие задачи:
- Добавьте следующее объявление в файл манифеста, внутри объявления приложения. Это позволит вашему приложению получать
MotionEventв активности:<application> <!-- Copy below declaration into your manifest file --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> </application>
- Переопределите метод
dispatchTouchEvent(motionEvent)активности, чтобы передать события движения методуonTouchEvent(motionEvent)детектора жестов. - Реализуйте
GlassGestureDetector.OnGestureListenerв вашей активности.
Ниже приведён пример детектора жестов на уровне активности:
Котлин
class MainAcvitiy : AppCompatActivity(), GlassGestureDetector.OnGestureListener { private lateinit var glassGestureDetector: GlassGestureDetector override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) glassGestureDetector = GlassGestureDetector(this, this) } override fun onGesture(gesture: GlassGestureDetector.Gesture): Boolean { when (gesture) { TAP -> // Response for TAP gesture return true SWIPE_FORWARD -> // Response for SWIPE_FORWARD gesture return true SWIPE_BACKWARD -> // Response for SWIPE_BACKWARD gesture return true else -> return false } } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { return if (glassGestureDetector.onTouchEvent(ev)) { true } else super.dispatchTouchEvent(ev) } }
Java
public class MainActivity extends AppCompatActivity implements OnGestureListener { private GlassGestureDetector glassGestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); glassGestureDetector = new GlassGestureDetector(this, this); } @Override public boolean onGesture(Gesture gesture) { switch (gesture) { case TAP: // Response for TAP gesture return true; case SWIPE_FORWARD: // Response for SWIPE_FORWARD gesture return true; case SWIPE_BACKWARD: // Response for SWIPE_BACKWARD gesture return true; default: return false; } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (glassGestureDetector.onTouchEvent(ev)) { return true; } return super.dispatchTouchEvent(ev); } }
Аудиовход
Glass Enterprise Edition 2 — это стандартное устройство на базе AOSP, поддерживающее базовые источники звука .
В следующих аудиоисточниках реализована расширенная обработка сигнала:
распознавание голоса
Glass Enterprise Edition 2 поддерживает встроенную реализацию распознавания речи. Эта функция поддерживается только для английского языка.

Интерфейс распознавания речи ожидает, пока пользователь произнесет фразу, а затем возвращает расшифрованный текст после того, как он закончит. Чтобы запустить функцию, выполните следующие шаги:
- Вызовите
startActivityForResult()с интентомACTION_RECOGNIZE_SPEECH. При запуске активности поддерживаются следующие дополнительные параметры интента: - Переопределите функцию обратного вызова
onActivityResult(), чтобы получать расшифрованный текст из дополнительного объекта IntentEXTRA_RESULTS, как показано в следующем примере кода. Эта функция обратного вызова вызывается, когда пользователь заканчивает говорить.
Котлин
private const val SPEECH_REQUEST = 109 private fun displaySpeechRecognizer() { val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) startActivityForResult(intent, SPEECH_REQUEST) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) { val results: List<String>? = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) val spokenText = results?.get(0) // Do something with spokenText. } super.onActivityResult(requestCode, resultCode, data) }
Java
private static final int SPEECH_REQUEST = 109; private void displaySpeechRecognizer() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); startActivityForResult(intent, SPEECH_REQUEST); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) { List<String> results = data.getStringArrayListExtra( RecognizerIntent.EXTRA_RESULTS); String spokenText = results.get(0); // Do something with spokenText. } super.onActivityResult(requestCode, resultCode, data); }
Для получения подробной информации о реализации ознакомьтесь с примером приложения для распознавания голоса .
Предвзятость по ключевым словам
Функция распознавания речи на Glass может быть настроена на определенный список ключевых слов. Настройка повышает точность распознавания ключевых слов. Чтобы включить настройку для ключевых слов, используйте следующие параметры:
Котлин
val keywords = arrayOf("Example", "Biasing", "Keywords") val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) intent.putExtra("recognition-phrases", keywords) startActivityForResult(intent, SPEECH_REQUEST)
Java
final String[] keywords = {"Example", "Biasing", "Keywords"}; Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra("recognition-phrases", keywords); startActivityForResult(intent, SPEECH_REQUEST);
Голосовые команды
Голосовые команды позволяют пользователям выполнять действия из различных активностей. Голосовые команды создаются с помощью стандартных API меню Android, но пользователи могут вызывать пункты меню с помощью голосовых команд, а не касания.
Чтобы включить голосовые команды для определенного действия, выполните следующие шаги:
- Чтобы включить голосовые команды, вызовите
getWindow().requestFeature(FEATURE_VOICE_COMMANDS)в нужном действии. При включении этой функции значок микрофона будет отображаться в левом нижнем углу экрана всякий раз, когда это действие получит фокус. - Запросите разрешение
RECORD_AUDIOв вашем приложении. - Переопределите
onCreatePanelMenu()и создайте ресурс меню. - Переопределите
onContextItemSelected()для обработки обнаруженных голосовых команд.
Котлин
class VoiceCommandsActivity : AppCompatActivity() { companion object { const val FEATURE_VOICE_COMMANDS = 14 const val REQUEST_PERMISSION_CODE = 200 val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO) val TAG = VoiceCommandsActivity::class.java.simpleName } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.requestFeature(FEATURE_VOICE_COMMANDS) setContentView(R.layout.activity_voice_commands) // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions( this, PERMISSIONS, REQUEST_PERMISSION_CODE ) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { if (requestCode == REQUEST_PERMISSION_CODE) { for (result in grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Permission denied. Voice commands menu is disabled.") } } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults) } } override fun onCreatePanelMenu(featureId: Int, menu: Menu): Boolean { menuInflater.inflate(R.menu.voice_commands_menu, menu) return true } override fun onContextItemSelected(item: MenuItem): Boolean { return when (item.itemId) { // Handle selected menu item R.id.edit -> { // Handle edit action true } else -> super.onContextItemSelected(item) } } }
Java
public class VoiceCommandsActivity extends AppCompatActivity { private static final String TAG = VoiceCommandsActivity.class.getSimpleName(); private static final int FEATURE_VOICE_COMMANDS = 14; private static final int REQUEST_PERMISSION_CODE = 200; private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO}; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(FEATURE_VOICE_COMMANDS); setContentView(R.layout.activity_voice_commands); // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_PERMISSION_CODE) { for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Permission denied. Voice commands menu is disabled."); } } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @Override public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) { getMenuInflater().inflate(R.menu.voice_commands_menu, menu); return true; } @Override public boolean onContextItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { // Handle selected menu item case R.id.edit: // Handle edit action return true; default: return super.onContextItemSelected(item); } } }
Ниже приведён пример ресурса меню, использованного в предыдущем задании:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/delete" android:icon="@drawable/ic_delete" android:title="@string/delete"/> <item android:id="@+id/edit" android:icon="@drawable/ic_edit" android:title="@string/edit"/> <item android:id="@+id/find" android:icon="@drawable/ic_search" android:title="@string/find"/> </menu>
Для получения полной информации ознакомьтесь с примером приложения для ведения заметок .
Перезагрузка списка голосовых команд
Вы можете динамически перезагружать список голосовых команд. Для этого замените ресурс menu в методе onCreatePanelMenu() или измените объект меню в методе onPreparePanel() . Чтобы применить изменения, вызовите метод invalidateOptionsMenu() .
Котлин
private val options = mutableListOf<String>() fun onPreparePanel(featureId: Int, view: View?, menu: Menu): Boolean { if (featureId != FEATURE_VOICE_COMMANDS) { return super.onCreatePanelMenu(featureId, menu) } for (optionTitle in options) { menu.add(optionTitle) } return true } /** * Method showing example implementation of voice command list modification * * If you call [Activity.invalidateOptionsMenu] method, voice command list will be * reloaded (onCreatePanelMenu and onPreparePanel methods will be called). */ private fun modifyVoiceCommandList() { options.add("Delete") options.add("Play") options.add("Pause") invalidateOptionsMenu() }
Java
private final List<String> options = new ArrayList<>(); @Override public boolean onPreparePanel(int featureId, View view, Menu menu) { if (featureId != FEATURE_VOICE_COMMANDS) { return super.onCreatePanelMenu(featureId, menu); } for (String optionTitle : options) { menu.add(optionTitle); } return true; } /** * Method showing example implementation of voice command list modification * * If you call {@link Activity#invalidateOptionsMenu()} method, voice command list will be * reloaded (onCreatePanelMenu and onPreparePanel methods will be called). */ private void modifyVoiceCommandList() { options.add("Delete"); options.add("Play"); options.add("Pause"); invalidateOptionsMenu(); }
Решение AppCompatActivity
Чтобы перезагрузить список голосовых команд в активности, расширяющей AppCompatActivity , используйте метод sendBroadcast() с действием Intent reload-voice-commands :
Котлин
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
Включение и отключение голосовых команд во время выполнения.
Вы можете включать и отключать голосовые команды во время выполнения. Для этого верните соответствующее значение из метода onCreatePanelMenu() следующим образом:
- Установите значение
true, чтобы включить эту функцию. - Чтобы отключить, установите значение
false.
режим отладки
Чтобы включить режим отладки для голосовых команд, вызовите getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) в нужном действии. Режим отладки активирует следующие функции:
- Logcat содержит запись с распознанной фразой для отладки.
- При обнаружении неопознанной команды отображается наложение пользовательского интерфейса, как показано на рисунке:

Котлин
class VoiceCommandsActivity : AppCompatActivity() { companion object { const val FEATURE_VOICE_COMMANDS = 14 const val FEATURE_DEBUG_VOICE_COMMANDS = 15 const val REQUEST_PERMISSION_CODE = 200 val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO) val TAG = VoiceCommandsActivity::class.java.simpleName } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.requestFeature(FEATURE_VOICE_COMMANDS) window.requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) setContentView(R.layout.activity_voice_commands) // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions( this, PERMISSIONS, REQUEST_PERMISSION_CODE ) } . . . }
Java
public class VoiceCommandsActivity extends AppCompatActivity { private static final String TAG = VoiceCommandsActivity.class.getSimpleName(); private static final int FEATURE_VOICE_COMMANDS = 14; private static final int FEATURE_DEBUG_VOICE_COMMANDS = 15; private static final int REQUEST_PERMISSION_CODE = 200; private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO}; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(FEATURE_VOICE_COMMANDS); getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS); setContentView(R.layout.activity_voice_commands); // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE); } . . . }
Для получения подробной информации о реализации ознакомьтесь с примером приложения для перезагрузки с помощью голосовых команд .
Преобразование текста в речь (TTS)
Функция преобразования текста в речь преобразует цифровой текст в синтезированную речь. Для получения дополнительной информации посетите документацию для разработчиков Android по функции TextToSpeech .
В Glass EE2 установлен движок преобразования текста в речь от Google . Он настроен как движок преобразования текста в речь по умолчанию и работает в автономном режиме.
В состав системы преобразования текста в речь Google входят следующие языковые версии:
| бенгальский китайский мандарин чешский датский немецкий греческий Английский испанский эстонский финский Французский гуджарати хинди | венгерский индонезийский итальянского японский яванский австронезийский Австроазиатский Каннада корейский Малаялам норвежский Голландский | польский португальский Русский словацкий сунданский шведский тамильский телугу Тайский турецкий украинский вьетнамский |
Камера
Glass Enterprise Edition 2 оснащен 8-мегапиксельной камерой с фиксированным фокусом, диафрагмой f/2.4, соотношением сторон сенсора 4:3 и диагональным полем зрения 83° (71° x 57° в альбомной ориентации). Мы рекомендуем использовать стандартный API CameraX или Camera2 .
Для получения подробной информации о реализации ознакомьтесь с примером приложения камеры .
Кнопка камеры
Кнопка камеры — это физическая кнопка на шарнире устройства Glass Enterprise Edition 2. Её можно использовать так же, как и стандартную клавишу клавиатуры , и она идентифицируется по коду клавиши KeyEvent#KEYCODE_CAMERA .
Начиная с обновления ОС OPM1.200313.001 , из приложения Launcher отправляются интенты со следующими действиями:
-
MediaStore#ACTION_IMAGE_CAPTUREпри коротком нажатии кнопки камеры. -
MediaStore#ACTION_VIDEO_CAPTUREпри длительном нажатии кнопки камеры.
Датчики
Разработчикам, создающим приложения в рамках Glass EE2, доступен широкий выбор датчиков.
На Glass поддерживаются следующие стандартные датчики Android:
-
TYPE_ACCELEROMETER -
TYPE_GRAVITY -
TYPE_GYROSCOPE -
TYPE_LIGHT -
TYPE_LINEAR_ACCELERATION -
TYPE_MAGNETIC_FIELD -
TYPE_ORIENTATION(устарело) -
TYPE_ROTATION_VECTOR
Следующие датчики Android не поддерживаются на Glass:
Система координат датчика Glass показана на следующем рисунке. Она отсчитывается относительно дисплея Glass. Для получения дополнительной информации см. раздел «Система координат датчика» .

Акселерометр, гироскоп и магнитометр расположены на оптическом модуле устройства Glass, который пользователь поворачивает для выравнивания устройства относительно своего поля зрения. Измерить угол наклона оптического модуля напрямую невозможно, поэтому учитывайте это при использовании углов, полученных с помощью этих датчиков, например, для определения направления по компасу.
Чтобы продлить срок службы батареи, используйте датчики только тогда, когда это необходимо. Принимая решение о начале и прекращении использования датчиков, учитывайте потребности и жизненный цикл приложения.
Обратные вызовы событий датчиков выполняются в потоке пользовательского интерфейса, поэтому обрабатывайте события и возвращайте значения как можно быстрее. Если обработка занимает слишком много времени, поместите события датчиков в очередь и используйте фоновый поток для их обработки.
Часто частоты дискретизации 50 Гц достаточно для отслеживания движений головы.
Для получения более подробной информации об использовании датчиков см. руководство разработчика Android .
службы определения местоположения
Устройство Glass Enterprise Edition 2 не оснащено модулем GPS и не определяет местоположение пользователя. Однако в нем реализованы службы определения местоположения, необходимые для отображения списка ближайших сетей Wi-Fi и устройств Bluetooth.
Если ваше приложение обладает правами владельца устройства, вы можете использовать его для программного изменения значения соответствующего параметра безопасности:
Котлин
val devicePolicyManager = context .getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) { val componentName = ComponentName(context, MyDeviceAdmin::class.java) devicePolicyManager.setSecureSetting( componentName, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_SENSORS_ONLY.toString() ) }
Java
final DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context .getSystemService(Context.DEVICE_POLICY_SERVICE); if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) { final ComponentName componentName = new ComponentName(context, MyDeviceAdmin.class); devicePolicyManager.setSecureSetting(componentName, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_SENSORS_ONLY)); }
Если вы используете стороннее решение для управления мобильными устройствами (MDM), это решение должно уметь изменять эти настройки за вас.