تمنحك حزمة تطوير البرامج (SDK) لنظام التشغيل Android إمكانية الوصول إلى المدخلات وأجهزة الاستشعار المختلفة المتاحة مع Glass EE2. تقدّم لك هذه الصفحة نظرة عامة حول الميزات المتاحة وتفاصيل التنفيذ ونصائح مفيدة.
إيماءات اللمس
يمكنك استخدام حزمة تطوير البرامج (SDK) لنظام التشغيل Android لتفعيل الوصول إلى البيانات الأولية من لوحة لمس Glass. ويتم تنفيذ ذلك من خلال أداة رصد الإيماءات التي ترصد تلقائيًا الإيماءات الشائعة على Glass، مثل النقر والتمرير والتنقّل.
يمكنك أيضًا استخدام أداة رصد الإيماءات هذه في تطبيقاتك لمراعاة النقر والتمرير السريع للأمام والتمرير سريعًا للخلف والتمرير سريعًا للأسفل. ويشبه هذا أجهزة Glass السابقة.
من الأفضل استخدام هذه الإيماءات بالطرق التالية:
- النقر: التأكيد أو الدخول.
- التمرير السريع للأمام والتمرير سريعًا للخلف: التنقُّل بين البطاقات والشاشات.
- التمرير السريع للأسفل: للرجوع أو الخروج.
وللحصول على تفاصيل التنفيذ، اطّلع على نموذج أداة رصد الإيماءات.
رصد الإيماءات باستخدام أداة رصد الإيماءات في Android
يتيح لك GestureDetector
Android اكتشاف إيماءات بسيطة ومعقدة، مثل الإيماءات التي تستخدم أصابعًا أو تستخدم عدّة أصابع.
رصد الإيماءات على مستوى النشاط
اكتشاف الإيماءات على مستوى النشاط فقط عندما لا يكون ذلك ممكنًا، بغض النظر عن الجزء الذي محل التركيز في واجهة المستخدم.
على سبيل المثال، إذا كنت تريد إظهار قائمة عندما ينقر المستخدم على لوحة اللمس،
بغض النظر عن العرض الذي يركّز عليه، يجب التعامل مع
MotionEvent
داخل النشاط.
في ما يلي مثال على رصد الإيماءات على مستوى النشاط الذي يستخدم
GestureDetector
وينفّذ
GestureDetector.OnGestureListener
لمعالجة الإيماءات التي تم التعرّف عليها، والتي
يتم معالجتها وترجمتها إلى ما يلي:
TAP
SWIPE_FORWARD
SWIPE_BACKWARD
SWIPE_UP
SWIPE_DOWN
Kotlin
class GlassGestureDetector(context: Context, private val onGestureListener: OnGestureListener) : GestureDetector.OnGestureListener { private val gestureDetector = GestureDetector(context, this) enum class Gesture { TAP, SWIPE_FORWARD, SWIPE_BACKWARD, SWIPE_UP, SWIPE_DOWN } interface OnGestureListener { fun onGesture(gesture: Gesture): Boolean } fun onTouchEvent(motionEvent: MotionEvent): Boolean { return gestureDetector.onTouchEvent(motionEvent) } override fun onDown(e: MotionEvent): Boolean { return false } override fun onShowPress(e: MotionEvent) {} override fun onSingleTapUp(e: MotionEvent): Boolean { return onGestureListener.onGesture(Gesture.TAP) } override fun onScroll( e1: MotionEvent, e2: MotionEvent, distanceX: Float, distanceY: Float ): Boolean { return false } override fun onLongPress(e: MotionEvent) {} /** * Swipe detection depends on the: * - movement tan value, * - movement distance, * - movement velocity. * * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement * angle is only between 60 and 120 degrees. * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends * on deltaX value sign. * * ______________________________________________________________ * | \ UP / | * | \ / | * | 60 120 | * | \ / | * | \ / | * | BACKWARD <------- 0 ------------ 180 ------> FORWARD | * | / \ | * | / \ | * | 60 120 | * | / \ | * | / DOWN \ | * -------------------------------------------------------------- */ override fun onFling( e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean { val deltaX = e2.x - e1.x val deltaY = e2.y - e1.y val tan = if (deltaX != 0f) abs(deltaY / deltaX).toDouble() else java.lang.Double.MAX_VALUE return if (tan > TAN_60_DEGREES) { if (abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) { false } else if (deltaY < 0) { onGestureListener.onGesture(Gesture.SWIPE_UP) } else { onGestureListener.onGesture(Gesture.SWIPE_DOWN) } } else { if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) { false } else if (deltaX < 0) { onGestureListener.onGesture(Gesture.SWIPE_FORWARD) } else { onGestureListener.onGesture(Gesture.SWIPE_BACKWARD) } } } companion object { private const val SWIPE_DISTANCE_THRESHOLD_PX = 100 private const val SWIPE_VELOCITY_THRESHOLD_PX = 100 private val TAN_60_DEGREES = tan(Math.toRadians(60.0)) } }
Java
public class GlassGestureDetector implements GestureDetector.OnGestureListener { enum Gesture { TAP, SWIPE_FORWARD, SWIPE_BACKWARD, SWIPE_UP, SWIPE_DOWN, } interface OnGestureListener { boolean onGesture(Gesture gesture); } private static final int SWIPE_DISTANCE_THRESHOLD_PX = 100; private static final int SWIPE_VELOCITY_THRESHOLD_PX = 100; private static final double TAN_60_DEGREES = Math.tan(Math.toRadians(60)); private GestureDetector gestureDetector; private OnGestureListener onGestureListener; public GlassGestureDetector(Context context, OnGestureListener onGestureListener) { gestureDetector = new GestureDetector(context, this); this.onGestureListener = onGestureListener; } public boolean onTouchEvent(MotionEvent motionEvent) { return gestureDetector.onTouchEvent(motionEvent); } @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return onGestureListener.onGesture(Gesture.TAP); } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } /** * Swipe detection depends on the: * - movement tan value, * - movement distance, * - movement velocity. * * To prevent unintentional SWIPE_DOWN and SWIPE_UP gestures, they are detected if movement * angle is only between 60 and 120 degrees. * Any other detected swipes, will be considered as SWIPE_FORWARD and SWIPE_BACKWARD, depends * on deltaX value sign. * * ______________________________________________________________ * | \ UP / | * | \ / | * | 60 120 | * | \ / | * | \ / | * | BACKWARD <------- 0 ------------ 180 ------> FORWARD | * | / \ | * | / \ | * | 60 120 | * | / \ | * | / DOWN \ | * -------------------------------------------------------------- */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { final float deltaX = e2.getX() - e1.getX(); final float deltaY = e2.getY() - e1.getY(); final double tan = deltaX != 0 ? Math.abs(deltaY/deltaX) : Double.MAX_VALUE; if (tan > TAN_60_DEGREES) { if (Math.abs(deltaY) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityY) < SWIPE_VELOCITY_THRESHOLD_PX) { return false; } else if (deltaY < 0) { return onGestureListener.onGesture(Gesture.SWIPE_UP); } else { return onGestureListener.onGesture(Gesture.SWIPE_DOWN); } } else { if (Math.abs(deltaX) < SWIPE_DISTANCE_THRESHOLD_PX || Math.abs(velocityX) < SWIPE_VELOCITY_THRESHOLD_PX) { return false; } else if (deltaX < 0) { return onGestureListener.onGesture(Gesture.SWIPE_FORWARD); } else { return onGestureListener.onGesture(Gesture.SWIPE_BACKWARD); } } } }
مثال للاستخدام
للاستفادة من رصد الإيماءات على مستوى النشاط، عليك إكمال المهام التالية:
- أضِف البيان التالي إلى ملف البيان داخل بيان التطبيق. يؤدي ذلك إلى تفعيل تطبيقك من تلقّي
MotionEvent
في النشاط:<application> <!-- Copy below declaration into your manifest file --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> </application>
- إلغاء طريقة النشاط
dispatchTouchEvent(motionEvent)
لنقل أحداث الحركة إلى أداة رصد الإيماءاتonTouchEvent(motionEvent)
. - نفِّذ
GlassGestureDetector.OnGestureListener
في نشاطك.
في ما يلي مثال على أداة رصد الإيماءات على مستوى النشاط:
Kotlin
class MainAcvitiy : AppCompatActivity(), GlassGestureDetector.OnGestureListener { private lateinit var glassGestureDetector: GlassGestureDetector override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) glassGestureDetector = GlassGestureDetector(this, this) } override fun onGesture(gesture: GlassGestureDetector.Gesture): Boolean { when (gesture) { TAP -> // Response for TAP gesture return true SWIPE_FORWARD -> // Response for SWIPE_FORWARD gesture return true SWIPE_BACKWARD -> // Response for SWIPE_BACKWARD gesture return true else -> return false } } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { return if (glassGestureDetector.onTouchEvent(ev)) { true } else super.dispatchTouchEvent(ev) } }
Java
public class MainActivity extends AppCompatActivity implements OnGestureListener { private GlassGestureDetector glassGestureDetector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); glassGestureDetector = new GlassGestureDetector(this, this); } @Override public boolean onGesture(Gesture gesture) { switch (gesture) { case TAP: // Response for TAP gesture return true; case SWIPE_FORWARD: // Response for SWIPE_FORWARD gesture return true; case SWIPE_BACKWARD: // Response for SWIPE_BACKWARD gesture return true; default: return false; } } @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (glassGestureDetector.onTouchEvent(ev)) { return true; } return super.dispatchTouchEvent(ev); } }
إدخال الصوت
Glass Enterprise Edition 2 هو جهاز عادي يستند إلى تقنية AOSP ويتوافق مع مصادر الصوت الأساسية.
تم تنفيذ معالجة الإشارات المتقدمة في مصادر الصوت التالية:
التعرّف على الصوت
يتيح Glass Enterprise Edition 2 استخدام طريقة تنفيذ أصلية لميزة "التعرّف على الكلام". تتوفّر هذه الميزة للغة الإنجليزية فقط.
في انتظار واجهة مستخدم التعرّف على الكلام حتى يتحدث المستخدمون ثم عرض النص الذي تم تحويله إلى نص بعد الانتهاء. لبدء النشاط، اتّبع الخطوات التالية:
- اطلب
startActivityForResult()
بقصدACTION_RECOGNIZE_SPEECH
. تتوفّر الميزات الإضافية التالية المستندة إلى النية بالشراء عند بدء النشاط: - يمكنك إلغاء استدعاء
onActivityResult()
لتلقي النص الذي تم تحويله إلى نص من نية الإضافةEXTRA_RESULTS
كما هو موضح في نموذج الرمز التالي. يتم استدعاء هذه المكالمة عند انتهاء المستخدم من التحدّث.
Kotlin
private const val SPEECH_REQUEST = 109 private fun displaySpeechRecognizer() { val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) startActivityForResult(intent, SPEECH_REQUEST) } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) { val results: List<String>? = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS) val spokenText = results?.get(0) // Do something with spokenText. } super.onActivityResult(requestCode, resultCode, data) }
Java
private static final int SPEECH_REQUEST = 109; private void displaySpeechRecognizer() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); startActivityForResult(intent, SPEECH_REQUEST); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SPEECH_REQUEST && resultCode == RESULT_OK) { List<String> results = data.getStringArrayListExtra( RecognizerIntent.EXTRA_RESULTS); String spokenText = results.get(0); // Do something with spokenText. } super.onActivityResult(requestCode, resultCode, data); }
للحصول على تفاصيل التنفيذ، يمكنك الاطّلاع على نموذج تطبيق التعرّف على الصوت.
انحياز الكلمات الرئيسية
يمكن استخدام ميزة "التعرّف على الكلام" على Glass لقائمة الكلمات الرئيسية. يعمل الانحياز على زيادة دقة التعرّف على الكلمات الرئيسية. لتفعيل انحياز الكلمات الرئيسية، استخدِم ما يلي:
Kotlin
val keywords = arrayOf("Example", "Biasing", "Keywords") val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) intent.putExtra("recognition-phrases", keywords) startActivityForResult(intent, SPEECH_REQUEST)
Java
final String[] keywords = {"Example", "Biasing", "Keywords"}; Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra("recognition-phrases", keywords); startActivityForResult(intent, SPEECH_REQUEST);
الطلبات الصوتية
تتيح الطلبات الصوتية للمستخدمين تنفيذ إجراءات من الأنشطة. ويمكنك إنشاء أوامر صوتية باستخدام واجهات برمجة تطبيقات قوائم Android العادية، ولكن يمكن للمستخدمين استدعاء عناصر القائمة باستخدام الطلبات الصوتية بدلاً من اللمس.
لتفعيل الأوامر الصوتية لنشاط معيَّن، اتبع الخطوات التالية:
- اتّصِل
getWindow().requestFeature(FEATURE_VOICE_COMMANDS)
في النشاط المطلوب لتفعيل الطلبات الصوتية. عند تفعيل هذه الميزة، يظهر رمز الميكروفون في أسفل يمين الشاشة كلما تلقّى هذا النشاط تركيزًا. - اطلب الإذن
RECORD_AUDIO
في تطبيقك. - يمكنك إلغاء
onCreatePanelMenu()
وتضخيم مورد القائمة. - يمكنك إلغاء
onContextItemSelected()
لمعالجة الطلبات الصوتية التي تم رصدها.
Kotlin
class VoiceCommandsActivity : AppCompatActivity() { companion object { const val FEATURE_VOICE_COMMANDS = 14 const val REQUEST_PERMISSION_CODE = 200 val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO) val TAG = VoiceCommandsActivity::class.java.simpleName } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.requestFeature(FEATURE_VOICE_COMMANDS) setContentView(R.layout.activity_voice_commands) // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions( this, PERMISSIONS, REQUEST_PERMISSION_CODE ) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { if (requestCode == REQUEST_PERMISSION_CODE) { for (result in grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Permission denied. Voice commands menu is disabled.") } } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults) } } override fun onCreatePanelMenu(featureId: Int, menu: Menu): Boolean { menuInflater.inflate(R.menu.voice_commands_menu, menu) return true } override fun onContextItemSelected(item: MenuItem): Boolean { return when (item.itemId) { // Handle selected menu item R.id.edit -> { // Handle edit action true } else -> super.onContextItemSelected(item) } } }
Java
public class VoiceCommandsActivity extends AppCompatActivity { private static final String TAG = VoiceCommandsActivity.class.getSimpleName(); private static final int FEATURE_VOICE_COMMANDS = 14; private static final int REQUEST_PERMISSION_CODE = 200; private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO}; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(FEATURE_VOICE_COMMANDS); setContentView(R.layout.activity_voice_commands); // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_PERMISSION_CODE) { for (int result : grantResults) { if (result != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "Permission denied. Voice commands menu is disabled."); } } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @Override public boolean onCreatePanelMenu(int featureId, @NonNull Menu menu) { getMenuInflater().inflate(R.menu.voice_commands_menu, menu); return true; } @Override public boolean onContextItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { // Handle selected menu item case R.id.edit: // Handle edit action return true; default: return super.onContextItemSelected(item); } } }
إليك مثال على قائمة الطعام التي استخدمها النشاط السابق:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/delete" android:icon="@drawable/ic_delete" android:title="@string/delete"/> <item android:id="@+id/edit" android:icon="@drawable/ic_edit" android:title="@string/edit"/> <item android:id="@+id/find" android:icon="@drawable/ic_search" android:title="@string/find"/> </menu>
اطّلِع على نموذج تطبيق تدوين الملاحظات للحصول على مثال كامل.
إعادة تحميل قائمة الطلبات الصوتية
يمكنك إعادة تحميل قائمة الطلبات الصوتية بشكل ديناميكي. لإجراء ذلك، عليك استبدال المورد menu
في الطريقة
onCreatePanelMenu()
، أو تعديل كائن القائمة في
الطريقة onPreparePanel()
. لتطبيق التغييرات، يمكنك استدعاء الطريقة
invalidateOptionsMenu()
.
Kotlin
private val options = mutableListOf<String>() fun onPreparePanel(featureId: Int, view: View?, menu: Menu): Boolean { if (featureId != FEATURE_VOICE_COMMANDS) { return super.onCreatePanelMenu(featureId, menu) } for (optionTitle in options) { menu.add(optionTitle) } return true } /** * Method showing example implementation of voice command list modification * * If you call [Activity.invalidateOptionsMenu] method, voice command list will be * reloaded (onCreatePanelMenu and onPreparePanel methods will be called). */ private fun modifyVoiceCommandList() { options.add("Delete") options.add("Play") options.add("Pause") invalidateOptionsMenu() }
Java
private final List<String> options = new ArrayList<>(); @Override public boolean onPreparePanel(int featureId, View view, Menu menu) { if (featureId != FEATURE_VOICE_COMMANDS) { return super.onCreatePanelMenu(featureId, menu); } for (String optionTitle : options) { menu.add(optionTitle); } return true; } /** * Method showing example implementation of voice command list modification * * If you call {@link Activity#invalidateOptionsMenu()} method, voice command list will be * reloaded (onCreatePanelMenu and onPreparePanel methods will be called). */ private void modifyVoiceCommandList() { options.add("Delete"); options.add("Play"); options.add("Pause"); invalidateOptionsMenu(); }
حل AppCompatActivity
لإعادة تحميل قائمة الطلبات الصوتية في نشاط يمتد إلى AppCompatActivity
، يمكنك استخدام طريقة
sendBroadcast()
مع الإجراء reload-voice-commands
المقصود:
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
تفعيل الأوامر الصوتية وإيقافها في وقت التشغيل
يمكنك تفعيل الطلبات الصوتية وإيقافها في وقت التشغيل. لإجراء ذلك، اعرض قيمة مناسبة من طريقة
onCreatePanelMenu()
كما يلي:
- اضبط القيمة على
true
لتفعيلها. - ويمكنك ضبط القيمة على
false
لإيقافها.
وضع تصحيح الأخطاء
لتفعيل وضع تصحيح الأخطاء للطلبات الصوتية، انقر على
getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
في النشاط المطلوب. يفعِّل وضع تصحيح الأخطاء الميزات التالية:
- يحتوي Logcat على السجلّ الذي يتضمّن العبارة التي تم التعرّف عليها لتصحيح الأخطاء.
- يتم عرض تراكب واجهة المستخدم عند اكتشاف أمر غير معروف، كما هو موضح:
Kotlin
class VoiceCommandsActivity : AppCompatActivity() { companion object { const val FEATURE_VOICE_COMMANDS = 14 const val FEATURE_DEBUG_VOICE_COMMANDS = 15 const val REQUEST_PERMISSION_CODE = 200 val PERMISSIONS = arrayOf(Manifest.permission.RECORD_AUDIO) val TAG = VoiceCommandsActivity::class.java.simpleName } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) window.requestFeature(FEATURE_VOICE_COMMANDS) window.requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) setContentView(R.layout.activity_voice_commands) // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions( this, PERMISSIONS, REQUEST_PERMISSION_CODE ) } . . . }
Java
public class VoiceCommandsActivity extends AppCompatActivity { private static final String TAG = VoiceCommandsActivity.class.getSimpleName(); private static final int FEATURE_VOICE_COMMANDS = 14; private static final int FEATURE_DEBUG_VOICE_COMMANDS = 15; private static final int REQUEST_PERMISSION_CODE = 200; private static final String[] PERMISSIONS = new String[]{Manifest.permission.RECORD_AUDIO}; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().requestFeature(FEATURE_VOICE_COMMANDS); getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS); setContentView(R.layout.activity_voice_commands); // Requesting permissions to enable voice commands menu ActivityCompat.requestPermissions(this, PERMISSIONS, REQUEST_PERMISSION_CODE); } . . . }
للحصول على تفاصيل التنفيذ، اطّلع على نموذج إعادة تحميل الطلبات الصوتية.
تحويل النص إلى كلام (TTS)
تحوّل وظيفة تحويل النص إلى كلام النص الرقمي إلى إخراج كلام مجمّع. للاطّلاع على مزيد من المعلومات، يُرجى الانتقال إلى TextToSpeech الذي يخص مستندات Android Developers.
تم تثبيت محرك تحويل النص إلى كلام من Google على جهاز Glass EE2. ويتم ضبطه كمحرّك تحويل النص إلى كلام التلقائي ويتم تشغيله بلا إنترنت.
يتم تضمين اللغات التالية مع محرّك تحويل النص إلى كلام من Google:
البنغالية الماندرين الصينية التشيكية الدانمركية الألمانية اليونانية الإنجليزية الإسبانية الإستونية الفنلندية الفرنسية الغوجاراتية الهندية |
المجرية الإندونيسية الإيطالية اليابانية الجاوية الأسترونية النمساوية الكنادية الكورية الملايلامية النرويجية الهولندية |
البولندية البرتغالية الروسية السلوفاكية السوندانية السويدية التاميلية التيلوغوية التايلاندية التركية الأوكرانية الفيتنامية |
الكاميرا
إنّ الإصدار 2 من Glass Enterprise مجهّز بكاميرا 8 ميغا بكسل بتركيز ثابت مع فتحة عدسة F/2.4 وبنسبة عرض إلى ارتفاع تبلغ 4:3 ونطاق قطري يبلغ 83 درجة (71 × 57 درجة في الاتجاه الأفقي). ننصح باستخدام واجهة برمجة التطبيقات الكاميرا X العادية أو الكاميرا 2.
للحصول على تفاصيل التنفيذ، يُرجى قراءة نموذج تطبيق الكاميرا.
زر الكاميرا
زر الكاميرا هو الزر الفعلي على مُفصَّلة جهاز Glass Enterprise Edition 2.
ويمكن التعامل معها تمامًا مثل
إجراء لوحة المفاتيح العادي
ويمكن التعرّف عليها من خلال رمز المفتاح
KeyEvent#KEYCODE_CAMERA
.
بدءًا من تحديث OPM1.200313.001 لنظام التشغيل، يتم إرسال النية بإجراء ات الإجراءات التالية من تطبيق "مشغّل التطبيقات":
MediaStore#ACTION_IMAGE_CAPTURE
على زر الكاميرا القصير، اضغط مع الاستمرار.MediaStore#ACTION_VIDEO_CAPTURE
على زر الكاميرا، اضغط مع الاستمرار.
أدوات الاستشعار
هناك مجموعة متنوعة من أجهزة الاستشعار المتاحة لمطوّري البرامج أثناء تطوير التطبيقات في Glass EE2.
تتوافق أجهزة الاستشعار المتوافقة مع Android العادية التالية مع Glass:
-
TYPE_ACCELEROMETER
-
TYPE_GRAVITY
-
TYPE_GYROSCOPE
-
TYPE_LIGHT
-
TYPE_LINEAR_ACCELERATION
-
TYPE_MAGNETIC_FIELD
-
TYPE_ORIENTATION
(متوقف) -
TYPE_ROTATION_VECTOR
لا تتوافق أجهزة استشعار Android التالية مع Glass:
يتم عرض نظام إحداثيات جهاز استشعار الزجاج في الرسم التوضيحي التالي. هذه النسبة مقارنةً بشاشة Glass. لمزيد من المعلومات، يمكنك الاطّلاع على نظام إحداثيات أجهزة الاستشعار.
يتوفّر مقياس التسارع والجيروسكوب ومقياس المغناطيسية في مجموعة المرئيات من جهاز Glass الذي يجري المستخدمون تدويرًا لمحاذاة الجهاز مع رؤيتهم. لا يمكنك قياس زاوية لوحة المواد البصرية مباشرةً، لذا يُرجى الانتباه إليها عند استخدام زوايا من أجهزة الاستشعار هذه للتطبيقات، مثل عنوان البوصلة.
للحفاظ على عمر البطارية، لا تستمع إلى أجهزة الاستشعار إلا عند الحاجة إليها. يمكنك الاستناد إلى احتياجات التطبيق ومراحل نشاطه عندما تقرّر موعد بدء تشغيل أجهزة الاستشعار والتوقّف عنها.
يتم تنفيذ استدعاءات أحداث جهاز الاستشعار على سلسلة واجهة المستخدم، لذا يمكنك معالجة الأحداث والمرتجعات في أسرع وقت ممكن. إذا استغرقت عملية المعالجة وقتًا طويلاً جدًا، أرسِل أحداث أداة الاستشعار إلى قائمة الانتظار واستخدِم سلسلة محادثات في الخلفية للتعامل معها.
غالبًا ما يمثل معدل 50 هرتز معدلًا كافيًا لأخذ العينات لتتبع حركة الرأس.
للاطّلاع على مزيد من المعلومات حول طريقة استخدام أجهزة الاستشعار، يُرجى الاطّلاع على دليل مطوّري برامج Android.
خدمات الموقع الجغرافي
إن جهاز Glass Enterprise Edition 2 غير مجهّز بوحدة GPS ولا يقدم الموقع الجغرافي للمستخدم. وتم أيضًا تنفيذ خدمات الموقع الجغرافي، وهي ضرورية لعرض قائمة بشبكات Wi-Fi المجاورة والأجهزة التي تتضمّن بلوتوث.
إذا كان تطبيقك يمتلك امتيازات مالك الجهاز، يمكنك استخدامه لتغيير قيمة الإعداد الآمن المقابل آليًا:
Kotlin
val devicePolicyManager = context .getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) { val componentName = ComponentName(context, MyDeviceAdmin::class.java) devicePolicyManager.setSecureSetting( componentName, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_SENSORS_ONLY.toString() ) }
Java
final DevicePolicyManager devicePolicyManager = (DevicePolicyManager) context .getSystemService(Context.DEVICE_POLICY_SERVICE); if (devicePolicyManager.isDeviceOwnerApp(context.getPackageName())) { final ComponentName componentName = new ComponentName(context, MyDeviceAdmin.class); devicePolicyManager.setSecureSetting(componentName, Settings.Secure.LOCATION_MODE, String.valueOf(Settings.Secure.LOCATION_MODE_SENSORS_ONLY)); }
إذا كنت تستخدم حلًّا لإدارة الأجهزة الجوّالة من جهة خارجية، يجب أن يتمكّن حل إدارة الأجهزة الجوّالة من تغيير هذه الإعدادات نيابةً عنك.