SDK Android cho phép bạn truy cập vào các đầu vào và cảm biến khác nhau có sẵn bằng Glass EE2. Trang này cung cấp cho bạn thông tin tổng quan về các tính năng hiện có, thông tin triển khai và các mẹo hữu ích.
Cử chỉ chạm
Bạn có thể sử dụng SDK Android để cho phép truy cập vào dữ liệu thô trên bàn di chuột của Glass. Quá trình này được thực hiện thông qua một trình phát hiện cử chỉ giúp tự động phát hiện các cử chỉ phổ biến trên ứng dụng Glass như nhấn, hất và cuộn.
Bạn cũng có thể sử dụng trình phát hiện cử chỉ này trong các ứng dụng để tính đến thao tác nhấn, vuốt về phía trước, vuốt ngược lại và vuốt xuống. Thao tác này tương tự như các thiết bị Glass trước đây.
Tốt nhất bạn nên sử dụng các cử chỉ này theo các cách sau:
- Nhấn: Xác nhận hoặc nhập.
- Vuốt về phía trước, vuốt về phía sau: Di chuyển qua các thẻ và màn hình.
- Vuốt xuống: Quay lại hoặc thoát.
Để biết thông tin chi tiết về cách triển khai, hãy đọc trình phát hiện cử chỉ mẫu.
Phát hiện cử chỉ bằng trình phát hiện cử chỉ của Android
Android GestureDetector
cho phép bạn phát hiện các cử chỉ đơn giản và phức tạp, chẳng hạn như các cử chỉ dùng nhiều ngón tay hoặc cuộn.
Phát hiện cử chỉ ở cấp hoạt động
Chỉ phát hiện các cử chỉ ở cấp hoạt động khi vật dụng không có tiêu điểm.
Ví dụ: nếu bạn muốn hiển thị một trình đơn khi người dùng nhấn vào bàn di chuột, bất kể chế độ xem nào có tiêu điểm, hãy xử lý MotionEvent
bên trong hoạt động.
Sau đây là ví dụ về tính năng phát hiện cử chỉ ở cấp hoạt động sử dụng GestureDetector
và triển khai GestureDetector.OnGestureListener
để xử lý các cử chỉ được nhận dạng, sau đó xử lý và dịch các nội dung sau:
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); } } } }
Ví dụ về mức sử dụng
Để sử dụng tính năng phát hiện cử chỉ ở cấp hoạt động, bạn cần hoàn thành các thao tác sau:
- Thêm phần khai báo sau vào tệp kê khai bên trong phần khai báo ứng dụng. Điều này cho phép ứng dụng của bạn nhận được
MotionEvent
trong hoạt động:<application> <!-- Copy below declaration into your manifest file --> <meta-data android:name="com.google.android.glass.TouchEnabledApplication" android:value="true" /> </application>
- Ghi đè phương thức
dispatchTouchEvent(motionEvent)
của hoạt động để chuyển các sự kiện chuyển động tới phương thứconTouchEvent(motionEvent)
của trình phát hiện cử chỉ. - Triển khai
GlassGestureDetector.OnGestureListener
trong hoạt động.
Sau đây là ví dụ về trình phát hiện cử chỉ ở cấp hoạt động:
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); } }
Thiết bị đầu vào âm thanh
Glass Enterprise Edition 2 là thiết bị dựa trên AOSP chuẩn hỗ trợ các nguồn âm thanh cơ bản.
Các nguồn âm thanh sau đây đã được triển khai tính năng xử lý tín hiệu nâng cao:
Nhận dạng giọng nói
Glass Enterprise Edition 2 hỗ trợ triển khai gốc để nhận dạng giọng nói. Thư này chỉ được hỗ trợ cho tiếng Anh.
Giao diện người dùng của tính năng nhận dạng lời nói chờ người dùng nói và sau đó trả về văn bản đã chép lời sau khi hoàn tất. Để bắt đầu hoạt động, hãy làm theo các bước sau:
- Gọi
startActivityForResult()
với ý địnhACTION_RECOGNIZE_SPEECH
. Các thành phần bổ sung ý định sau đây được hỗ trợ khi bạn bắt đầu hoạt động: - Ghi đè lệnh gọi lại
onActivityResult()
để nhận văn bản đã chép lời từ ý địnhEXTRA_RESULTS
như được hiển thị trong mã mẫu sau. Lệnh gọi lại này được gọi khi người dùng nói xong.
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); }
Để biết thông tin chi tiết về cách triển khai, hãy đọc ứng dụng nhận dạng giọng nói mẫu.
Xu hướng cho từ khóa
Tính năng nhận dạng lời nói trên Glass có thể thiên về danh sách từ khóa. Xu hướng làm tăng độ chính xác của tính năng nhận dạng từ khóa. Để bật tính năng xu hướng cho các từ khoá, hãy sử dụng:
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);
Lệnh thoại
Lệnh thoại cho phép người dùng thực hiện hành động từ các hoạt động. Bạn tạo các lệnh thoại bằng các API trình đơn Android tiêu chuẩn, nhưng người dùng có thể gọi các mục trong trình đơn bằng lệnh thoại thay vì chạm.
Để bật lệnh thoại cho một hoạt động cụ thể, hãy làm theo các bước sau:
- Gọi
getWindow().requestFeature(FEATURE_VOICE_COMMANDS)
trong hoạt động mong muốn để bật lệnh thoại. Khi tính năng này được bật, biểu tượng micrô sẽ xuất hiện ở góc dưới cùng bên trái của màn hình bất cứ khi nào hoạt động này nhận được tiêu điểm. - Yêu cầu quyền
RECORD_AUDIO
trong ứng dụng. - Ghi đè
onCreatePanelMenu()
và tăng cường tài nguyên trình đơn. - Ghi đè
onContextItemSelected()
để xử lý các lệnh thoại mà Google phát hiện được.
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); } } }
Sau đây là ví dụ về tài nguyên trình đơn mà hoạt động trước sử dụng:
<?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>
Hãy đọc ứng dụng ghi chú mẫu để biết ví dụ hoàn chỉnh.
Tải lại danh sách lệnh thoại
Bạn có thể tự động tải lại danh sách lệnh thoại. Để thực hiện việc này, hãy thay thế tài nguyên menu
trong phương thức onCreatePanelMenu()
hoặc sửa đổi đối tượng trình đơn trong phương thức onPreparePanel()
. Để áp dụng các thay đổi, hãy gọi phương thức 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(); }
Giải pháp AppCompatActivity
Để tải lại danh sách lệnh thoại trong một hoạt động mở rộng AppCompatActivity
, hãy sử dụng phương thức sendBroadcast()
với thao tác theo ý định reload-voice-commands
:
Kotlin
sendBroadcast(Intent("reload-voice-commands"))
Java
sendBroadcast(new Intent("reload-voice-commands"));
Bật và tắt lệnh thoại trong thời gian chạy
Bạn có thể bật và tắt các lệnh thoại trong thời gian chạy. Để thực hiện việc này, hãy trả về một giá trị thích hợp từ phương thức onCreatePanelMenu()
như sau:
- Đặt giá trị thành
true
để bật. - Đặt giá trị này thành
false
để tắt tính năng này.
Chế độ gỡ lỗi
Để bật chế độ gỡ lỗi cho các lệnh thoại, hãy gọi
getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS)
trong hoạt động mong muốn. Chế độ gỡ lỗi kích hoạt các tính năng sau:
- Logcat chứa nhật ký chứa cụm từ được công nhận để gỡ lỗi.
- Lớp phủ giao diện người dùng hiển thị khi phát hiện một lệnh không xác định, như sau:
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); } . . . }
Để biết thông tin chi tiết về cách triển khai, hãy đọc ứng dụng tải lại lệnh thoại mẫu.
Chuyển văn bản sang lời nói (TTS)
Chức năng chuyển văn bản sang lời nói chuyển đổi văn bản kỹ thuật số thành đầu ra bằng giọng nói tổng hợp. Để biết thêm thông tin, hãy truy cập vào Tài liệu dành cho nhà phát triển Android TextToSpeak.
Glass EE2 đã cài đặt công cụ Chuyển văn bản sang lời nói của Google. Nó được đặt làm công cụ TTS mặc định và hoạt động ngoại tuyến.
Các ngôn ngữ sau đi kèm với công cụ Chuyển văn bản sang lời nói của Google:
Tiếng Bengal Tiếng Trung |
Tiếng Hungary Tiếng Indonesia Tiếng Ý Tiếng Nhật Tiếng Java Tiếng Úc Austron |
Tiếng Ba Lan Tiếng Bồ Đào Nha Tiếng Nga Tiếng Slovak Tiếng Sunda Tiếng Thụy Điển Tiếng Tamil Tiếng Telugu Tiếng Thái Tiếng Thổ Nhĩ Kỳ Tiếng Ukraina Tiếng Việt |
Máy ảnh
Glass Enterprise Edition 2 được trang bị máy ảnh 8 megapixel, lấy nét cố định có khẩu độ f/2, 4, tỷ lệ khung hình cảm biến 4:3 và trường nhìn đường chéo 83° (71° x 57° theo hướng ngang). Bạn nên sử dụng API CameraX hoặc Camera2 chuẩn.
Để biết thông tin chi tiết về cách triển khai, hãy đọc ứng dụng máy ảnh mẫu.
Nút máy ảnh
Nút máy ảnh là nút vật lý trên bản lề của thiết bị Glass Enterprise Edition 2.
Bạn có thể xử lý thao tác này giống như một thao tác trên bàn phím chuẩn và có thể được xác định bằng mã phím
KeyEvent#KEYCODE_CAMERA
.
Kể từ bản cập nhật hệ điều hành OPM1.200313.001, ý định có các thao tác sau đây sẽ được gửi qua ứng dụng Trình chạy:
MediaStore#ACTION_IMAGE_CAPTURE
trên nút máy ảnh, hãy nhấn và giữ.MediaStore#ACTION_VIDEO_CAPTURE
nhấn và giữ nút máy ảnh.
Cảm biến
Có nhiều loại cảm biến dành cho nhà phát triển trong quá trình phát triển các ứng dụng trong Glass EE2.
Các cảm biến Android tiêu chuẩn sau đây được hỗ trợ trên Glass:
-
TYPE_ACCELEROMETER
-
TYPE_GRAVITY
-
TYPE_GYROSCOPE
-
TYPE_LIGHT
-
TYPE_LINEAR_ACCELERATION
-
TYPE_MAGNETIC_FIELD
TYPE_ORIENTATION
(không dùng nữa)-
TYPE_ROTATION_VECTOR
Các cảm biến Android sau đây không được hỗ trợ trên Glass:
Hệ thống toạ độ cảm biến Glass được hiển thị trong hình minh hoạ sau. Nó tương đối với màn hình Glass. Để biết thêm thông tin, hãy xem nội dung Hệ thống toạ độ cảm biến.
Gia tốc kế, con quay hồi chuyển và từ kế nằm trên vỏ quang học của thiết bị Glass, cho phép người dùng xoay thiết bị để phù hợp với thị giác của họ. Bạn không thể đo trực tiếp góc của nhóm ống kính, vì vậy, hãy lưu ý điều này khi bạn sử dụng góc từ các cảm biến này cho các ứng dụng, chẳng hạn như tiêu đề la bàn.
Để duy trì tuổi thọ pin, chỉ nghe các cảm biến khi bạn cần. Cân nhắc nhu cầu và vòng đời của ứng dụng khi bạn quyết định thời điểm bắt đầu và dừng nghe cảm biến.
Lệnh gọi lại sự kiện cảm biến chạy trên luồng giao diện người dùng. Vì vậy, hãy xử lý các sự kiện và trả về nhanh nhất có thể. Nếu quá trình xử lý mất quá nhiều thời gian, hãy đẩy các sự kiện cảm biến vào hàng đợi và sử dụng luồng nền để xử lý.
Tần số lấy mẫu 50 Hz thường là đủ để theo dõi chuyển động của đầu.
Để biết thêm thông tin về cách sử dụng cảm biến, hãy xem Hướng dẫn cho nhà phát triển Android.
Dịch vụ vị trí
Thiết bị Glass Enterprise Edition 2 không được trang bị mô-đun GPS và không cung cấp vị trí của người dùng. Tuy nhiên, tính năng này đã triển khai các dịch vụ vị trí. Việc này là cần thiết để hiển thị danh sách các mạng Wi-Fi và thiết bị Bluetooth ở gần.
Nếu ứng dụng có đặc quyền của chủ sở hữu thiết bị, bạn có thể sử dụng ứng dụng đó để thay đổi giá trị của chế độ cài đặt bảo mật tương ứng theo phương thức lập trình:
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)); }
Nếu bạn sử dụng giải pháp MDM bên thứ ba, thì giải pháp MDM phải có khả năng thay đổi các tùy chọn cài đặt này cho bạn.