Entrées et capteurs

Le SDK Android vous permet d'accéder aux différentes entrées et capteurs disponibles avec Glass EE2. Cette page offre un aperçu des fonctionnalités disponibles, des détails de mise en œuvre et des conseils utiles.

Gestes pour appuyer

Vous pouvez utiliser le SDK Android pour permettre l'accès aux données brutes depuis le pavé tactile Glass. Pour ce faire, elles utilisent un détecteur de gestes qui détecte automatiquement les gestes les plus courants sur Glass, comme les gestes d'appui, de balayage ou de défilement.

Vous pouvez également utiliser ce détecteur dans vos applications pour tenir compte des gestes d'appui, de balayage vers l'avant, de balayage vers le bas et vers le bas. Cette fonctionnalité est semblable aux appareils Glass précédents.

Il est préférable d'utiliser ces gestes de différentes manières:

  • Appuyer: confirmez ou appuyez sur Entrée.
  • Balayez l'écran vers l'avant, balayez l'écran vers l'arrière: parcourez les cartes et les écrans.
  • Balayer vers le bas : "Retour"ou"Quitter".

Pour en savoir plus sur l'implémentation, consultez l'exemple de détecteur de geste.

Détecter des gestes avec le détecteur de gestes Android

L'GestureDetector Android vous permet de détecter des gestes simples et complexes, tels que ceux qui utilisent plusieurs doigts ou font défiler des éléments.

Détecter les gestes d'activité

Détectez les gestes au niveau de l'activité uniquement lorsqu'il n'est pas nécessaire de contrôler les parties de l'interface utilisateur concernées. Par exemple, si vous souhaitez afficher un menu lorsqu'un utilisateur appuie sur le pavé tactile, quelle que soit la vue sélectionnée, gérez l'élément MotionEvent dans l'activité.

Voici un exemple de détection des gestes au niveau de l'activité qui utilise GestureDetector et met en œuvre GestureDetector.OnGestureListener pour traiter les expressions faciales reconnues, qui sont ensuite traitées et traduites comme suit:

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

Exemple d'utilisation

Pour pouvoir utiliser la détection des gestes au niveau de l'activité, vous devez effectuer les tâches suivantes:

  1. Ajoutez la déclaration suivante à votre fichier manifeste, dans la déclaration d'application. Cela permet à votre application de recevoir le MotionEvent dans l'activité :
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
    
  2. Remplacez la méthode d'activité dispatchTouchEvent(motionEvent) pour transmettre les événements de mouvement à la méthode onTouchEvent(motionEvent) du détecteur de gestes.
  3. Implémentez GlassGestureDetector.OnGestureListener dans votre activité.

Voici un exemple de détecteur de gestes au niveau de l'activité:

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

Entrée audio

Glass Enterprise Edition 2 est un appareil standard basé sur AOSP compatible avec les sources audio de base.

Le traitement des signaux avancé est intégré aux sources audio suivantes:

Reconnaissance vocale

Glass Enterprise Edition 2 propose une implémentation native pour la reconnaissance vocale. Cette option n'est disponible qu'en anglais.

Image de la reconnaissance vocale Glass

L'interface de reconnaissance vocale attend que l'utilisateur parle, puis renvoie le texte transcrit. Pour démarrer l'activité, procédez comme suit:

  1. Appelez startActivityForResult() avec l'intent ACTION_RECOGNIZE_SPEECH. Les options d'intent supplémentaires suivantes sont disponibles lorsque vous démarrez l'activité :
  2. Ignorez le rappel onActivityResult() pour recevoir le texte transcrit de l'intent EXTRA_RESULTS supplémentaire, comme indiqué dans l'exemple de code suivant. Ce rappel est appelé lorsque l'utilisateur a fini de parler.

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

Pour en savoir plus sur l'implémentation, consultez l'exemple d'application de reconnaissance vocale.

Limiter les résultats aux mots clés

La reconnaissance vocale sur Glass peut être biaisée pour une liste de mots clés. La pondération augmente la précision de la reconnaissance des mots clés. Pour activer la pondération des mots clés, utilisez le code suivant:

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

Commandes vocales

Les commandes vocales permettent aux utilisateurs d'effectuer des actions à partir d'activités. Vous pouvez créer des commandes vocales avec les API de menu Android standards, mais les utilisateurs peuvent appeler les éléments de menu à l'aide de commandes vocales au lieu d'appuyer.

Pour activer les commandes vocales pour une activité précise, procédez comme suit:

  1. Appelez getWindow().requestFeature(FEATURE_VOICE_COMMANDS) dans l'activité souhaitée pour activer les commandes vocales. Lorsque cette fonctionnalité est activée, l'icône du micro apparaît en bas à gauche de l'écran chaque fois que cette activité est sélectionnée.
  2. Demandez l'autorisation RECORD_AUDIO dans votre application.
  3. Ignorez onCreatePanelMenu() et gonflez une ressource de menu.
  4. Ignorez onContextItemSelected() pour gérer les commandes vocales détectées.

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

Voici un exemple de ressource de menu utilisée par l'activité précédente:

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

Lisez l'exemple d'application de prise de notes pour obtenir un exemple complet.

Actualisation de la liste de commandes vocales

Vous pouvez actualiser dynamiquement la liste des commandes vocales. Pour ce faire, remplacez la ressource menu dans la méthode onCreatePanelMenu() ou modifiez l'objet de menu dans la méthode onPreparePanel(). Pour appliquer les modifications, appelez la méthode 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();
}

Solution AppCompatActivity

Pour recharger une liste de commandes vocales dans une activité qui étend AppCompatActivity, utilisez la méthode sendBroadcast() avec l'action reload-voice-commands:

Kotlin

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

Java

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

Activer et désactiver les commandes vocales dans l'environnement d'exécution

Vous pouvez activer et désactiver les commandes vocales pendant l'exécution. Pour ce faire, renvoyez une valeur appropriée à partir de la méthode onCreatePanelMenu(), comme suit:

  • Définissez la valeur sur true pour l'activer.
  • Définissez la valeur sur false pour la désactiver.

Mode débogage

Pour activer le mode débogage pour les commandes vocales, appelez getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) dans l'activité souhaitée. Le mode débogage active les fonctionnalités suivantes:

  • Logcat contient le journal contenant l'expression reconnue pour le débogage.
  • Une superposition d'interface utilisateur s'affiche lorsqu'une commande non reconnue est détectée, comme illustré ci-dessous:
  • Image de commande non reconnue via la reconnaissance vocale 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);
  }
  .
  .
  .
}

Pour en savoir plus sur l'implémentation, consultez l'exemple d'application permettant de recharger les commandes vocales.

Synthèse vocale

La fonctionnalité de synthèse vocale convertit le texte numérique en sortie vocale synthétisée. Pour en savoir plus, consultez la documentation TextToSpeech d'Android Developers.

Le moteur Google Text-to-Speech est installé sur Glass EE2. Il s'agit du moteur de synthèse vocale par défaut qui fonctionne hors connexion.

Les paramètres régionaux suivants sont intégrés au moteur de synthèse vocale Google:

Bengali
Chinois mandarin
Tchèque
Danois
Allemand
Grec
Anglais
Espagnol
Estonien
Finnois
Français
Gujarati
hindi
Hongrois
Indonésien
Italien
Japonais
Javanais
Austronésien
Austroasiatique
Kannada
Coréen
Malayalam
Norvégien
Néerlandais
Polonais
Portugais
Russe
Slovaque
Soudanais
Suédois
Tamoul
Télougou
Thaï
Turc
Ukrainien
Vietnamien

Caméra

Glass Enterprise Edition 2 est équipé d'une caméra à mise au point fixe de 8 mégapixels avec une ouverture de f/2,4, des proportions de 4:3 et un champ de vision de 83° en diagonale (71° x 57° en orientation paysage). Nous vous recommandons d'utiliser l'API standard CameraX ou Camera2.

Pour en savoir plus sur l'implémentation, consultez l'exemple d'application d'appareil photo.

Bouton de l'appareil photo

Le bouton de l'appareil photo est le bouton physique situé sur la charnière de l'appareil Glass Enterprise Edition 2. Elle peut être gérée comme une action de clavier standard, et elle peut être identifiée par le code-clé KeyEvent#KEYCODE_CAMERA.

À compter de la mise à jour de l'OS OPM1.200313.001, les intents ayant les actions suivantes sont envoyés à partir de l'application de lancement:

Capteurs

Différents capteurs sont disponibles pour les développeurs qui développent des applications dans Glass EE2.

Les capteurs Android standards suivants sont compatibles avec Glass:

Les capteurs Android suivants ne sont pas compatibles avec Glass:

Le système de coordonnées du capteur Glass est illustré dans l'illustration suivante. Par rapport à l'écran Glass. Pour en savoir plus, consultez la section Système de coordonnées du capteur.

Le système de coordonnées du capteur Glass est présenté ici, par rapport à l&#39;écran Glass.

L'accéléromètre, le gyroscope et le magnétomètre sont situés sur la sonde optique de l'appareil Glass, que les utilisateurs font pivoter pour aligner l'appareil sur leur champ de vision. Il n'est pas possible de mesurer directement l'angle du pod optique. Il est donc important de tenir compte de ce point lorsque vous utilisez des angles de ces capteurs pour des applications telles qu'une direction de boussole.

Pour prolonger l'autonomie de la batterie, n'écoutez les capteurs que lorsque vous en avez besoin. Lorsque vous décidez de lancer ou d'arrêter l'écoute des capteurs, tenez compte des besoins et du cycle de vie de l'application.

Les rappels d'événement des capteurs s'exécutent sur le thread UI. Par conséquent, traitez les événements et renvoyez-les aussi rapidement que possible. Si le traitement prend trop de temps, placez les événements de capteurs dans une file d'attente et utilisez un thread d'arrière-plan pour les gérer.

La fréquence de 50 Hz est souvent suffisante pour suivre les mouvements de la tête.

Pour en savoir plus sur l'utilisation des capteurs, consultez le guide du développeur Android.

Services de localisation

L'appareil Glass Enterprise Edition 2 n'est pas doté d'un module GPS et ne fournit pas la position de l'utilisateur. Toutefois, les services de localisation sont mis en œuvre, ce qui est nécessaire pour afficher la liste des réseaux Wi-Fi et des appareils Bluetooth à proximité.

Si votre application dispose des droits de propriétaire de l'appareil, vous pouvez l'utiliser pour modifier de manière programmatique la valeur du paramètre sécurisé correspondant:

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

Si vous utilisez une solution MDM tierce, celle-ci doit pouvoir modifier ces paramètres à votre place.