Pakiet Android SDK zapewnia dostęp do różnych urządzeń wejściowych i czujników, które są dostępne w Google Glass EE2. Na tej stronie znajdziesz przegląd dostępnych funkcji, szczegółów implementacji i przydatne wskazówki.
Kliknięcia
Za pomocą pakietu SDK na Androida możesz zapewnić dostęp do nieprzetworzonych danych na touchpadzie Glass. Można to osiągnąć za pomocą wzorca do wykrywania gestów, który automatycznie wykrywa typowe gesty w Google Glass, takie jak klikanie, wyrzucanie czy przewijanie.
W swoich aplikacjach możesz też używać tego wzorca do wykrywania gestów, aby np. klikać, przesuwać palcem do przodu lub do tyłu, a także przesuwać palcem w dół. Podobne do poprzednich urządzeń Glass.
Najlepiej używać tych gestów:
- Klikanie: potwierdź lub wpisz.
- Przesuń do przodu lub do tyłu: przeglądaj karty i ekrany.
- Przesuń w dół: Wstecz lub Wyjdź.
Szczegółowe informacje o implementacji znajdziesz w tym artykule.
Wykrywanie gestów za pomocą wzorca do wykrywania gestów w Androidzie
Android GestureDetector
umożliwia wykrywanie prostych i złożonych gestów, np. gestów wymagających użycia wielu palców lub przewijania.
Wykrywanie gestów na poziomie aktywności
Wykrywaj gesty na poziomie aktywności tylko wtedy, gdy nie jest ważny.
Jeśli na przykład chcesz otworzyć menu, gdy użytkownik kliknie touchpada, niezależnie od tego, jaki widok jest aktywny, potraktuj element MotionEvent
wewnątrz aktywności.
Oto przykład wykrywania gestów na poziomie aktywności z wykorzystaniem GestureDetector
i implementuje właściwość GestureDetector.OnGestureListener
w celu przetwarzania rozpoznanych gestów, które są następnie obsługiwane i tłumaczone na:
TAP
SWIPE_FORWARD
SWIPE_BACKWARD
SWIPE_UP
SWIPE_DOWN
Kotlin
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); } } } }
Przykład użycia
Aby korzystać z funkcji wykrywania gestów na poziomie aktywności, musisz wykonać te zadania:
- Dodaj do pliku manifestu tej deklaracji w deklaracji aplikacji. Dzięki temu aplikacja otrzyma
MotionEvent
w ramach aktywności:<application> <!-- Copy below declaration into your manifest file --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> </application>
- Zastąp metodę
dispatchTouchEvent(motionEvent)
aktywności, aby przekazać zdarzenia ruchu do wzorca do wykrywania gestówonTouchEvent(motionEvent)
. - Zaimplementuj
GlassGestureDetector.OnGestureListener
w swojej aktywności.
Oto przykład wzorca do wykrywania gestów na poziomie aktywności:
Kotlin
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); } }
Wejście audio
Glass Enterprise Edition 2 to standardowe urządzenie oparte na AOSP, które obsługuje podstawowe źródła dźwięku.
Te źródła dźwięku mają zaimplementowane zaawansowane przetwarzanie sygnałów:
Rozpoznawanie głosu
Glass Enterprise Edition 2 obsługuje natywną implementację rozpoznawania mowy. Ta funkcja jest dostępna tylko w języku angielskim.
Interfejs rozpoznawania mowy czeka, aż użytkownik się wypowiedzieć, i po zakończeniu transkrypcji zwraca tekst. Aby rozpocząć aktywność, wykonaj te czynności:
- Wywołaj
startActivityForResult()
z intencjąACTION_RECOGNIZE_SPEECH
. Po rozpoczęciu aktywności obsługiwane są te dodatkowe intencje: - Zastąp wywołanie zwrotne
onActivityResult()
, aby otrzymać transkrypcję tekstu z intencjiEXTRA_RESULTS
, jak pokazano w poniższym przykładzie kodu. To wywołanie zwrotne jest wywoływane, gdy użytkownik skończy mówić.
Kotlin
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); }
Szczegółowe informacje o implementacji znajdziesz w przykładowej aplikacji rozpoznawania głosu.
Uwzględnianie słów kluczowych
Rozpoznawanie mowy w Google Glass może powodować odchylenie listy słów kluczowych. Uwzględnianie słów kluczowych zwiększa dokładność rozpoznawania słów kluczowych. Aby włączyć promowanie wyników ze względu na słowa kluczowe:
Kotlin
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);
Polecenia głosowe
Polecenia głosowe umożliwiają użytkownikom wykonywanie działań. Polecenia głosowe tworzysz za pomocą standardowych interfejsów API menu Androida, ale użytkownicy mogą wywoływać pozycje menu za pomocą poleceń głosowych zamiast dotyku.
Aby włączyć polecenia głosowe dla określonej aktywności, wykonaj te czynności:
- Aby włączyć polecenia głosowe, wywołaj
getWindow().requestFeature(FEATURE_VOICE_COMMANDS)
w wybranej aktywności. Gdy ta funkcja jest włączona, w lewym dolnym rogu ekranu pojawia się ikona mikrofonu, gdy aktywność jest skupiona. - Poproś o uprawnienia
RECORD_AUDIO
w Twojej aplikacji. - Zastąp plik
onCreatePanelMenu()
i zapełnij zasób menu. - Zastąp
onContextItemSelected()
, aby obsługiwać wykryte polecenia głosowe.
Kotlin
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); } } }
Oto przykład zasobu menu używanego przez poprzednią aktywność:
<?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>
Pełny przykład znajdziesz w aplikacji do robienia notatek.
Ponowne ładowanie listy poleceń głosowych
Listę poleceń głosowych możesz dynamicznie wczytywać ponownie. Aby to zrobić, zastąp zasób menu
w metodzie onCreatePanelMenu()
lub zmodyfikuj obiekt menu w metodzie onPreparePanel()
. Aby zastosować zmiany, wywołaj metodę invalidateOptionsMenu()
.
Kotlin
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(); }
Rozwiązanie AppCompatActivity
Aby ponownie wczytać listę poleceń głosowych w aktywności, która obejmuje AppCompatActivity
, użyj metody sendBroadcast()
z działaniem reload-voice-commands
:
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
Włączanie i wyłączanie poleceń głosowych w czasie działania
Polecenia głosowe możesz włączyć lub wyłączyć w czasie działania. W tym celu zwróć odpowiednią wartość z metody onCreatePanelMenu()
:
- Aby ją włączyć, ustaw wartość
true
. - Aby wyłączyć, ustaw wartość
false
.
Tryb debugowania
Aby włączyć tryb debugowania poleceń głosowych, wywołaj getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
w wybranej aktywności. Tryb debugowania aktywuje te funkcje:
- Logcat zawiera dziennik z rozpoznanym wyrażeniem na potrzeby debugowania.
- Nakładka interfejsu jest wyświetlana, gdy zostanie wykryte nierozpoznane polecenie, jak pokazano:
Kotlin
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); } . . . }
Szczegółowe informacje znajdziesz w przykładowej aplikacji do ponownego ładowania poleceń głosowych.
Zamiana tekstu na mowę
Zamiana tekstu na mowę przekształca tekst cyfrowy na dane wyjściowe syntezatora. Więcej informacji znajdziesz w dokumentacji TextToSpeech.
Glass EE2 ma zainstalowany mechanizm Zamiana tekstu na mowę Google. Jako domyślny mechanizm zamiany tekstu na mowę działa tryb offline.
Te języki są dołączone do mechanizmu zamiany tekstu na mowę Google:
bengalski Chiński mandaryński Czeski Duński Grecki Angielski Hiszpański Estoński Fiński Gudżarati hindi |
Węgierski indonezyjski włoski japoński jawajski austronejski australijski koreański malajalam norweski niderlandzki |
polski portugalski rosyjski słowacki sundajski szwedzki tamilski tajski turecki ukraiński wietnamski |
Aparat
Glass Enterprise Edition 2 jest wyposażony w aparat o stałej ostrości (8 megapikseli) z przysłoną F/2,4, czujnikiem 4:3 i polem widzenia 83° (71° x 57°). Zalecamy używanie standardowego interfejsu API CameraX lub Kamera2.
Szczegółowe informacje znajdziesz w przykładowej aplikacji aparatu.
Przycisk aparatu
Przycisk aparatu to fizyczny przycisk na zawiasie urządzenia Glass Enterprise Edition 2.
Można ją obsługiwać tak samo jak w przypadku standardowego działania klawiatury, rozpoznając kod klucza KeyEvent#KEYCODE_CAMERA
.
Od aktualizacji systemu operacyjnego OPM1.200313.001 zamiar jest wysyłany z aplikacji uruchamiającej za pomocą tych działań:
MediaStore#ACTION_IMAGE_CAPTURE
– naciśnij krótko przycisk aparatu.MediaStore#ACTION_VIDEO_CAPTURE
– przytrzymaj przycisk aparatu.
Czujniki
Programiści mogą korzystać z różnych czujników tworzonych w aplikacji Glass EE2.
Szklane czujniki Androida są obsługiwane przez te standardowe czujniki:
-
TYPE_ACCELEROMETER
-
TYPE_GRAVITY
-
TYPE_GYROSCOPE
-
TYPE_LIGHT
-
TYPE_LINEAR_ACCELERATION
-
TYPE_MAGNETIC_FIELD
TYPE_ORIENTATION
(wycofane)-
TYPE_ROTATION_VECTOR
Te czujniki Androida nie są obsługiwane przez Glass:
Układ współrzędnych czujnika Glass pokazuje ta ilustracja. w stosunku do wyświetlacza Glass. Więcej informacji znajdziesz w artykule Układ współrzędnych czujnika.
Akcelerometr, żyroskop i magnetometr znajdują się na źródle optycznym urządzenia Glass, które użytkownik obraca, aby dopasować do siebie widok. Nie można bezpośrednio zmierzyć kąta bloku optycznego, dlatego należy o tym pamiętać podczas korzystania z tych czujników w przypadku aplikacji, np. nagłówka.
Aby wydłużyć żywotność baterii, słuchaj czujników tylko wtedy, gdy są Ci potrzebne. Decyzję o tym, kiedy włączyć lub wyłączyć czujniki, weź pod uwagę potrzeby i cykl życia aplikacji.
Wywołania zwrotne zdarzeń z czujnika są wykonywane w wątku użytkownika, więc przetwarzaj zdarzenia i zwracaj je jak najszybciej. Jeśli przetwarzanie trwa zbyt długo, przekaż zdarzenia czujnika do kolejki i zarządzaj nimi za pomocą wątku w tle.
Częstotliwość próbkowania 50 Hz jest często wystarczająca do próbkowania ruchu głowy.
Więcej informacji o używaniu czujników znajdziesz w przewodniku dla programistów Androida.
Usługi lokalizacyjne
Urządzenie Glass Enterprise Edition 2 nie zawiera modułu GPS, a informacje o lokalizacji użytkownika nie są dostępne. Wdrożono jednak usługi lokalizacyjne, które są niezbędne do wyświetlania listy pobliskich sieci Wi-Fi i urządzeń Bluetooth.
Jeśli Twoja aplikacja ma uprawnienia właściciela urządzenia, możesz za jej pomocą automatycznie zmienić wartość odpowiedniego zabezpieczenia:
Kotlin
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)); }
Jeśli korzystasz z rozwiązania MDM innej firmy, musi ono być w stanie zmienić te ustawienia.