Android SDK ช่วยให้คุณเข้าถึงอินพุตและเซ็นเซอร์ต่างๆ ที่มีใน Glass EE2 ได้ หน้านี้จะแสดงภาพรวมของฟีเจอร์ที่มี รายละเอียดการติดตั้งใช้งาน และเคล็ดลับที่เป็นประโยชน์
ท่าทางแตะสัมผัส
คุณสามารถใช้ Android SDK เพื่อเปิดใช้การเข้าถึงข้อมูลดิบจากทัชแพดของ Glass ได้ ซึ่งทำได้ผ่านเครื่องตรวจจับท่าทางสัมผัสที่ตรวจจับท่าทางสัมผัสทั่วไปบน Glass โดยอัตโนมัติ เช่น แตะ ปัด และเลื่อน
คุณยังใช้เครื่องตรวจจับท่าทางสัมผัสนี้ในแอปเพื่อรองรับการแตะ ปัดไปข้างหน้า ปัดไปข้างหลัง และปัดลงได้ด้วย ซึ่งคล้ายกับอุปกรณ์ Glass รุ่นก่อนๆ
คุณควรใช้ท่าทางสัมผัสเหล่านี้ในลักษณะต่อไปนี้
- แตะ: ยืนยันหรือป้อน
- ปัดไปข้างหน้า ปัดไปข้างหลัง: เลื่อนดูการ์ดและหน้าจอ
- ปัดลง: กลับหรือออก
ดูรายละเอียดการใช้งานได้ที่ตัวอย่างเครื่องตรวจจับท่าทางสัมผัส
ตรวจหาท่าทางสัมผัสด้วยเครื่องตรวจจับท่าทางสัมผัสของ Android
GestureDetector ของ Android
ช่วยให้คุณตรวจจับท่าทางสัมผัสที่เรียบง่ายและซับซ้อนได้ เช่น ท่าทางสัมผัสที่ใช้นิ้วหลายนิ้วหรือการเลื่อน
ตรวจจับท่าทางสัมผัสระดับกิจกรรม
ตรวจจับท่าทางสัมผัสที่ระดับกิจกรรมเฉพาะเมื่อไม่สำคัญว่าส่วนใดของ UI จะมีโฟกัส
ตัวอย่างเช่น หากต้องการแสดงเมนูเมื่อผู้ใช้แตะทัชแพด
ไม่ว่ามุมมองใดจะโฟกัสอยู่ ให้จัดการ
MotionEvent
ภายในกิจกรรม
ต่อไปนี้เป็นตัวอย่างการตรวจจับท่าทางสัมผัสระดับกิจกรรมที่ใช้
GestureDetector และใช้
GestureDetector.OnGestureListener เพื่อประมวลผลท่าทางสัมผัสที่รับรู้ ซึ่งจะ
ได้รับการจัดการและแปลเป็นรายการต่อไปนี้
TAPSWIPE_FORWARDSWIPE_BACKWARDSWIPE_UPSWIPE_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); } } } }
ตัวอย่างการใช้งาน
หากต้องการใช้การตรวจจับท่าทางสัมผัสระดับกิจกรรม คุณต้องทําภารกิจต่อไปนี้ให้เสร็จสมบูรณ์
- เพิ่มการประกาศต่อไปนี้ลงในไฟล์ Manifest ภายในประกาศของแอปพลิเคชัน ซึ่งจะช่วยให้แอปได้รับ
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 รองรับการติดตั้งใช้งานการจดจำเสียงพูดโดยตรง ฟีเจอร์นี้รองรับเฉพาะภาษาอังกฤษ
UI การจดจำเสียงพูดจะรอให้ผู้ใช้พูด แล้วแสดงข้อความที่ถอดเสียงหลังจากที่ผู้ใช้พูดจบ หากต้องการเริ่มกิจกรรม ให้ทำตามขั้นตอนต่อไปนี้
- เรียกใช้
startActivityForResult()ด้วยความตั้งใจACTION_RECOGNIZE_SPEECHระบบรองรับส่วนเสริมของ Intent ต่อไปนี้เมื่อคุณเริ่มกิจกรรม - ลบล้าง
onActivityResult()การเรียกกลับเพื่อรับข้อความที่ถอดเสียงจากEXTRA_RESULTSIntent Extra ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้ ระบบจะเรียกใช้ Callback นี้เมื่อผู้ใช้พูดจบ
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 Menu API มาตรฐาน แต่ผู้ใช้จะเรียกใช้รายการเมนูด้วยคำสั่งเสียง แทนการแตะได้
หากต้องการเปิดใช้คำสั่งเสียงสำหรับกิจกรรมหนึ่งๆ ให้ทำตามขั้นตอนต่อไปนี้
- โทร
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 การดำเนินการของ Intent ดังนี้
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
เปิดและปิดใช้คำสั่งเสียงในรันไทม์
คุณเปิดและปิดใช้คำสั่งเสียงได้ในรันไทม์ โดยให้ส่งคืนค่าที่เหมาะสมจากเมธอด
onCreatePanelMenu()
ดังนี้
- ตั้งค่าเป็น
trueเพื่อเปิดใช้ - ตั้งค่าเป็น
falseเพื่อปิดใช้
โหมดแก้ไขข้อบกพร่อง
หากต้องการเปิดใช้โหมดแก้ไขข้อบกพร่องสำหรับคำสั่งเสียง ให้เรียกใช้
getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
ในกิจกรรมที่ต้องการ โหมดแก้ไขข้อบกพร่องจะเปิดใช้งานฟีเจอร์ต่อไปนี้
- Logcat มีบันทึกพร้อมวลีที่ระบบจดจำได้สำหรับการแก้ไขข้อบกพร่อง
- การซ้อนทับ UI จะแสดงขึ้นเมื่อตรวจพบคำสั่งที่ไม่รู้จัก ดังที่แสดง
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)
ฟังก์ชันการอ่านออกเสียงข้อความจะแปลงข้อความดิจิทัลเป็นเอาต์พุตเสียงพูดที่สังเคราะห์ขึ้น ดูข้อมูลเพิ่มเติมได้ที่ เอกสารประกอบสำหรับนักพัฒนาแอป Android เกี่ยวกับ TextToSpeech
Glass EE2 มีเครื่องมือการอ่านออกเสียงข้อความของ Google ติดตั้งไว้ โดยจะตั้งเป็นเครื่องมือ TTS เริ่มต้นและทำงานแบบออฟไลน์
เครื่องมืออ่านออกเสียงข้อความของ Google มาพร้อมกับภาษาต่อไปนี้
|
เบงกาลี จีนกลาง เช็ก เดนมาร์ก เยอรมัน กรีก อังกฤษ สเปน เอสโตเนีย ฟินแลนด์ ฝรั่งเศส คุชราต ฮินดี |
ฮังการี อินโดนีเซีย อิตาลี ญี่ปุ่น ชวา ออสโตรนีเซียน ออสโตรเอเชียติก กันนาดา เกาหลี มาลายาลัม นอร์เวย์ ดัตช์ |
โปแลนด์ โปรตุเกส รัสเซีย สโลวัก ซุนดา สวีเดน ทมิฬ เตลูกู ไทย ตุรกี ยูเครน เวียดนาม |
กล้อง
Glass Enterprise Edition 2 มาพร้อมกล้อง 8 ล้านพิกเซลที่มีโฟกัสคงที่ รูรับแสง f/2.4 สัดส่วนภาพของเซ็นเซอร์ 4:3 และขอบเขตการมองเห็นแนวทแยง 83° (71° x 57° ในแนวนอน) เราขอแนะนำให้คุณใช้ API CameraX หรือ Camera2 มาตรฐาน
ดูรายละเอียดการนำไปใช้งานได้ที่แอปกล้องตัวอย่าง
ปุ่มกล้องถ่ายรูป
ปุ่มกล้องคือปุ่มจริงที่บานพับของอุปกรณ์ Glass Enterprise Edition 2
คุณจัดการได้เช่นเดียวกับการดำเนินการของแป้นพิมพ์มาตรฐาน
และระบุได้ด้วยรหัสคีย์
KeyEvent#KEYCODE_CAMERA
ตั้งแต่การอัปเดต OS OPM1.200313.001 เป็นต้นไป ระบบจะส่ง Intent ที่มี การดำเนินการต่อไปนี้จากแอปพลิเคชัน Launcher
MediaStore#ACTION_IMAGE_CAPTUREเมื่อกดปุ่มกล้องสั้นๆMediaStore#ACTION_VIDEO_CAPTUREกดปุ่มกล้องค้างไว้
เซ็นเซอร์
นักพัฒนาแอปมีเซ็นเซอร์หลากหลายประเภทให้ใช้งานขณะพัฒนาแอปพลิเคชันใน Glass EE2
Glass รองรับเซ็นเซอร์ Android มาตรฐานต่อไปนี้
-
TYPE_ACCELEROMETER -
TYPE_GRAVITY -
TYPE_GYROSCOPE -
TYPE_LIGHT -
TYPE_LINEAR_ACCELERATION -
TYPE_MAGNETIC_FIELD -
TYPE_ORIENTATION(เลิกใช้งานแล้ว) -
TYPE_ROTATION_VECTOR
Glass ไม่รองรับเซ็นเซอร์ Android ต่อไปนี้
ระบบพิกัดเซ็นเซอร์ของ Glass แสดงอยู่ในภาพต่อไปนี้ โดยจะสัมพันธ์กับจอแสดงผลของ Glass ดูข้อมูลเพิ่มเติมได้ที่ ระบบพิกัดของเซ็นเซอร์
มาตรความเร่ง ไจโรสโคป และแมกนีโตมิเตอร์จะอยู่ที่พ็อดเลนส์ของอุปกรณ์ Glass ซึ่งผู้ใช้จะหมุนเพื่อจัดแนวอุปกรณ์ให้ตรงกับสายตา คุณไม่สามารถวัดมุมของพ็อดเลนส์ได้โดยตรง ดังนั้นโปรดทราบถึงข้อจำกัดนี้เมื่อใช้มุมจากเซ็นเซอร์เหล่านี้สำหรับแอปพลิเคชัน เช่น ทิศทางเข็มทิศ
ฟังเซ็นเซอร์เฉพาะเมื่อจำเป็นเท่านั้นเพื่อช่วยยืดอายุการใช้งานแบตเตอรี่ พิจารณาความต้องการและวงจรของแอปเมื่อตัดสินใจว่าจะเริ่มและหยุดฟังเซ็นเซอร์ เมื่อใด
Callback ของเหตุการณ์เซ็นเซอร์จะทำงานใน UI เธรด ดังนั้นให้ประมวลผลเหตุการณ์และส่งคืนค่าให้เร็วที่สุด เท่าที่จะทำได้ หากการประมวลผลใช้เวลานานเกินไป ให้ส่งเหตุการณ์เซ็นเซอร์ไปยังคิวและใช้เธรดเบื้องหลัง เพื่อจัดการเหตุการณ์เหล่านั้น
โดยทั่วไปแล้ว 50 Hz เป็นอัตราการสุ่มตัวอย่างที่เพียงพอต่อการติดตามการเคลื่อนไหวของศีรษะ
ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีใช้เซ็นเซอร์ได้ที่ คู่มือนักพัฒนาแอป 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)); }
หากคุณใช้โซลูชัน MDM ของบุคคลที่สาม โซลูชัน MDM ต้องเปลี่ยนการตั้งค่าเหล่านี้ให้คุณได้