Eingaben und Sensoren

Mit dem Android SDK haben Sie Zugriff auf die verschiedenen Eingaben und Sensoren, die mit Glass EE2 verfügbar sind. Auf dieser Seite finden Sie eine Übersicht über die verfügbaren Funktionen, Implementierungsdetails und hilfreiche Tipps.

Einfaches Tippen

Mit dem Android SDK können Sie den Zugriff auf Rohdaten vom Glass-Touchpad aktivieren. Dies wird durch einen Gestenerkennungsmechanismus erreicht, der automatisch gängige Gesten auf Glass wie Tippen, Wischen und Scrollen erkennt.

Sie können diesen Gestenerkennungsmechanismus auch in Ihren Apps verwenden, um Tippen, Wischen nach vorn, Wischen nach hinten und Wischen nach unten zu berücksichtigen. Das ist ähnlich wie bei früheren Glass-Geräten.

Am besten verwenden Sie diese Gesten so:

  • Tippen: Bestätigen oder eingeben.
  • Nach vorn wischen, nach hinten wischen: Hiermit können Sie durch Karten und Bildschirme navigieren.
  • Nach unten wischen: Zurück oder beenden.

Einzelheiten zur Implementierung finden Sie im Beispiel für die Gestenerkennung.

Gesten mit dem Android-Gesterndetektor erkennen

Mit der Android-Klasse GestureDetector können Sie einfache und komplexe Gesten erkennen, z. B. solche, bei denen mehrere Finger verwendet werden oder bei denen gescrollt wird.

Gesten auf Aktivitätsebene erkennen

Erkennen Sie Gesten auf Aktivitätsebene nur, wenn es keine Rolle spielt, welcher Teil Ihrer Benutzeroberfläche den Fokus hat. Wenn Sie beispielsweise ein Menü aufrufen möchten, wenn ein Nutzer auf das Touchpad tippt, unabhängig davon, welche Ansicht den Fokus hat, behandeln Sie MotionEvent in der Aktivität.

Im Folgenden sehen Sie ein Beispiel für die Erkennung von Gesten auf Aktivitätsebene, bei dem GestureDetector verwendet und GestureDetector.OnGestureListener implementiert wird, um erkannte Gesten zu verarbeiten. Diese werden dann verarbeitet und in Folgendes übersetzt:

  • 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);
       }
     }
   }
  }

Verwendungsbeispiel

Damit Sie die Gestenerkennung auf Aktivitätsebene nutzen können, müssen Sie die folgenden Aufgaben ausführen:

  1. Fügen Sie der Manifestdatei innerhalb der Anwendungsdeklaration die folgende Deklaration hinzu. Dadurch kann Ihre App die MotionEvent in der Aktivität empfangen:
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
  2. Überschreiben Sie die dispatchTouchEvent(motionEvent)-Methode der Aktivität, um die Bewegungsereignisse an die onTouchEvent(motionEvent)-Methode des Gestenerkenners zu übergeben.
  3. Implementiere GlassGestureDetector.OnGestureListener in deiner Aktivität.

Das folgende Beispiel zeigt einen Aktivitätserkennungs-Gesten-Detektor:

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);
   }
  }

Audioeingabe

Die Glass Enterprise Edition 2 ist ein standardmäßiges AOSP-basiertes Gerät, das grundlegende Audioquellen unterstützt.

Für die folgenden Audioquellen ist eine erweiterte Signalverarbeitung implementiert:

Spracherkennung

Glass Enterprise Edition 2 unterstützt eine native Implementierung für die Spracherkennung. Diese Funktion wird nur für Englisch unterstützt.

Bild zur Spracherkennung auf der Brille.

Die Benutzeroberfläche für die Spracherkennung wartet, bis ein Nutzer spricht, und gibt dann den transkribierten Text zurück. So startest du die Aktivität:

  1. Rufen Sie startActivityForResult() mit dem Intent ACTION_RECOGNIZE_SPEECH auf. Die folgenden Intent-Extras werden beim Starten der Aktivität unterstützt:
  2. Überschreiben Sie den Callback onActivityResult(), um den transkribierten Text aus dem Intent-Extra EXTRA_RESULTS zu empfangen, wie im folgenden Codebeispiel gezeigt. Dieser Callback wird aufgerufen, wenn der Nutzer mit dem Sprechen fertig ist.

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);
}

Einzelheiten zur Implementierung finden Sie in der Beispiel-App für die Spracherkennung.

Keywords bevorzugen

Die Spracherkennung auf Glass kann für eine Liste von Keywords optimiert werden. Durch die Gewichtung wird die Genauigkeit der Keyword-Erkennung erhöht. So aktivieren Sie die Gewichtung für Keywords:

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);

Sprachbefehle

Mit Sprachbefehlen können Nutzer Aktionen aus Aktivitäten ausführen. Sie erstellen Sprachbefehle mit den Standard-Android-Menü-APIs, aber Nutzer können die Menüelemente mit Sprachbefehlen anstelle von Berührungen aufrufen.

So aktivieren Sie Sprachbefehle für eine bestimmte Aktivität:

  1. Rufen Sie getWindow().requestFeature(FEATURE_VOICE_COMMANDS) in der gewünschten Aktivität auf, um Sprachbefehle zu aktivieren. Wenn diese Funktion aktiviert ist, wird das Mikrofonsymbol  unten links auf dem Bildschirm angezeigt, sobald diese Aktivität im Fokus steht.
  2. Fordern Sie die Berechtigung RECORD_AUDIO in Ihrer App an.
  3. Überschreiben Sie onCreatePanelMenu() und fügen Sie eine Menüressource ein.
  4. Überschreiben Sie onContextItemSelected(), um die erkannten Sprachbefehle zu verarbeiten.

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);
    }
  }
}

Im Folgenden sehen Sie ein Beispiel für die Menüressource, die von der vorherigen Aktivität verwendet wird:

<?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>

Ein vollständiges Beispiel finden Sie in der Beispiel-App für Notizen.

Liste der Sprachbefehle wird neu geladen

Sie können die Liste der Sprachbefehle dynamisch neu laden. Ersetzen Sie dazu die menu-Ressource in der Methode onCreatePanelMenu() oder ändern Sie das Menüobjekt in der Methode onPreparePanel(). Rufen Sie die Methode invalidateOptionsMenu() auf, um die Änderungen zu übernehmen.

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();
}

AppCompatActivity-Lösung

Wenn Sie eine Liste mit Sprachbefehlen in einer Aktivität neu laden möchten, die AppCompatActivity erweitert, verwenden Sie die Methode sendBroadcast() mit der Intent-Aktion reload-voice-commands:

Kotlin

sendBroadcast(Intent("reload-voice-commands"))

Java

sendBroadcast(new Intent("reload-voice-commands"));

Sprachbefehle zur Laufzeit aktivieren und deaktivieren

Sie können Sprachbefehle zur Laufzeit aktivieren und deaktivieren. Geben Sie dazu einen entsprechenden Wert aus der Methode onCreatePanelMenu() zurück:

  • Legen Sie den Wert auf true fest, um die Funktion zu aktivieren.
  • Legen Sie den Wert auf false fest, um die Funktion zu deaktivieren.

Debug-Modus

Wenn Sie den Debugging-Modus für Sprachbefehle aktivieren möchten, rufen Sie getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) in der gewünschten Aktivität auf. Im Debug-Modus werden die folgenden Funktionen aktiviert:

  • Logcat enthält das Log mit dem erkannten Ausdruck für das Debugging.
  • Wenn ein nicht erkannter Befehl erkannt wird, wird ein UI-Overlay angezeigt, wie hier zu sehen:
  • Bild eines nicht erkannten Befehls bei der Spracherkennung von Glass.

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);
  }
  .
  .
  .
}

Weitere Informationen zur Implementierung finden Sie in der Beispiel-App zum Neuladen von Sprachbefehlen.

Sprachausgabe

Die Text-to-Speech-Funktion wandelt digitalen Text in synthetische Sprachausgabe um. Weitere Informationen finden Sie in der Android-Entwicklerdokumentation zu TextToSpeech.

Auf Glass EE2 ist das Google-Sprachausgabemodul installiert. Sie ist als Standard-TTS-Engine festgelegt und funktioniert offline.

Die folgenden Sprachen sind in der Google-Sprachausgabe enthalten:

Bengalisch
Chinesisch (Mandarin)
Tschechisch
Dänisch
Deutsch
Griechisch
Englisch
Spanisch
Estnisch
Finnisch
Französisch
Gujarati
Hindi
Ungarisch
Indonesisch
Italienisch
Japanisch
Javanisch
Austronesisch
Austroasiatisch
Kannada
Koreanisch
Malayalam
Norwegisch
Niederländisch
Polnisch
Portugiesisch
Russisch
Slowakisch
Sundanesisch
Schwedisch
Tamil
Telugu
Thailändisch
Türkisch
Ukrainisch
Vietnamesisch

Kamera

Glass Enterprise Edition 2 ist mit einer 8‑Megapixel-Kamera mit Fixfokus ausgestattet, die eine Blende von f/2.4, ein Sensor-Seitenverhältnis von 4:3 und ein diagonales Sichtfeld von 83° (71° × 57° im Querformat) hat. Wir empfehlen, die Standard-API CameraX oder Camera2 zu verwenden.

Einzelheiten zur Implementierung finden Sie in der Beispiel-Kamera-App.

Schaltfläche "Kamera"

Die Kamerataste ist die physische Taste am Scharnier des Glass Enterprise Edition 2-Geräts. Sie kann wie eine standardmäßige Tastaturaktion behandelt und über den Tastencode KeyEvent#KEYCODE_CAMERA identifiziert werden.

Seit dem Betriebssystemupdate OPM1.200313.001 werden Intents mit den folgenden Aktionen von der Launcher-App gesendet:

Sensoren

Entwicklern steht eine Vielzahl von Sensoren zur Verfügung, wenn sie Anwendungen für Glass EE2 entwickeln.

Die folgenden Standard-Android-Sensoren werden auf Glass unterstützt:

Die folgenden Android-Sensoren werden auf Glass nicht unterstützt:

Das Koordinatensystem des Glass-Sensors ist in der folgenden Abbildung dargestellt. Es ist relativ zum Glasdisplay. Weitere Informationen finden Sie unter Koordinatensystem des Sensors.

Das Koordinatensystem des Glassensors ist hier relativ zum Glasdisplay dargestellt.

Der Beschleunigungsmesser, das Gyroskop und das Magnetometer befinden sich im Optikmodul des Glass-Geräts, das Nutzer drehen, um das Gerät an ihr Sichtfeld anzupassen. Der Winkel des Optik-Pods kann nicht direkt gemessen werden. Berücksichtigen Sie dies, wenn Sie Winkel von diesen Sensoren für Anwendungen wie eine Kompassrichtung verwenden.

Um die Akkulaufzeit zu verlängern, sollten Sie nur dann auf Sensoren zugreifen, wenn Sie sie benötigen. Berücksichtigen Sie die Anforderungen und den Lebenszyklus der App, wenn Sie entscheiden, wann die Sensoren abgehört werden sollen.

Sensorereignis-Callbacks werden im UI-Thread ausgeführt. Verarbeite Ereignisse und Rückgaben daher so schnell wie möglich. Wenn die Verarbeitung zu lange dauert, sollten Sie Sensorereignisse in eine Warteschlange einfügen und sie in einem Hintergrundthread verarbeiten.

50 Hz sind oft eine ausreichende Abtastrate, um Kopfbewegungen zu erfassen.

Weitere Informationen zur Verwendung von Sensoren finden Sie im Android-Entwicklerleitfaden.

Standortdienste

Das Glass Enterprise Edition 2-Gerät ist nicht mit einem GPS-Modul ausgestattet und gibt den Standort des Nutzers nicht an. Es sind jedoch Standortdienste implementiert, die erforderlich sind, um eine Liste der WLANs und Bluetooth-Geräte in der Nähe anzuzeigen.

Wenn Ihre Anwendung Berechtigungen als Geräteinhaber hat, können Sie damit den Wert der entsprechenden sicheren Einstellung programmatisch ändern:

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));
}

Wenn Sie eine MDM-Lösung eines Drittanbieters verwenden, muss diese in der Lage sein, diese Einstellungen für Sie zu ändern.