Input dan sensor

SDK Android memberi Anda akses ke berbagai input dan sensor yang tersedia di Glass EE2. Halaman ini menyediakan ringkasan fitur, detail implementasi, dan tips bermanfaat yang tersedia.

Gestur sentuh

Anda dapat menggunakan Android SDK untuk mengaktifkan akses ke data mentah dari touchpad Glass. Hal ini dilakukan melalui detektor gestur yang otomatis mendeteksi gestur umum pada Glass, seperti ketuk, lempar, dan scroll.

Anda juga dapat menggunakan pendeteksi gestur ini di aplikasi untuk memperhitungkan ketukan, geser ke depan, geser ke belakang, dan geser ke bawah. Perangkat ini serupa dengan perangkat Glass sebelumnya.

Sebaiknya gunakan gestur ini dengan cara berikut:

  • Ketuk: Konfirmasi atau masukkan.
  • Geser ke depan, geser ke belakang: Menavigasi kartu dan layar.
  • Geser ke bawah: Kembali atau keluar.

Untuk detail penerapan, baca pendeteksi gestur contoh.

Mendeteksi gestur dengan detektor gestur Android

GestureDetector Android memungkinkan Anda mendeteksi gestur sederhana dan kompleks, seperti gestur yang menggunakan beberapa jari atau men-scroll.

Mendeteksi gestur level aktivitas

Mendeteksi gestur pada level aktivitas hanya jika ada bagian UI yang perlu difokuskan. Misalnya, jika Anda ingin memunculkan menu saat pengguna mengetuk touchpad, terlepas dari tampilan yang memiliki fokus, tangani MotionEvent di dalam aktivitas.

Berikut adalah contoh deteksi gestur level aktivitas yang menggunakan GestureDetector dan menerapkan GestureDetector.OnGestureListener untuk memproses gestur yang dikenali, yang kemudian ditangani dan diterjemahkan ke dalam kode berikut:

  • 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);
       }
     }
   }
  }

Contoh penggunaan

Untuk memanfaatkan deteksi gestur level aktivitas, Anda perlu menyelesaikan tugas-tugas berikut:

  1. Tambahkan deklarasi berikut ke file manifes Anda, di dalam deklarasi aplikasi. Hal ini memungkinkan aplikasi Anda menerima MotionEvent dalam aktivitas:
    <application>
    <!-- Copy below declaration into your manifest file -->
    <meta-data
      android:name="com.google.android.glass.TouchEnabledApplication"
      android:value="true" />
    </application>
    
  2. Ganti metode dispatchTouchEvent(motionEvent) aktivitas untuk meneruskan peristiwa gerakan ke metode onTouchEvent(motionEvent) detektor gestur.
  3. Implementasikan GlassGestureDetector.OnGestureListener dalam aktivitas Anda.

Berikut adalah contoh pendeteksi gestur tingkat aktivitas:

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);
   }
  }

Input audio

Glass Enterprise Edition 2 adalah perangkat berbasis AOSP standar yang mendukung sumber audio dasar.

Sumber audio berikut telah menerapkan pemrosesan sinyal lanjutan:

Pengenalan suara

Glass Enterprise Edition 2 mendukung implementasi native untuk pengenalan ucapan. Setelan ini hanya didukung untuk bahasa Inggris.

Gambar pengenalan suara kaca.

UI pengenalan ucapan menunggu pengguna berbicara, lalu menampilkan teks yang ditranskripsikan setelah selesai. Untuk memulai aktivitas, ikuti langkah-langkah berikut:

  1. Panggil startActivityForResult() dengan intent ACTION_RECOGNIZE_SPEECH. Tambahan intent berikut ini didukung saat Anda memulai aktivitas:
  2. Ganti callback onActivityResult() untuk menerima teks yang ditranskripsikan dari ekstra intent EXTRA_RESULTS seperti yang ditunjukkan dalam contoh kode berikut. Callback ini dipanggil saat pengguna selesai berbicara.

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);
}

Untuk detail penerapan, baca contoh aplikasi pengenalan suara.

Pembiasan untuk kata kunci

Pengenalan ucapan pada Glass dapat dibias untuk daftar kata kunci. Bias meningkatkan akurasi pengenalan kata kunci. Untuk mengaktifkan bias untuk kata kunci, gunakan hal berikut:

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);

Perintah suara

Perintah suara memungkinkan pengguna melakukan tindakan dari aktivitas. Anda membuat perintah suara dengan API menu Android standar, tetapi pengguna dapat memanggil item menu dengan perintah suara, bukan sentuhan.

Guna mengaktifkan perintah suara untuk aktivitas tertentu, ikuti langkah berikut:

  1. Panggil getWindow().requestFeature(FEATURE_VOICE_COMMANDS) dalam aktivitas yang diinginkan untuk mengaktifkan perintah suara. Jika fitur ini diaktifkan, ikon mikrofon akan muncul di sudut kiri bawah layar setiap kali aktivitas ini menerima fokus.
  2. Minta izin RECORD_AUDIO di aplikasi Anda.
  3. Ganti onCreatePanelMenu() dan inflate resource menu.
  4. Ganti onContextItemSelected() untuk menangani perintah suara yang terdeteksi.

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);
    }
  }
}

Berikut adalah contoh resource menu yang digunakan oleh aktivitas sebelumnya:

<?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>

Baca contoh aplikasi pembuat catatan untuk contoh lengkapnya.

Daftar ulang perintah suara dimuat ulang

Anda dapat memuat ulang daftar perintah suara secara dinamis. Untuk melakukannya, ganti resource menu dalam metode onCreatePanelMenu(), atau ubah objek menu di metode onPreparePanel(). Untuk menerapkan perubahan, panggil metode 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();
}

Solusi AppCompatActivity

Untuk memuat ulang daftar perintah suara dalam aktivitas yang memperluas AppCompatActivity, gunakan metode sendBroadcast() dengan tindakan intent reload-voice-commands:

Kotlin

sendBroadcast(Intent("reload-voice-commands"))

Java

sendBroadcast(new Intent("reload-voice-commands"));

Mengaktifkan dan menonaktifkan perintah suara saat runtime

Anda dapat mengaktifkan dan menonaktifkan perintah suara saat runtime. Untuk melakukannya, tampilkan nilai yang sesuai dari metode onCreatePanelMenu() seperti berikut:

  • Setel nilai ke true untuk mengaktifkan.
  • Setel nilai ke false untuk menonaktifkan.

Mode debug

Untuk mengaktifkan mode debug untuk perintah suara, panggil getWindow().requestFeature(FEATURE_DEBUG_VOICE_COMMANDS) dalam aktivitas yang diinginkan. Mode debug mengaktifkan fitur berikut:

  • Logcat berisi log dengan frasa yang dikenali untuk proses debug.
  • Overlay UI ditampilkan saat perintah yang tidak dikenal terdeteksi, seperti yang ditunjukkan:
  • Gambar perintah kaca pengenalan suara tidak dikenal.

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);
  }
  .
  .
  .
}

Untuk detail penerapan, baca contoh aplikasi pemuatan ulang perintah suara.

Text-to-Speech (TTS)

Fungsi Text-to-Speech mengonversi teks digital menjadi output ucapan yang disintesis. Untuk informasi selengkapnya, buka TextToSpeech Dokumentasi Developer Android.

Glass EE2 telah menginstal mesin Google Text-to-Speech. Ini ditetapkan sebagai mesin TTS default dan berfungsi secara offline.

Lokal berikut dipaketkan dengan mesin Google Text-to-Speech:

Bengali
China Mandarin
Ceko
Denmark
Jerman
Yunani
Inggris
Spanyol
Estonia
Finlandia
Prancis
Gujarati
Hindi
Hungaria
Indonesia
Italia
Jepang
Jawa
Austronesia
Austroasiatik
Kannada
Korea
Malayalam
Norwegia
Belanda
Polandia
Portugis
Rusia
Slovak
Sunda
Swedia
Tamil
Telugu
Thai
Turki
Ukraina
Vietnam

Kamera

Glass Enterprise Edition 2 dilengkapi dengan kamera 8 megapiksel, fokus tetap yang memiliki aperture f/2,4, rasio lebar tinggi sensor 4:3, dan ruang pandang diagonal 83° (71° x 57° dalam orientasi lanskap). Sebaiknya gunakan CameraX atau Camera2 API standar.

Untuk mengetahui detail implementasi, baca contoh aplikasi kamera.

Tombol kamera

Tombol kamera adalah tombol fisik pada engsel perangkat Glass Enterprise Edition 2. Ini dapat ditangani seperti tindakan keyboard standar dan dapat diidentifikasi dengan kode tombol KeyEvent#KEYCODE_CAMERA.

Mulai update OS OPM1.200313.001, intent dengan tindakan berikut akan dikirim dari aplikasi Peluncur:

Sensor

Ada berbagai sensor yang tersedia untuk developer saat mereka mengembangkan aplikasi di Glass EE2.

Sensor Android standar berikut didukung di Glass:

Sensor Android berikut tidak didukung di Glass:

Sistem koordinat sensor kaca ditampilkan dalam ilustrasi berikut. Ini relatif terhadap layar Kaca. Untuk informasi selengkapnya, lihat Sistem koordinat sensor.

Sistem koordinat sensor Kaca ditampilkan di sini, relatif terhadap tampilan Kaca.

Akselerometer, giroskop, dan magnetometer terletak di pod optik perangkat Glass, yang diputar pengguna untuk menyelaraskan perangkat dengan penglihatannya. Anda tidak dapat mengukur sudut pod optik secara langsung, jadi perhatikan hal ini saat Anda menggunakan sudut dari sensor ini untuk aplikasi, seperti arah kompas.

Untuk menghemat masa pakai baterai, hanya dengarkan sensor saat Anda membutuhkannya. Pertimbangkan kebutuhan dan siklus proses aplikasi saat Anda memutuskan kapan harus memulai dan berhenti mendengarkan sensor.

Callback peristiwa sensor berjalan pada UI thread, jadi proses peristiwa dan kembalilah secepat mungkin. Jika pemrosesan berlangsung terlalu lama, dorong peristiwa sensor ke dalam antrean dan gunakan thread latar belakang untuk menanganinya.

50 Hz sering kali memiliki frekuensi sampling yang memadai untuk melacak gerakan kepala.

Untuk mengetahui informasi selengkapnya tentang cara menggunakan sensor, lihat panduan developer Android.

Layanan lokasi

Perangkat Glass Enterprise Edition 2 tidak dilengkapi dengan modul GPS dan tidak menyediakan lokasi pengguna. Namun, layanan ini menerapkan layanan lokasi, yang diperlukan untuk menampilkan daftar jaringan Wi-Fi dan perangkat Bluetooth di sekitar.

Jika aplikasi Anda memiliki hak istimewa pemilik perangkat, Anda dapat menggunakannya untuk mengubah nilai setelan aman yang sesuai secara terprogram:

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));
}

Jika Anda menggunakan solusi MDM pihak ketiga, solusi MDM harus dapat mengubah setelan ini untuk Anda.