מיקומים וחיישנים

הגישה לנתוני המיקום והחיישנים מתבצעת באמצעות מכשיר Android הרגיל ממשקי API של הפלטפורמה.

מיקום

המיקום ב-Glass כולל שימוש במכשיר Android הרגיל ממשקי API של הפלטפורמה לקבלת נתוני מיקום זמינים ספקי מיקום.

כדי לקבל נתוני מיקום, תשתמשו במחלקות הבאות של Android SDK:

  • LocationManager – מספק גישה לשירות מערכת המיקום של Android שמטפל בתקשורת עם LocationProvider

  • LocationProvider – מספקת נתוני מיקום על סמך קריטריונים מסוימים. Glass מספקים "שלט רחוק" מיוחד ספקים שמאפשרים לקבל נתוני מיקום ממכשיר מותאם עם MyGlass אפליקציה נלווית מותקנת.

  • Criteria – מאפשרת לכם ליצור קבוצה של קריטריונים בוחר את LocationProvider הטוב ביותר על סמך הקריטריונים שאתם מגדירים.

סקירה כללית

כדי לקבל נתוני מיקום, צריך להשתמש LocationManager כדי לקבל נתונים מספק מיקום אחד או יותר.

אפליקציות בטלפון או בטאבלט Android מאחזרות נתוני מיקום ספקי מיקום של רשתות ו-GPS במכשיר. ב-Glass, הקבוצה של ספקי המיקום הזמינים היא דינמית ויכולה לכלול מרחוק ספקי מיקום שמספקים נתוני מיקום ממקור אחר, כמו מכשיר המותאם Bluetooth עם האפליקציה הנלווית של MyGlass. כדי לטפל ב: ספקים נוספים אלה, מקשיבים לעדכוני מיקום ספקים ולא ספק אחד.

כדי לבקש נתונים מכל ספקי המיקום הזמינים:

  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 יש חיישן מיוחד כדי לזהות אם המכשיר נמצא משתמשים לראש. כשההגדרה מופעלת, היא עוזרת לחסוך בצריכת הסוללה כשהמכשיר לא בשימוש. ניתן להשתמש בתכונה זו ב-Glassware כדי להשבית או שירותי רקע של ויסות נתונים (throttle). קודם כל, צריך להטמיע BroadcastReceiver לזהות ACTION_ON_HEAD_STATE_CHANGE אירועים.

בדוגמה הבאה לעיכובים ולהשבתה של עדכוני תוצאות המשחקים, המשתמש הסיר את Glass מהראש שלו:

  1. ליישם BroadcastReceiver לטפל בשינוי המצב.
  2. בשירות שלכם, מטמיעים את onCreate() ורושמים מקלט שמאזין Intent 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

חיישני Android הבאים נתמכים ב-Glass:

אין תמיכה בחיישני Android הבאים:

הנה כמה טיפים לשימוש בחיישנים ב-Glass:

  • מד התאוצה, הג'ירוסקופ והמגנטומטר נמצאים בשקע האופטיקה של מכשיר ה-Glass, שמשתמשים מסובבים כדי ליישר את המכשיר ביחס למראה שלהם. אי אפשר למדוד את הזווית הישירה של רצף האופטיקה, לכן חשוב לשים לב לכך באמצעות זוויות מהחיישנים האלה לאפליקציות כמו כיוון מצפן.

  • כדי להאריך את חיי הסוללה, חשוב להאזין לחיישנים רק כשיש לך צורך בהם. לדוגמה, אם משתמש ב-Service כדי לעבד LiveCard וצריך את החיישנים רק כשהכרטיס הפעיל גלוי, משתמשים LiveCard הצגת שיטות קריאה חוזרת (callback) כדי להתחיל ולהפסיק להאזין לחיישנים.

  • קריאות חוזרות (callbacks) של אירועים מהחיישן פועלות בשרשור של ממשק המשתמש, לכן המערכת מעבדת את האירועים וחוזרת בתור במהירות האפשרית. כדאי להעביר אירועי חיישנים לתור ולהשתמש בשרשור ברקע לטפל בהן אם העיבוד נמשך יותר מדי זמן.

  • תדירות דגימה של 50 Hz לעיתים קרובות מספיקה למעקב אחרי תנועת הראש.

לקבלת מידע נוסף על אופן השימוש בחיישנים, אפשר לעיין במאמר המדריך למפתחי Android.