Standorte und Sensoren

Sie greifen über die standardmäßigen Android-Plattform-APIs auf Standort- und Sensordaten zu.

Standort

Für die Funktion „Standortdienste in Glass“ werden die standardmäßigen Android-Plattform-APIs verwendet, um Standortdaten von verfügbaren Standortanbietern abzurufen.

Mit den folgenden Android SDK-Klassen können Sie Standortdaten abrufen:

  • LocationManager – Bietet Zugriff auf den Android-Standortsystemdienst, der die Kommunikation mit einem LocationProvider übernimmt.

  • LocationProvider – Stellt Standortdaten basierend auf einigen Kriterien bereit. Glass stellt spezielle Remote-Anbieter bereit, mit denen Sie Standortdaten von einem gekoppelten Gerät abrufen können, auf dem die MyGlass-Companion-App installiert ist.

  • Criteria – Hiermit können Sie eine Reihe von Kriterien erstellen, die basierend auf den von Ihnen festgelegten Kriterien die besten LocationProvider auswählen.

Übersicht

Zum Abrufen von Standortdaten müssen Sie die Klasse LocationManager verwenden, um Daten von einem oder mehreren Standortanbietern abzurufen.

Anwendungen auf einem Android-Smartphone oder -Tablet rufen Standortdaten von lokalen GPS- und Netzwerkstandortanbietern auf dem Gerät ab. In Glass ist die Gruppe der verfügbaren Standortanbieter jedoch dynamisch und kann Remote-Standortanbieter enthalten, die Standortdaten aus einer anderen Quelle bereitstellen, z. B. ein mit Bluetooth gekoppeltes Gerät, auf dem die MyGlass-Companion-App installiert ist. Achten Sie zur Verarbeitung dieser zusätzlichen Anbieter auf Standortaktualisierungen von mehreren Anbietern anstelle eines einzelnen Anbieters.

So fordern Sie Daten von allen verfügbaren Standortanbietern an:

  1. Erstellen Sie ein Criteria-Objekt mit Ihren Standortanforderungen.
  2. Rufen Sie getProviders() auf, um die Liste der aktivierten Anbieter abzurufen, die Ihren Kriterien entsprechen.
  3. Gehen Sie die Liste der Anbieter durch und fordern Sie bei allen Anbietern Aktualisierungen an. Dadurch wird sichergestellt, dass Sie Updates von den Remote-Anbietern erhalten, wenn sie verfügbar sind, aber auch von den lokalen Anbietern in Glass (z. B. einem WLAN-Anbieter).
  4. Bestimmen Sie anhand der bei jeder Aktualisierung angegebenen Genauigkeits- und Zeitangaben, ob die Aktualisierung ausreicht oder ob Sie auf eine weitere Aktualisierung warten sollten.

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

Sensoren

Glas

Glass hat einen speziellen Sensor, der erkennt, ob sich das Gerät am Kopf des Nutzers befindet. Wenn diese Einstellung aktiviert ist, schont das Gerät den Akku, wenn das Gerät nicht verwendet wird. Sie können dieses Feature in Ihrer Glassware verwenden, um Hintergrunddienste zu deaktivieren oder zu drosseln. Implementieren Sie zuerst einen BroadcastReceiver, um ACTION_ON_HEAD_STATE_CHANGE-Ereignisse zu erkennen.

Im folgenden Beispiel wird die Aktualisierung von Spielständen abhängig davon, ob der Nutzer Glass von seinem Kopf entfernt hat, verzögert und deaktiviert:

  1. Implementieren Sie BroadcastReceiver, um die Statusänderung zu verarbeiten.
  2. Implementieren Sie in Ihrem Dienst die Methode onCreate() und registrieren Sie einen Empfänger, der den Intent ACTION_ON_HEAD_STATE_CHANGE überwacht.
  3. Heben Sie in der Methode onDestroy() die Registrierung des Empfängers auf.

    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

Die folgenden Android-Sensoren werden in Glass unterstützt:

Die folgenden Android-Sensoren werden nicht unterstützt:

Hier einige Tipps zur Verwendung von Sensoren in Glass:

  • Das Koordinatensystem für Glass-Sensoren wird relativ zum Glass-Display angezeigt. Weitere Informationen finden Sie unter Sensorkoordinatensystem.

  • Beschleunigungsmesser, Gyroskop und Magnetometer befinden sich auf der optischen Kappe des Glass-Geräts, die Nutzer drehen, um das Gerät am Sichtfeld auszurichten. Sie können den Winkel des optischen Pods nicht direkt messen. Berücksichtigen Sie dies, wenn Sie den Winkel dieser Sensoren für Anwendungen wie die Kompassausrichtung verwenden.

  • Damit der Akku geschont wird, sollten Sie Sensoren nur bei Bedarf nutzen. Wenn Ihre Glassware beispielsweise eine Service verwendet, um einen LiveCard zu rendern, und Sie die Sensoren nur benötigen, wenn die Live-Karte sichtbar ist, können Sie die Callback-Funktion für die Oberflächensensoren mithilfe der LiveCard-Methoden zum Starten und Beenden beenden.

  • Sensorereignis-Callbacks werden im UI-Thread ausgeführt. Verarbeiten Sie Ereignisse daher so schnell wie möglich. Verschieben Sie Sensorereignisse in eine Warteschlange und verwenden Sie einen Hintergrundthread, um sie zu verarbeiten, wenn die Verarbeitung zu lange dauert.

  • 50 Hz reicht oft aus, um die Kopfbewegungen zu erfassen.

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