Emplacements et capteurs

Vous pouvez accéder aux données de localisation et aux capteurs à l'aide des API standards de la plate-forme Android.

Emplacement

La fonctionnalité de localisation sur Glass implique l'utilisation des API de la plate-forme Android standards pour obtenir les données de localisation des fournisseurs de services disponibles.

Vous allez utiliser les classes suivantes du SDK Android pour obtenir des données de localisation:

  • LocationManager : permet d'accéder au service du système de localisation Android qui gère la communication avec un LocationProvider

  • LocationProvider : fournit des données de localisation en fonction de certains critères. Glass fournit des fournisseurs "distants" spéciaux qui vous permettent d'obtenir des données de localisation à partir d'un appareil associé sur lequel l'application associée MyGlass est installée.

  • Criteria : permet de créer un ensemble de critères qui sélectionnent les meilleurs éléments LocationProvider en fonction des critères que vous définissez.

Présentation

Pour obtenir les données de localisation, vous devez utiliser la classe LocationManager pour obtenir les données d'un ou de plusieurs fournisseurs de services de localisation.

Les applications installées sur un téléphone ou une tablette Android récupèrent les données de localisation auprès des fournisseurs de localisation GPS et de réseau local sur l'appareil. Toutefois, sur Glass, l'ensemble des fournisseurs de position géographique disponibles est dynamique et peut inclure des fournisseurs de services de localisation à distance qui fournissent des données de localisation à partir d'une autre source, comme un appareil associé en Bluetooth sur lequel l'application associée MyGlass est installée. Pour gérer ces fournisseurs supplémentaires, écoutez les mises à jour de la position de plusieurs fournisseurs plutôt que d'un seul.

Pour demander les données de tous les fournisseurs de services de localisation disponibles:

  1. Créez un objet Criteria répondant à vos exigences de localisation.
  2. Appelez getProviders() pour récupérer la liste des fournisseurs activés répondant à vos critères.
  3. Parcourez la liste des fournisseurs et demandez à les mettre à jour. Cela garantit que vous recevez les mises à jour des fournisseurs distants s'ils sont disponibles, mais également des fournisseurs locaux sur Glass (tels qu'un fournisseur de réseau sans fil).
  4. Utilisez les informations de précision et de synchronisation fournies avec chaque mise à jour pour déterminer si elle est suffisamment satisfaisante ou si vous devez attendre une autre mise à jour.

    LocationManager locationManager; // initialized elsewhere
    
    // This example requests fine accuracy and requires altitude, but
    // these criteria could be whatever you want.
    Criteria criteria = new Criteria();
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(true);
    
    List<String> providers = locationManager.getProviders(
            criteria, true /* enabledOnly */);
    
    for (String provider : providers) {
        locationManager.requestLocationUpdates(provider, minTime,
                minDistance, listener);
    }
    

Capteurs

Verre

Glass dispose d'un capteur spécialisé pour détecter si l'appareil est sur la tête de l'utilisateur ou non. Lorsqu'il est activé, ce paramètre permet d'économiser la batterie lorsque l'appareil n'est pas utilisé. Vous pouvez utiliser cette fonctionnalité dans votre Glassware pour désactiver ou limiter les services en arrière-plan. Commencez par implémenter un BroadcastReceiver pour détecter les événements ACTION_ON_HEAD_STATE_CHANGE.

L'exemple suivant retarde et désactive les mises à jour des scores de jeu selon que l'utilisateur a supprimé les lunettes Glass de sa tête:

  1. Implémentez un objet BroadcastReceiver pour gérer le changement d'état.
  2. Dans votre service, implémentez la méthode onCreate() et enregistrez un récepteur qui écoute l'intent ACTION_ON_HEAD_STATE_CHANGE.
  3. Dans la méthode onDestroy(), annulez l'enregistrement du destinataire.

    import com.google.android.glass.content.Intents;
    ...
    
    public class LiveCardService extends Service {
    
        ...
        private boolean mIsStopped = false;
    
        private final BroadcastReceiver broadCastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
    
                if (Intents.ACTION_ON_HEAD_STATE_CHANGED.equals(intent.getAction())) {
                    boolean onHead = intent.getBooleanExtra(Intents.EXTRA_IS_ON_HEAD,
                            false);
                    if (onHead) {
                        mDelay = LiveCardService.DELAY_MILLIS;
                        if (isStopped()) {
                            // Resume updating scores
                            setStop(false);
    
                            // Restart immediately to get a refreshed score
                            mHandler.postDelayed(mUpdateLiveCardRunnable, 0);
                        }
                    } else {
                        // Increase the delay when the device is off head
                        mDelay = LiveCardService.DELAY_MILLIS_EXT;
                    }
                }
            }
        };
    
        private final Runnable mUpdateLiveCardRunnable = new Runnable() {
    
            @Override
            public void run() {
    
                if (mDelay == DELAY_MILLIS_EXT) {
                    // Count the increased delay as a retry attempt
                    mRetryCount++;
                } else if (mDelay == DELAY_MILLIS) {
                    mRetryCount = 0;
                }
    
                if (mRetryCount > MAX_RETRIES) {
                    // Stop updating scores
                    mIsStopped = true;
                }
    
                if (!isStopped()) {
                    // Generate fake points.
                    homeScore += mPointsGenerator.nextInt(3);
                    awayScore += mPointsGenerator.nextInt(3);
    
                    // Update the remote view with the new scores.
                    mLiveCardView = getRemoteViews(homeScore, awayScore);
    
                    // Always call setViews() to update the live card's RemoteViews.
                    mLiveCard.setViews(mLiveCardView);
    
                    // Queue another score update in 30 seconds.
                    mHandler.postDelayed(mUpdateLiveCardRunnable, mDelay);
                }
            }
        };
    
        @Override
        public void onCreate() {
            super.onCreate();
            mPointsGenerator = new Random();
            mDelay = DELAY_MILLIS;
    
            registerReceiver(broadCastReceiver, new IntentFilter(
                    Intents.ACTION_ON_HEAD_STATE_CHANGED));
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            if (mLiveCard == null) {
    
                // Get an instance of a live card
                mLiveCard = new LiveCard(this, LIVE_CARD_TAG);
    
                // Inflate a layout into a remote view
                mLiveCardView = new RemoteViews(getPackageName(),
                        R.layout.live_card);
    
                // Set up initial RemoteViews values
                homeScore = 0;
                awayScore = 0;
                mLiveCardView = getRemoteViews(homeScore, awayScore);
    
                // Set up the live card's action with a pending intent
                // to show a menu when tapped
                Intent menuIntent = new Intent(this, LiveCardMenuActivity.class);
                menuIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                        Intent.FLAG_ACTIVITY_CLEAR_TASK);
                mLiveCard.setAction(PendingIntent.getActivity(
                        this, 0, menuIntent, 0));
    
                // Publish the live card
                mLiveCard.publish(PublishMode.REVEAL);
    
                // Queue the update text runnable
                mHandler.post(mUpdateLiveCardRunnable);
            }
    
            return START_STICKY;
        }
    
        @Override
        public void onDestroy() {
            if (mLiveCard != null && mLiveCard.isPublished()) {
                //Stop the handler from queuing more Runnable jobs
                setStop(true);
    
                mLiveCard.unpublish();
                mLiveCard = null;
            }
    
            unregisterReceiver(broadCastReceiver);
    
            super.onDestroy();
        }
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        private RemoteViews getRemoteViews(int homeScore, int awayScore) {
            RemoteViews remoteViews = new RemoteViews(getPackageName(),
                    R.layout.live_card);
    
            remoteViews.setTextViewText(R.id.home_team_name_text_view,
                    getString(R.string.home_team));
            remoteViews.setTextViewText(R.id.away_team_name_text_view,
                    getString(R.string.away_team));
            remoteViews.setTextViewText(R.id.footer_text,
                    getString(R.string.game_quarter));
    
            remoteViews.setTextViewText(R.id.home_score_text_view,
                    String.valueOf(homeScore));
            remoteViews.setTextViewText(R.id.away_score_text_view,
                    String.valueOf(awayScore));
            return remoteViews;
        }
    
        public boolean isStopped() {
            return mIsStopped;
        }
    
        public void setStop(boolean isStopped) {
            mIsStopped = isStopped;
        }
    }
    

Android

Les capteurs Android suivants sont compatibles avec Glass:

Les capteurs Android suivants ne sont pas compatibles:

Voici quelques conseils concernant l'utilisation des capteurs sur les lunettes Glass:

  • L'accéléromètre, le gyroscope et le magnétomètre sont situés sur le module optique de l'appareil Glass, que les utilisateurs font pivoter pour aligner l'appareil avec leur vue. Vous ne pouvez pas mesurer directement l'angle du pod optique. Vous devez donc en tenir compte lorsque vous utilisez les angles de ces capteurs pour des applications telles que l'orientation de la boussole.

  • Pour préserver l'autonomie de la batterie, n'écoutez les capteurs que lorsque vous en avez besoin. Par exemple, si votre Glassware utilise un Service pour afficher un LiveCard et que vous n'avez besoin que des capteurs lorsque la carte active est visible, utilisez les méthodes de rappel de surface LiveCard pour démarrer et arrêter l'écoute des capteurs.

  • Les rappels d'événements des capteurs s'exécutent sur le thread UI. Par conséquent, traitez les événements et revenez le plus rapidement possible. Envisagez de placer les événements de capteur dans une file d'attente et de les traiter en arrière-plan si le traitement prend trop de temps.

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

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