位置情報とセンサー

位置情報とセンサーデータにアクセスするには、標準の Android プラットフォーム API を使用します。

場所

Glass で位置情報を使用するには、標準の Android プラットフォーム API を使用して、利用可能な位置情報プロバイダから位置情報データを取得する必要があります。

位置情報データを取得するには、次の Android SDK クラスを使用します。

  • LocationManager - LocationProvider との通信を処理する Android 位置情報システム サービスへのアクセスを提供します。

  • LocationProvider - いくつかの基準に基づいて位置情報データを提供します。Glass には特別な「リモート」プロバイダが用意されており、MyGlass コンパニオン アプリがインストールされたペア設定済みのデバイスから位置情報を取得できます。

  • Criteria - 設定した条件に基づいて最適な LocationProvider を選択する一連の条件を作成できます。

概要

位置情報データを取得するには、LocationManager クラスを使用して、1 つ以上の位置情報プロバイダからデータを取得する必要があります。

Android スマートフォンやタブレットのアプリは、デバイスのローカル GPS やネットワーク位置情報プロバイダから位置情報データを取得します。ただし、Glass では、利用可能な位置情報プロバイダのセットは動的であり、別のソース(MyGlass コンパニオン アプリがインストールされた Bluetooth ペア設定デバイスなど)から位置情報を提供するリモートの位置情報プロバイダが含まれる場合があります。これらの追加プロバイダを処理するには、1 つのプロバイダではなく、複数のプロバイダからの位置情報の更新をリッスンします。

利用可能なすべての位置情報プロバイダからデータをリクエストするには:

  1. ロケーションの要件を指定して Criteria オブジェクトを作成します。
  2. getProviders() を呼び出して、条件を満たす有効なプロバイダのリストを取得します。
  3. プロバイダのリストを反復処理し、すべてのプロバイダに更新をリクエストします。これにより、リモート プロバイダがあればその最新情報を受信できますが、Glass のローカル プロバイダ(ワイヤレス ネットワーク プロバイダなど)からも更新を受け取ることができます。
  4. 各アップデートで提供される精度とタイミングの情報を使用して、アップデートが十分であるのか、それとも別のアップデートを待つべきなのかを判断します。

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

センサー

Glass

Glass には、デバイスがユーザーの頭に装着しているかどうかを検出する専用のセンサーがあります。有効にすると、デバイスを使用していないときにバッテリーを節約できます。この機能は、Glassware でバックグラウンド サービスの無効化やスロットリングに使用できます。まず、BroadcastReceiver を実装して ACTION_ON_HEAD_STATE_CHANGE イベントを検出します。

次の例では、ユーザーが頭から Glass を削除したかどうかに応じて、ゲームスコアの更新を遅らせ、無効にします。

  1. 状態の変化を処理する BroadcastReceiver を実装します。
  2. サービスに onCreate() メソッドを実装し、ACTION_ON_HEAD_STATE_CHANGE インテントをリッスンするレシーバを登録します。
  3. onDestroy() メソッドで、レシーバの登録を解除します。

    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

Glass では、次の Android センサーがサポートされています。

次の Android センサーはサポートされていません。

Glass でセンサーを使用する際は、次のヒントを参考にしてください。

  • Glass センサー座標系は、Glass ディスプレイに対して相対的に表示されています。 詳しくは、センサー座標系をご覧ください。

  • 加速度計、ジャイロスコープ、磁力計は Glass デバイスの光学ユニット上に配置され、ユーザーが視線に合わせてデバイスを回転させます。光学ユニットの角度を直接測定することはできません。コンパス方位などのアプリでこれらのセンサーの角度を使用する場合は、この点に注意してください。

  • バッテリーを長持ちさせるため、必要なときだけセンサーを聞きます。たとえば、Glassware で Service を使用して LiveCard をレンダリングし、ライブカードが表示されているときにのみセンサーが必要な場合は、LiveCard サーフェス コールバック メソッドを使用してセンサーのリッスンを開始および停止します。

  • センサー イベントのコールバックは UI スレッドで実行されるため、イベントを処理して可能な限り早く返されます。処理に時間がかかりすぎる場合は、センサー イベントをキューに push し、バックグラウンド スレッドを使用して処理することを検討してください。

  • 50 Hz は、頭の動きのトラッキングを行うのに十分なサンプリング レートであることが多いです。

センサーの使い方について詳しくは、Android デベロッパー ガイドをご覧ください。