Lokalizacje i czujniki

Dostęp do danych o lokalizacji i danych z czujników można uzyskać za pomocą standardowego systemu Android za pomocą interfejsów API platformy Google.

Lokalizacja

Lokalizacja na Google Glass wymaga użycia standardowego systemu Android interfejsów API platformy do pobierania danych o lokalizacji, dostawcy usług lokalizacyjnych.

Użyjesz tych klas pakietu Android SDK, aby uzyskać dane o lokalizacji:

  • LocationManager – Zapewnia dostęp do usługi systemu lokalizacji Android która obsługuje komunikację z LocationProvider

  • LocationProvider – Podaje dane o lokalizacji na podstawie pewnych kryteriów. Google Glass oferuje specjalny „zdalny pilot” usługodawcy które umożliwiają uzyskanie danych o lokalizacji ze sparowanego urządzenia z technologią MyGlass. Zainstalowano aplikację towarzyszącą.

  • Criteria – Pozwala utworzyć zestaw kryteriów, wybiera najlepsze LocationProvider na podstawie ustawionych przez Ciebie kryteriów.

Omówienie

Aby uzyskać dane o lokalizacji, należy korzystać z LocationManager , aby uzyskać dane od co najmniej jednego dostawcy lokalizacji.

Aplikacje na telefonie lub tablecie z Androidem pobierają dane o lokalizacji z lokalnych GPS i operatorzy lokalizacji sieciowej na urządzeniu. Na Google Glass zestaw dostępnych dostawców lokalizacji jest dynamiczny i może zawierać opcję zdalne dostawcy danych o lokalizacji, którzy dostarczają dane o lokalizacji z innego źródła, np. Urządzenie sparowane przez Bluetooth z zainstalowaną aplikacją towarzyszącą MyGlass. Do obsługi mogą nasłuchiwać aktualizacji lokalizacji wielu różnych dostawców usługodawcy, a nie jednego dostawcy.

Aby poprosić o dostęp do danych od wszystkich dostępnych dostawców lokalizacji:

  1. Tworzenie Criteria z wymaganiami dotyczącymi lokalizacji.
  2. Zadzwoń pod numer getProviders() aby uzyskać listę włączonych dostawców, którzy spełniają podane kryteria.
  3. Wykonanie iteracji na liście dostawców i prośba o aktualność od wszystkich Dzięki temu będziesz otrzymywać aktualizacje od dostawców zdalnych, jeśli do nich ale też od lokalnych operatorów w Google Glass (takich jak operatora sieci komórkowej).
  4. Wykorzystaj informacje o dokładności i czasie podawane w każdym z nich. aby określić, czy aktualizacja jest wystarczająca, poczekaj na kolejną.

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

Czujniki

Szkło

Glass ma specjalny czujnik wykrywający, czy urządzenie znajduje się na użytkowników głowa. Po włączeniu tego ustawienia pomaga oszczędzać baterię, gdy urządzenie nie jest w użyciu. Za pomocą tej funkcji w oprogramowaniu Glassware możesz wyłączyć lub ograniczanie dostępu do usług w tle. Zacznij od wdrożenia BroadcastReceiver w celu wykrycia ACTION_ON_HEAD_STATE_CHANGE zdarzeń.

Ten przykład opóźnia i wyłącza aktualizacje wyników gier na podstawie tego, użytkownik wyjął Glass z głowy:

  1. Zaimplementuj BroadcastReceiver aby obsłużyć zmianę stanu.
  2. W swojej usłudze zaimplementuj onCreate() i zarejestruj odbiornik, który nasłuchuje ACTION_ON_HEAD_STATE_CHANGE.
  3. W onDestroy() , wyrejestruj odbiorcę.

    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

Google Glass obsługuje te czujniki z Androidem:

Te czujniki Androida nie są obsługiwane:

.

Oto kilka wskazówek dotyczących korzystania z czujników w Google Glass:

  • Akcelerometr, żyroskop i magnetometr znajdują się na obudowie optycznej urządzenia Glass. które użytkownicy obracają, aby dopasować urządzenie do wzroku. Nie można zmierzyć pod określonym kątem. Trzeba o tym pamiętać, na przykład przy określaniu kierunku kompasu.

  • Aby wydłużyć czas pracy na baterii, nasłuchuj czujników tylko wtedy, gdy są potrzebne. Jeśli na przykład oprogramowanie Glassware używa Service do renderowania LiveCard Czujniki są potrzebne tylko wtedy, gdy widoczna jest aktywna karta, LiveCard wyświetla metody wywołania zwrotnego, aby rozpocząć i zatrzymać nasłuchiwanie czujników.

  • Wywołania zwrotne zdarzeń czujnika są uruchamiane w wątku UI, więc przetwarzają zdarzenia i zwracają wartość jak najszybciej. Rozważ przeniesienie zdarzeń z czujnika do kolejki i użycie wątku w tle w celu ich obsłużenia, jeśli przetwarzanie będzie trwało zbyt długo.

  • 50 Hz jest często wystarczającą częstotliwością próbkowania do śledzenia ruchu głowy.

Więcej informacji o korzystaniu z czujników znajdziesz w Przewodnik dla programistów Androida