您可以使用标准的 Android 平台 API 访问位置信息和传感器数据。
位置
Glass on Location 涉及使用标准 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
intent 的接收器。 在
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
Surface 回调方法来开始和停止监听传感器。传感器事件回调在界面线程上运行,因此请处理事件并尽快返回。请考虑将传感器事件推送到队列中,并在处理时间过长时使用后台线程来处理这些事件。
50 Hz 通常足以用来跟踪头部移动。
如需详细了解如何使用传感器,请参阅 Android 开发者指南。