المواقع وأجهزة الاستشعار

يمكنك الوصول إلى بيانات الموقع الجغرافي وجهاز الاستشعار باستخدام واجهات برمجة التطبيقات العادية لنظام التشغيل Android الأساسي.

الموقع الجغرافي

يتضمن الموقع على Glass استخدام واجهات برمجة تطبيقات نظام Android الأساسي القياسية للحصول على بيانات الموقع من موردي المواقع المتوفرين.

ستستخدم فئات Android SDK التالية للحصول على بيانات الموقع:

  • LocationManager – يوفر هذا الإعداد إمكانية الوصول إلى خدمة نظام الموقع الجغرافي لنظام التشغيل Android التي تعالج الاتصال بـ LocationProvider.

  • LocationProvider – تقدم بيانات الموقع بناءً على بعض المعايير. يوفر تطبيق Glass مزودي خدمة "بعيد" خاصين يتيحون لك الحصول على بيانات الموقع من جهاز مقترن تم تثبيت تطبيق MyGlass المصاحب عليه.

  • Criteria – تتيح لك هذه الميزة إنشاء مجموعة من المعايير التي تختار أفضل LocationProvider بناءً على المعايير التي تحدّدها.

نظرة عامة

للحصول على بيانات الموقع الجغرافي، ستحتاج إلى استخدام فئة LocationManager للحصول على بيانات من موفّر موقع جغرافي واحد أو أكثر.

تسترد التطبيقات على هاتف أو جهاز لوحي يعمل بنظام التشغيل Android بيانات الموقع الجغرافي من نظام تحديد المواقع العالمي (GPS) ومقدمي خدمات الشبكة على الجهاز. ومع ذلك، في مجموعة Glass، تكون مجموعة موفري المواقع الجغرافية المتاحة ديناميكية، وقد تتضمن مقدمي خدمة الموقع عن بُعد الذين يقدمون بيانات الموقع من مصدر آخر، مثل جهاز تم إقرانه عبر بلوتوث مع تثبيت التطبيق المصاحب لنظاراتي. للتعامل مع مقدمي الخدمة الإضافيين هؤلاء، استمع إلى تحديثات الموقع من مقدمي الخدمة بدلاً من مزود واحد.

لطلب البيانات من جميع موفري المواقع المتاحة:

  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 لتعطيل خدمات الخلفية أو تقييدها. ابدأ بتنفيذ 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، والتي يتم تدويرها لمحاذاة الجهاز مع العين. لا يمكنك قياس زاوية لوحة اللوحات البصرية مباشرة، لذا يجب الانتباه لذلك عند استخدام الزوايا من أجهزة الاستشعار هذه لتطبيقات مثل عنوان البوصلة.

  • للحفاظ على عمر البطارية، استمع إلى أجهزة الاستشعار عند الحاجة إليها فقط. على سبيل المثال، إذا كانت Glassware تستخدم Service لعرض LiveCard وكنت لا تحتاج إلى أجهزة الاستشعار إلا عندما تكون البطاقة المباشرة مرئية، استخدِم طرق معاودة الاتصال على سطح LiveCard لبدء الاستماع إلى أجهزة الاستشعار وإيقافها.

  • تعمل استدعاءات أحداث أداة الاستشعار على سلسلة واجهة المستخدم، لذا يمكنك معالجة الأحداث والرجوع إليها في أسرع وقت ممكن. يمكنك إرسال أحداث المستشعر إلى قائمة الانتظار واستخدام سلسلة محادثات للتعامل معها إذا استغرقت المعالجة وقتًا طويلاً.

  • غالبًا ما يكون معدل العينات 50 هرتز كافيًا لتتبع حركة الرأس.

لمزيد من المعلومات حول كيفية استخدام أجهزة الاستشعار، يمكنك الاطّلاع على دليل مطوّري برامج Android.