位置情報とセンサーデータにアクセスするには、標準の Android プラットフォーム API を使用します。
場所
Glass で位置情報を使用するには、標準の Android プラットフォーム API を使用して、利用可能な位置情報プロバイダから位置情報データを取得する必要があります。
位置情報データを取得するには、次の Android SDK クラスを使用します。
LocationManager
-LocationProvider
との通信を処理する Android 位置情報システム サービスへのアクセスを提供します。LocationProvider
- いくつかの基準に基づいて位置情報データを提供します。Glass には特別な「リモート」プロバイダが用意されており、MyGlass コンパニオン アプリがインストールされたペア設定済みのデバイスから位置情報を取得できます。Criteria
- 設定した条件に基づいて最適なLocationProvider
を選択する一連の条件を作成できます。
概要
位置情報データを取得するには、LocationManager
クラスを使用して、1 つ以上の位置情報プロバイダからデータを取得する必要があります。
Android スマートフォンやタブレットのアプリは、デバイスのローカル GPS やネットワーク位置情報プロバイダから位置情報データを取得します。ただし、Glass では、利用可能な位置情報プロバイダのセットは動的であり、別のソース(MyGlass コンパニオン アプリがインストールされた Bluetooth ペア設定デバイスなど)から位置情報を提供するリモートの位置情報プロバイダが含まれる場合があります。これらの追加プロバイダを処理するには、1 つのプロバイダではなく、複数のプロバイダからの位置情報の更新をリッスンします。
利用可能なすべての位置情報プロバイダからデータをリクエストするには:
- ロケーションの要件を指定して
Criteria
オブジェクトを作成します。 getProviders()
を呼び出して、条件を満たす有効なプロバイダのリストを取得します。- プロバイダのリストを反復処理し、すべてのプロバイダに更新をリクエストします。これにより、リモート プロバイダがあればその最新情報を受信できますが、Glass のローカル プロバイダ(ワイヤレス ネットワーク プロバイダなど)からも更新を受け取ることができます。
各アップデートで提供される精度とタイミングの情報を使用して、アップデートが十分であるのか、それとも別のアップデートを待つべきなのかを判断します。
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 を削除したかどうかに応じて、ゲームスコアの更新を遅らせ、無効にします。
- 状態の変化を処理する
BroadcastReceiver
を実装します。 - サービスに
onCreate()
メソッドを実装し、ACTION_ON_HEAD_STATE_CHANGE
インテントをリッスンするレシーバを登録します。 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 センサーがサポートされています。
TYPE_ACCELEROMETER
TYPE_GRAVITY
TYPE_GYROSCOPE
TYPE_LIGHT
TYPE_LINEAR_ACCELERATION
TYPE_MAGNETIC_FIELD
TYPE_ORIENTATION
(非推奨)TYPE_ROTATION_VECTOR
次の Android センサーはサポートされていません。
Glass でセンサーを使用する際は、次のヒントを参考にしてください。
- Glass センサー座標系は、Glass ディスプレイに対して相対的に表示されています。 詳しくは、センサー座標系をご覧ください。
加速度計、ジャイロスコープ、磁力計は Glass デバイスの光学ユニット上に配置され、ユーザーが視線に合わせてデバイスを回転させます。光学ユニットの角度を直接測定することはできません。コンパス方位などのアプリでこれらのセンサーの角度を使用する場合は、この点に注意してください。
バッテリーを長持ちさせるため、必要なときだけセンサーを聞きます。たとえば、Glassware で
Service
を使用してLiveCard
をレンダリングし、ライブカードが表示されているときにのみセンサーが必要な場合は、LiveCard
サーフェス コールバック メソッドを使用してセンサーのリッスンを開始および停止します。センサー イベントのコールバックは UI スレッドで実行されるため、イベントを処理して可能な限り早く返されます。処理に時間がかかりすぎる場合は、センサー イベントをキューに push し、バックグラウンド スレッドを使用して処理することを検討してください。
50 Hz は、頭の動きのトラッキングを行うのに十分なサンプリング レートであることが多いです。
センサーの使い方について詳しくは、Android デベロッパー ガイドをご覧ください。