您可以使用標準 Android 平台 API 存取位置和感應器資料。
位置
Glass 上的位置功能是使用標準 Android 平台 API 從可用的定位服務供應商取得位置資料。
您將使用以下 Android SDK 類別取得位置資料:
LocationManager
- 提供處理與LocationProvider
通訊的 Android 定位系統服務的存取權。LocationProvider
- 根據部分條件提供位置資料。Glass 提供特殊的「遠端」提供者,可讓您從已安裝 MyGlass 隨附應用程式的配對裝置上取得位置資料。Criteria
– 您可以建立一組條件,根據您設定的條件選取最佳LocationProvider
。
總覽
如要取得位置資料,您必須使用 LocationManager
類別取得一或多個位置提供者的資料。
Android 手機或平板電腦上的應用程式會從裝置上的本機 GPS 和網路位置供應商擷取位置資料。但是在 Glass 上,可用的位置集是動態的,其中可能包含「遠端」定位提供者,可提供其他來源的位置資料,例如已安裝 MyGlass 隨附應用程式的藍牙配對裝置。如要處理這些額外供應商,請監聽多個供應商 (而非單一供應商) 的位置更新。
如何要求所有可用定位服務供應商的資料:
- 建立包含位置資訊要求的
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 具有專用的感應器,可偵測裝置是否位於使用者頭部。啟用後,這項設定可在裝置處於閒置狀態時節省電力。您可以在 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 裝置的光學 Pod 上,使用者會旋轉,使裝置與視線方向對齊。您無法直接測量光學 Pod 的角度,因此在為應用程式 (例如指南針方向) 使用這類感應器的角度時,請注意這一點。
為了延長電池續航力,建議你只在有需要時監聽感應器。舉例來說,如果您的 Glassware 使用
Service
轉譯LiveCard
,且只有在顯示即時資訊卡時,才需要使用感應器,請使用LiveCard
顯示回呼方法,開始和停止監聽感應器。感應器事件回呼會在 UI 執行緒上執行,因此請處理事件並盡快傳回。如果處理處理時間過長,請考慮將感應器事件推送到佇列,並使用背景執行緒來處理。
50 Hz 通常足以提供追蹤頭部動作的取樣率。
如要進一步瞭解如何使用感應器,請參閱 Android 開發人員指南。