Mengembangkan Layanan Aksesibilitas untuk Android

1. Pengantar

Layanan aksesibilitas adalah fitur framework Android yang didesain untuk memberikan masukan navigasi alternatif kepada pengguna atas nama aplikasi yang diinstal di perangkat Android. Layanan aksesibilitas dapat berkomunikasi kepada pengguna atas nama aplikasi, misalnya dengan mengonversi teks menjadi ucapan atau memberikan respons haptik saat pengguna mengarahkan kursor ke area penting pada layar. Codelab ini menunjukkan cara membuat layanan aksesibilitas yang sangat sederhana.

Apa itu Layanan Aksesibilitas?

Layanan Aksesibilitas membantu pengguna penyandang disabilitas dalam menggunakan perangkat dan aplikasi Android. Ini adalah layanan hak istimewa yang telah lama berjalan, yang membantu pengguna memproses informasi di layar dan memungkinkan mereka berinteraksi secara bermakna dengan perangkat.

Contoh layanan aksesibilitas umum

  • Tombol Akses: memungkinkan pengguna Android dengan batasan mobilitas untuk berinteraksi dengan perangkat menggunakan satu atau beberapa tombol.
  • Voice Access (beta): memungkinkan pengguna Android yang memiliki batasan mobilitas untuk mengontrol perangkat menggunakan perintah lisan.
  • Talkback: pembaca layar yang biasanya digunakan oleh penyandang gangguan penglihatan atau tunanetra.

Membangun layanan aksesibilitas

Meskipun Google menyediakan layanan seperti Tombol Akses, Voice Access, dan Talkback untuk pengguna Android, layanan ini mungkin tidak dapat melayani semua pengguna penyandang disabilitas. Karena banyak pengguna penyandang disabilitas memiliki kebutuhan unik, API Android untuk membuat layanan aksesibilitas bersifat terbuka, dan developer bebas membuat layanan aksesibilitas dan mendistribusikannya melalui Play Store.

Yang akan Anda buat

Dalam codelab ini, Anda akan mengembangkan layanan sederhana yang melakukan beberapa hal berguna menggunakan API aksesibilitas. Jika dapat menulis aplikasi Android dasar, Anda bisa mengembangkan layanan serupa.

API aksesibilitas sangat berguna: kode untuk layanan yang akan Anda bangun hanya dimuat dalam empat file, dan menggunakan ~200 baris kode!

Pengguna akhir

Anda akan membangun layanan untuk pengguna fiktif dengan karakteristik berikut:

  • Pengguna mengalami kesulitan menjangkau tombol samping pada perangkat.
  • Pengguna mengalami kesulitan menggulir atau menggeser.

Detail layanan

Layanan Anda akan menempatkan panel tindakan global di layar. Pengguna dapat menyentuh tombol pada bilah ini untuk melakukan tindakan berikut:

  1. Matikan perangkat tanpa menjangkau tombol daya sebenarnya pada sisi ponsel.
  2. Sesuaikan volume tanpa menyentuh tombol volume di bagian samping ponsel.
  3. Lakukan tindakan scroll tanpa benar-benar men-scroll.
  4. Lakukan geser tanpa harus menggunakan gestur geser.

Yang Anda butuhkan

Codelab ini mengasumsikan bahwa Anda akan menggunakan hal berikut:

  1. Komputer yang menjalankan Android Studio.
  2. Terminal untuk menjalankan perintah {i>shell<i} sederhana.
  3. Perangkat yang menjalankan Android 7.0 (Nougat) yang terhubung ke komputer yang akan Anda gunakan untuk pengembangan.

Mari kita mulai!

2. Mempersiapkan

Dengan menggunakan terminal, buat direktori tempat Anda akan bekerja. Ubah ke direktori ini.

Download Kode

Anda dapat meng-clone repo yang berisi kode untuk codelab ini:

git clone https://github.com/android/codelab-android-accessibility.git

Repositori ini berisi beberapa project Android Studio. Dengan Android Studio, buka GlobalActionBarService.

Luncurkan Android Studio dengan mengklik ikon Studio:

Logo yang digunakan untuk meluncurkan Android Studio.

Pilih opsi Import project (Eclipse ADT, Gradle, etc.):

Layar sambutan untuk Android Studio.

Buka lokasi tempat Anda meng-clone sumber, lalu pilih GlobalLogcatService.

Kemudian, dengan menggunakan terminal, beralihlah ke direktori {i>root<i}.

3. Memahami kode awal

Jelajahi project yang telah Anda buka.

Kerangka sederhana untuk layanan aksesibilitas telah dibuat untuk Anda. Semua kode yang akan Anda tulis dalam codelab ini dibatasi untuk empat file berikut:

  1. app/src/main/AndroidManifest.xml
  2. app/src/main/res/layout/action_bar.xml
  3. app/src/main/res/xml/global_action_bar_service.xml
  4. app/src/main/java/com/example/android/globalactionbarservice/GlobalActionBarService.java

Berikut adalah panduan konten setiap file.

AndroidManifest.xml

Informasi tentang layanan aksesibilitas dideklarasikan dalam manifes:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.android.globalactionbarservice">

   <application>
       <service
           android:name=".GlobalActionBarService"
           android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
           android:exported="true">
           <intent-filter>
               <action android:name="android.accessibilityservice.AccessibilityService" />
           </intent-filter>
           <meta-data
               android:name="android.accessibilityservice"
               android:resource="@xml/global_action_bar_service" />
       </service>
   </application>
</manifest>

Tiga item wajib berikut dideklarasikan di AndroidManifest.xml:

  1. Izin untuk mengikat ke layanan aksesibilitas:
<service
    ...
    android:permission = "android.permission.BIND_ACCESSIBILITY_SERVICE">
    ...             
</service>
  1. Intent AccessibilityService:
<intent-filter>
   <action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
  1. Lokasi file yang berisi metadata untuk layanan yang Anda buat:
<meta-data
       ...
       android:resource="@xml/global_action_bar_service" />
</service>

global_action_bar_service.xml

File ini berisi metadata untuk layanan.

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
   android:accessibilityFeedbackType="feedbackGeneric"
   android:accessibilityFlags="flagDefault"
   android:canPerformGestures="true"
   android:canRetrieveWindowContent="true" />

Dengan menggunakan elemen &lt;accessibility-service&gt;, metadata berikut telah ditentukan:

  1. Jenis masukan untuk layanan ini (codelab ini menggunakan feedbackGeneric, yang merupakan setelan default yang baik).
  2. Tanda aksesibilitas untuk layanan (codelab ini menggunakan tanda default).
  3. Kemampuan yang dibutuhkan untuk layanan ini:
  4. Untuk melakukan geser, android:canPerformGestures, disetel ke true.
  5. Untuk mengambil konten jendela, android:canRetrieveWindowContent ditetapkan ke true.

GlobalActionBarService.java

Sebagian besar kode untuk layanan aksesibilitas berada di GlobalActionBarService.java. Awalnya, file berisi kode minimum absolut untuk layanan aksesibilitas:

  1. Class yang memperluas AccessibilityService.
  2. Beberapa metode yang diganti yang diperlukan (dibiarkan kosong dalam codelab ini).
public class GlobalActionBarService extends AccessibilityService {

   @Override
   public void onAccessibilityEvent(AccessibilityEvent event) {

   }

   @Override
   public void onInterrupt() {

   }
}

Anda akan menambahkan kode ke file ini selama codelab.

action_bar.xml

Layanan ini mengekspos UI dengan empat tombol, dan file tata letak action_bar.xml berisi markup untuk menampilkan tombol tersebut:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="horizontal"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
</LinearLayout>

File ini berisi LinearLayout kosong untuk saat ini. Anda akan menambahkan markup untuk tombol selama codelab.

Meluncurkan aplikasi

Pastikan perangkat terhubung ke komputer Anda. Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Tindakan ini akan meluncurkan aplikasi yang sedang Anda kerjakan.

Buka Setelan > Aksesibilitas. Global Action Bar Service diinstal di perangkat Anda.

Layar setelan aksesibilitas

Klik Global Action Bar Service dan aktifkan. Anda akan melihat dialog izin berikut:

Dialog izin layanan aksesibilitas.

Layanan aksesibilitas meminta izin untuk mengamati tindakan pengguna, mengambil konten jendela, dan melakukan gestur atas nama pengguna. Saat menggunakan layanan aksesibilitas pihak ketiga, pastikan Anda benar-benar memercayai sumbernya.

Tidak ada banyak manfaat yang dijalankan dengan menjalankan layanan ini, karena kita belum menambahkan fungsionalitas apa pun. Mari kita mulai melakukannya.

4. Membuat tombol

Buka action_bar.xml di res/layout. Tambahkan markup di dalam LinearLayout yang saat ini kosong:

<LinearLayout ...>
    <Button
        android:id="@+id/power"
        android:text="@string/power"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/volume_up"
        android:text="@string/volume"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/scroll"
        android:text="@string/scroll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <Button
        android:id="@+id/swipe"
        android:text="@string/swipe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>

Tindakan ini akan membuat tombol yang akan ditekan pengguna untuk memicu tindakan di perangkat.

Buka GlobalActionBarService.java dan tambahkan variabel untuk menyimpan tata letak untuk panel tindakan:

public class GlobalActionBarService extends AccessibilityService {
    FrameLayout mLayout;
    ...
}

Sekarang tambahkan metode onServiceStarted():

public class GlobalActionBarService extends AccessibilityService {
   FrameLayout mLayout;

   @Override
   protected void onServiceConnected() {
       // Create an overlay and display the action bar
       WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
       mLayout = new FrameLayout(this);
       WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
       lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
       lp.format = PixelFormat.TRANSLUCENT;
       lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
       lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
       lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
       lp.gravity = Gravity.TOP;
       LayoutInflater inflater = LayoutInflater.from(this);
       inflater.inflate(R.layout.action_bar, mLayout);
       wm.addView(mLayout, lp);
   }
}

Kode ini meng-inflate tata letak dan menambahkan bilah tindakan ke bagian atas layar.

Metode onServiceConnected() berjalan saat layanan terhubung. Saat ini, layanan aksesibilitas memiliki semua izin yang diperlukan agar dapat berfungsi. Izin kunci yang akan Anda gunakan di sini adalah izin WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY. Izin ini memungkinkan Anda menggambar langsung pada layar di atas konten yang ada tanpa harus melalui alur izin yang rumit.

Siklus proses Layanan Aksesibilitas

Siklus proses layanan aksesibilitas dikelola secara eksklusif oleh sistem dan mengikuti siklus proses layanan yang telah ditetapkan.

  • Layanan aksesibilitas dimulai saat pengguna mengaktifkan layanan secara eksplisit di setelan perangkat.
  • Setelah mengikat ke layanan, sistem akan memanggil onServiceConnected(). Metode ini dapat diganti oleh layanan yang ingin melakukan penyiapan pasca-binding.
  • Layanan aksesibilitas berhenti baik saat pengguna menonaktifkannya di setelan perangkat atau saat memanggil disableSelf().

Menjalankan layanan

Sebelum dapat meluncurkan layanan menggunakan Android Studio, Anda perlu memastikan bahwa setelan Run dikonfigurasi dengan benar.

Edit konfigurasi Run Anda (gunakan Run dari menu atas, lalu buka Edit Configurations. Kemudian, dengan menggunakan dropdown, ubah Opsi Peluncuran dari "Default Activity" ke "Nothing".

Drop-down untuk mengonfigurasi setelan run guna meluncurkan layanan menggunakan Android Studio.

Sekarang Anda dapat meluncurkan layanan menggunakan Android Studio.

Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Lalu, kunjungi Setelan > Aksesibilitas dan aktifkan Global Action Bar Service.

Anda akan melihat empat tombol yang membentuk UI layanan yang dihamparkan di atas konten yang ditampilkan di layar.

overlay.png

Sekarang Anda akan menambahkan fungsionalitas ke keempat tombol, sehingga pengguna dapat menyentuhnya untuk melakukan tindakan yang berguna.

5. Mengonfigurasi tombol Daya

Tambahkan metode configurePowerButton() ke configurePowerButton():

private void configurePowerButton() {
   Button powerButton = (Button) mLayout.findViewById(R.id.power);
   powerButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
       }
   });
}

Untuk mengakses menu tombol daya, configurePowerButton() menggunakan metode performGlobalAction(), yang disediakan oleh AccessibilityService. Kode yang baru saja Anda tambahkan sederhana: mengklik tombol akan memicu onClickListener(). Tindakan ini akan memanggil performGlobalAction(GLOBAL_ACTION_POWER_DIALOG) dan menampilkan dialog daya kepada pengguna.

Perhatikan bahwa tindakan global tidak terikat dengan tampilan mana pun. Menekan tombol Kembali, tombol Beranda, tombol Terbaru adalah contoh tindakan global lainnya.

Sekarang tambahkan configurePowerButton() ke akhir metode onServiceTerhubung():

@Override
protected void onServiceConnected() {
   ...
   configurePowerButton();
}

Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Lalu, kunjungi Setelan > Aksesibilitas dan mulai Global Action Bar Service.

Tekan tombol Daya untuk menampilkan dialog daya.

6. Mengonfigurasi Tombol Volume

Tambahkan metode configureVolumeButton() ke configureVolumeButton():

private void configureVolumeButton() {
   Button volumeUpButton = (Button) mLayout.findViewById(R.id.volume_up);
   volumeUpButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
           audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
                   AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
       }
   });
}

Metode configureVolumeButton() menambahkan onClickListener() yang dipicu saat pengguna menekan tombol volume. Di dalam pemroses ini, configureVolumeButton() menggunakan AudioManager untuk menyesuaikan volume streaming.

Perhatikan bahwa siapa pun dapat mengontrol volume (Anda tidak harus menjadi layanan aksesibilitas untuk melakukan ini).

Sekarang tambahkan configureVolumeButton() ke akhir metode onServiceTerhubung():

@Override
protected void onServiceConnected() {
   ...

   configureVolumeButton();
}

Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Lalu, buka Setelan > Aksesibilitas dan mulai Global Action Bar Service.

Tekan tombol Volume untuk mengubah volume.

Pengguna fiktif yang tidak dapat menjangkau kontrol volume di sisi perangkat kini dapat menggunakan Layanan Panel Tindakan Global untuk mengubah (meningkatkan) volume.

7. Mengonfigurasi Tombol Scroll

Bagian ini melibatkan pengkodean dua metode. Metode pertama menemukan node yang dapat di-scroll, dan metode kedua melakukan tindakan scroll atas nama pengguna.

Tambahkan metode findScrollableNode ke findScrollableNode:

private AccessibilityNodeInfo findScrollableNode(AccessibilityNodeInfo root) {
   Deque<AccessibilityNodeInfo> deque = new ArrayDeque<>();
   deque.add(root);
   while (!deque.isEmpty()) {
       AccessibilityNodeInfo node = deque.removeFirst();
       if (node.getActionList().contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)) {
           return node;
       }
       for (int i = 0; i < node.getChildCount(); i++) {
           deque.addLast(node.getChild(i));
       }
   }
   return null;
}

Layanan aksesibilitas tidak memiliki akses ke tampilan sebenarnya di layar. Sebagai gantinya, aplikasi ini melihat refleksi dari apa yang ada di layar dalam bentuk hierarki yang terdiri dari objek AccessibilityNodeInfo. Objek ini berisi informasi tentang tampilan yang diwakilinya (lokasi tampilan, teks apa pun yang terkait dengan tampilan, metadata yang telah ditambahkan untuk aksesibilitas, tindakan yang didukung oleh tampilan, dll.). Metode findScrollableNode() melakukan traversal pertama luas dari pohon ini, yang dimulai dari node root. Jika menemukan node yang dapat di-scroll (yaitu, node yang mendukung tindakan AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD), node tersebut akan menampilkannya, jika tidak, node akan menampilkan null.

Sekarang, tambahkan metode configureScrollButton() ke configureScrollButton():

private void configureScrollButton() {
   Button scrollButton = (Button) mLayout.findViewById(R.id.scroll);
   scrollButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());
           if (scrollable != null) {
               scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId());
           }
       }
   });
}

Metode ini membuat onClickListener() yang diaktifkan saat tombol scroll diklik. Kode ini mencoba menemukan node yang dapat di-scroll dan, jika berhasil, akan melakukan tindakan scroll.

Sekarang tambahkan configureScrollButton() ke onServiceTerhubung():

@Override
protected void onServiceConnected() {
   ...

   configureScrollButton();
}

Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Lalu, buka Setelan > Aksesibilitas dan mulai Global Action Bar Service.

Tekan tombol kembali untuk membuka Setelan > Aksesibilitas. Item pada aktivitas setelan aksesibilitas dapat di-scroll dan menyentuh tombol Scroll akan melakukan tindakan scroll. Pengguna fiktif yang tidak dapat melakukan tindakan scroll dengan mudah kini dapat menggunakan tombol Scroll untuk men-scroll daftar item.

8. Mengonfigurasi Tombol Geser

Tambahkan metode configureSwipeButton() ke configureSwipeButton():

private void configureSwipeButton() {
   Button swipeButton = (Button) mLayout.findViewById(R.id.swipe);
   swipeButton.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View view) {
           Path swipePath = new Path();
           swipePath.moveTo(1000, 1000);
           swipePath.lineTo(100, 1000);
           GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
           gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 500));
           dispatchGesture(gestureBuilder.build(), null, null);
       }
   });
}

Metode configureSwipeButton() menggunakan API baru yang ditambahkan di N yang melakukan gestur atas nama pengguna. Kode ini menggunakan objek GestureDescription untuk menentukan jalur gestur yang akan dilakukan (nilai hardcode digunakan dalam codelab ini), lalu mengirimkan gestur geser atas nama pengguna menggunakan metode AccessibilityService dispatchGesture().

Sekarang tambahkan configureSwipeButton() ke onServiceTerhubung():

@Override
protected void onServiceConnected() {
   ...
   configureSwipeButton();
}

Tekan ikon hijau Play Tombol Putar Android Studio yang digunakan untuk meluncurkan layanan dari panel menu ke bagian atas layar. Lalu, buka Setelan > Aksesibilitas dan mulai Global Action Bar Service.

Cara termudah untuk menguji fungsi geser adalah dengan membuka aplikasi Maps yang diinstal di ponsel. Setelah peta dimuat, menyentuh tombol Usap akan menggeser layar ke kanan.

9. Ringkasan

Selamat! Anda telah membuat layanan aksesibilitas yang sederhana dan fungsional.

Anda dapat memperluas layanan ini dalam berbagai cara. Contoh:

  1. Buat panel tindakan dapat dipindahkan (saat ini hanya ada di bagian atas layar).
  2. Izinkan pengguna menaikkan dan menurunkan volume.
  3. Izinkan pengguna menggeser ke kiri dan kanan.
  4. Menambahkan dukungan untuk gestur tambahan yang dapat direspons oleh panel tindakan.

Codelab ini hanya mencakup sebagian kecil fungsi yang disediakan oleh API aksesibilitas. API juga mencakup hal berikut (daftar sebagian):

  • Dukungan untuk multi-jendela.
  • Dukungan untuk AccessibilityEvent. Saat UI berubah, layanan aksesibilitas akan diberi tahu tentang perubahan tersebut menggunakan objek AccessibilityEvent. Selanjutnya, layanan dapat merespons perubahan UI sebagaimana mestinya.
  • Kemampuan untuk mengontrol pembesaran.

Codelab ini membantu Anda mulai menulis layanan aksesibilitas. Jika Anda mengenal pengguna dengan masalah aksesibilitas tertentu yang ingin diatasi, Anda kini dapat membangun layanan untuk membantu pengguna tersebut.