Locais e sensores

Você acessa dados de local e do sensor usando a API Android nas APIs da plataforma do Google Cloud.

Local

A localização no Google Glass envolve o uso da API Android de APIs da plataforma para acessar os dados de localização provedores de localização.

Você vai usar as seguintes classes do SDK do Android para receber dados de local:

  • LocationManager – Fornece acesso ao serviço do sistema de localização do Android que lida com a comunicação LocationProvider

  • LocationProvider – Fornece dados de local com base em alguns critérios. O Google Glass oferece um "remoto" especial provedores que permitem obter dados de localização de um dispositivo pareado que tem o MyGlass aplicativo complementar instalado.

  • Criteria – Permite criar um conjunto de critérios que seleciona o melhor LocationProvider com base nos critérios definidos.

Visão geral

Para obter os dados de local, você precisará usar o LocationManager para receber dados de um ou mais provedores de localização.

Aplicativos em um smartphone ou tablet Android recuperam dados de local de GPS e provedores de localização de rede no dispositivo. No Google Glass, no entanto, de provedores de localização disponíveis é dinâmico e pode incluir provedores de localização remoto provedores de localização que fornecem dados de localização de outra fonte, como um Dispositivo pareado por Bluetooth com o app complementar MyGlass instalado. Para processar esses provedores adicionais, ouça as atualizações de local de vários provedores em vez de um único provedor.

Para solicitar dados de todos os provedores de localização disponíveis:

  1. Criar um Criteria com seus requisitos de localização.
  2. Chamar getProviders() para recuperar a lista de provedores ativados que atendem aos seus critérios.
  3. Iterar na lista de provedores e solicitar atualizações de todos eles. Isso garante que você receba atualizações dos provedores remotos se eles forem disponíveis, mas também de fornecedores locais no Google Glass (como uma rede provedora de rede).
  4. Use as informações de precisão e tempo fornecidas em cada atualizar para determinar se a atualização é boa o suficiente ou se você deve espere outro.

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

Sensores

Vidro

O Google Glass tem um sensor especializado para detectar se o dispositivo está ou não no dos usuários a cabeça. Quando ativada, esta configuração ajuda a economizar bateria quando o dispositivo não está em uso. Você pode usar esse recurso no seu Glassware para desativar ou limitar os serviços em segundo plano. Comece implementando uma BroadcastReceiver para detectar ACTION_ON_HEAD_STATE_CHANGE eventos.

O exemplo a seguir atrasa e desativa as atualizações de pontuação do jogo o usuário removeu o Glass da cabeça:

  1. Implementar um BroadcastReceiver para lidar com a mudança de estado.
  2. No seu serviço, implemente o onCreate() e registrar um receptor que detecte o evento ACTION_ON_HEAD_STATE_CHANGE.
  3. Na onDestroy() cancele o registro do receptor.

    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

Os seguintes sensores do Android são compatíveis com o Google Glass:

Os seguintes sensores do Android não são compatíveis:

.

Confira algumas dicas sobre o uso dos sensores no Google Glass:

  • O sistema de coordenadas do sensor do Google Glass é mostrado abaixo em relação à tela do dispositivo. Para mais informações, consulte sistema de coordenadas do sensor.

  • O acelerômetro, giroscópio e magnetômetro ficam localizados no conjunto óptico do dispositivo Glass, que os usuários giram para alinhar o dispositivo com a visão deles. Não é possível medir ângulo interno da cápsula óptica. Portanto, esteja ciente disso usando ângulos desses sensores para aplicativos como a orientação da bússola.

  • Para preservar a duração da bateria, ouça os sensores apenas quando precisar deles. Por exemplo, se o seu Glassware usa um Service para renderizar um LiveCard e você só precisa dos sensores quando o card ao vivo estiver visível, use o LiveCard exibe métodos de callback para iniciar e parar a detecção dos sensores.

  • Os callbacks de eventos do sensor são executados na linha de execução da interface. Portanto, processe os eventos e retorne como o mais rápido possível. Considere enviar eventos do sensor para uma fila e usar uma linha de execução em segundo plano para lidar com eles caso o processamento leve muito tempo.

  • 50 Hz costuma ser uma taxa de amostragem suficiente para rastrear o movimento da cabeça.

Para mais informações sobre como usar os sensores, consulte o Guia do desenvolvedor Android.