Posizioni e sensori

Accedi ai dati sulla posizione e ai sensori utilizzando le API standard della piattaforma Android.

Località

La geolocalizzazione su Glass prevede l'utilizzo delle API standard della piattaforma Android per recuperare i dati sulla posizione dai provider di geolocalizzazione disponibili.

Per ottenere i dati sulla posizione verranno utilizzate le seguenti classi di SDK Android:

  • LocationManager: fornisce l'accesso al servizio di geolocalizzazione di Android che gestisce la comunicazione con LocationProvider.

  • LocationProvider: fornisce dati sulla posizione basati su alcuni criteri. Glass fornisce speciali provider "remoti" che ti consentono di ottenere i dati sulla posizione da un dispositivo accoppiato su cui è installata l'app companion MyGlass.

  • Criteria: consente di creare un insieme di criteri che selezionano il LocationProvider migliore in base ai criteri impostati.

Panoramica

Per ottenere i dati sulla posizione, devi utilizzare la classe LocationManager per ottenere i dati da uno o più fornitori di posizione.

Le applicazioni su un telefono o tablet Android recuperano i dati sulla posizione dai GPS locali e dai provider di geolocalizzazione della rete sul dispositivo. Tuttavia, su Glass l'insieme di fornitori di posizione disponibili è dinamico e può includere fornitori di posizione remoti che forniscono dati sulla posizione da un'altra fonte, ad esempio un dispositivo accoppiato tramite Bluetooth con l'app companion MyGlass installata. Per gestire questi provider aggiuntivi, ascolta gli aggiornamenti della posizione di più provider anziché di un singolo provider.

Per richiedere i dati di tutti i fornitori di posizione disponibili:

  1. Crea un oggetto Criteria con i requisiti di posizione.
  2. Richiama getProviders() per recuperare l'elenco dei provider attivati che soddisfano i tuoi criteri.
  3. Ripeti l'elenco dei provider e richiedi aggiornamenti da parte di ciascuno. In questo modo puoi assicurarti di ricevere aggiornamenti dai provider remoti, se disponibili, ma anche dai provider locali su Glass (ad esempio un provider di rete wireless).
  4. Utilizza le informazioni su accuratezza e tempistiche fornite con ogni aggiornamento per determinare se l'aggiornamento è sufficiente o se devi attendere un altro aggiornamento.

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

Sensori

Vetro

Glass ha un sensore specializzato per rilevare se il dispositivo si trova sulla testa degli utenti. Quando è attiva, questa impostazione consente di risparmiare batteria quando il dispositivo non è in uso. Puoi utilizzare questa funzionalità in Glassware per disattivare o limitare i servizi in background. Per iniziare, implementa una risorsa BroadcastReceiver per rilevare gli eventi ACTION_ON_HEAD_STATE_CHANGE.

L'esempio seguente ritarda e disattiva gli aggiornamenti del punteggio del gioco in base al fatto che l'utente abbia rimosso Glass dalla testa:

  1. Implementa un BroadcastReceiver per gestire la modifica dello stato.
  2. Nel servizio, implementa il metodo onCreate() e registra un destinatario in ascolto dell'intent ACTION_ON_HEAD_STATE_CHANGE.
  3. Nel metodo onDestroy(), annulla la registrazione del destinatario.

    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

Su Glass sono supportati i seguenti sensori Android:

I seguenti sensori Android non sono supportati:

Ecco alcuni suggerimenti quando utilizzi i sensori su Glass:

  • Il sistema di coordinate del sensore di vetro è mostrato di seguito rispetto al display di Glass. Per ulteriori informazioni, consulta Sistema di coordinate del sensore.

  • L'accelerometro, il giroscopio e il magnetometro si trovano sul pod ottico del dispositivo Glass, che gli utenti ruotano per allineare il dispositivo al proprio campo visivo. Non puoi misurare direttamente l'angolo del pod ottico, quindi tienilo presente quando utilizzi gli angoli di questi sensori per applicazioni come l'intestazione della bussola.

  • Per prolungare la durata della batteria, ascolta i sensori solo quando ti servono. Ad esempio, se il tuo Glassware utilizza un elemento Service per eseguire il rendering di LiveCard e ti servono soltanto quando i sensori sono visibili, usa i metodi di callback di superficie LiveCard per avviare e interrompere l'ascolto dei sensori.

  • I callback degli eventi del sensore vengono eseguiti sul thread dell'interfaccia utente, quindi elabora gli eventi e torna il più rapidamente possibile. Ti consigliamo di inviare gli eventi del sensore in coda e di utilizzare un thread in background per gestirli se l'elaborazione richiede troppo tempo.

  • La frequenza a 50 Hz è spesso una frequenza di campionamento sufficiente per monitorare il movimento della testa.

Per ulteriori informazioni su come utilizzare i sensori, consulta la Guida per gli sviluppatori di Android.