บริการการช่วยเหลือพิเศษคือแอปที่ปรับปรุงอินเทอร์เฟซผู้ใช้เพื่อช่วยเหลือ ผู้ใช้ที่มีความพิการหรืออาจไม่สามารถโต้ตอบได้อย่างสมบูรณ์แบบชั่วคราว ด้วยอุปกรณ์ เช่น ผู้ใช้ที่ขับรถและดูแลเด็กเล็ก หรือไปงานปาร์ตี้ที่มีเสียงดังมากๆ อาจต้องใช้อินเทอร์เฟซเพิ่มเติมหรืออินเทอร์เฟซอื่น ความคิดเห็น
Android ให้บริการการช่วยเหลือพิเศษแบบมาตรฐาน ซึ่งรวมถึง TalkBack และนักพัฒนาแอปจะสร้างและเผยแพร่บริการของตนเองได้อย่างไร เอกสารนี้ อธิบายพื้นฐานในการสร้างบริการการช่วยเหลือพิเศษ
บริการการช่วยเหลือพิเศษอาจมาพร้อมกับแอปทั่วไปหรือสร้างเป็น Android แบบสแตนด์อโลน โดยมีขั้นตอนในการสร้างบริการเหมือนกัน สถานการณ์ใดสถานการณ์หนึ่ง
สร้างบริการการช่วยเหลือพิเศษ
สร้างชั้นเรียนแบบขยายภายในโปรเจ็กต์ของคุณ
AccessibilityService
:
Kotlin
package com.example.android.apis.accessibility import android.accessibilityservice.AccessibilityService import android.view.accessibility.AccessibilityEvent class MyAccessibilityService : AccessibilityService() { ... override fun onInterrupt() {} override fun onAccessibilityEvent(event: AccessibilityEvent?) {} ... }
Java
package com.example.android.apis.accessibility; import android.accessibilityservice.AccessibilityService; import android.view.accessibility.AccessibilityEvent; public class MyAccessibilityService extends AccessibilityService { ... @Override public void onAccessibilityEvent(AccessibilityEvent event) { } @Override public void onInterrupt() { } ... }
หากคุณสร้างโปรเจ็กต์ใหม่สำหรับ Service
นี้และไม่ได้วางแผนที่จะมีแอป
ที่เกี่ยวข้อง คุณสามารถนำคลาส Activity
เริ่มต้นออกจาก
แหล่งที่มา
การประกาศและสิทธิ์ในไฟล์ Manifest
แอปที่ให้บริการการช่วยเหลือพิเศษต้องมีประกาศเฉพาะใน ไฟล์ Manifest ของแอปจะถือเป็นบริการช่วยเหลือพิเศษโดย Android ระบบ ส่วนนี้จะอธิบายการตั้งค่าที่บังคับและไม่บังคับสำหรับ บริการการช่วยเหลือพิเศษ
การประกาศบริการการช่วยเหลือพิเศษ
หากต้องการให้แอปของคุณถือเป็นบริการช่วยเหลือพิเศษ ให้ใส่ service
แทนที่จะเป็นองค์ประกอบ activity
ภายใน application
ในไฟล์ Manifest นอกจากนี้ ภายในองค์ประกอบ service
ให้ใส่
ตัวกรอง Intent ของบริการการช่วยเหลือพิเศษ ไฟล์ Manifest ต้องปกป้องบริการด้วย
โดยเพิ่ม
BIND_ACCESSIBILITY_SERVICE
เพื่อให้มั่นใจว่ามีเพียงระบบเท่านั้นที่สามารถเชื่อมโยงกับระบบได้ ตัวอย่างเช่น
<application> <service android:name=".MyAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" android:label="@string/accessibility_service_label"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> </service> </application>
การกำหนดค่าบริการการช่วยเหลือพิเศษ
บริการการช่วยเหลือพิเศษต้องมีการกำหนดค่าที่ระบุประเภทของ
เหตุการณ์การช่วยเหลือพิเศษที่บริการจัดการและข้อมูลเพิ่มเติม
บริการ การกำหนดค่าของบริการการเข้าถึงจะอยู่ใน
AccessibilityServiceInfo
บริการของคุณสามารถสร้างและตั้งค่าการกำหนดค่าโดยใช้อินสแตนซ์นี้
ชั้นเรียนและ
setServiceInfo()
ขณะรันไทม์ อย่างไรก็ตาม ตัวเลือกการกำหนดค่าบางอย่างอาจใช้ไม่ได้เมื่อใช้
คุณใส่เอลิเมนต์ <meta-data>
ลงในไฟล์ Manifest เพื่ออ้างอิง
ซึ่งทำให้คุณสามารถตั้งค่าตัวเลือกทั้งหมดสำหรับ
บริการการเข้าถึงดังที่ปรากฏในตัวอย่างต่อไปนี้
<service android:name=".MyAccessibilityService"> ... <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service>
องค์ประกอบ <meta-data>
นี้หมายถึงไฟล์ XML ที่คุณสร้างขึ้นในไฟล์
ไดเรกทอรีทรัพยากรของแอป:
<project_dir>/res/xml/accessibility_service_config.xml>
รหัสต่อไปนี้
แสดงตัวอย่างเนื้อหาของไฟล์การกำหนดค่าบริการ
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/accessibility_service_description" android:packageNames="com.example.android.apis" android:accessibilityEventTypes="typeAllMask" android:accessibilityFlags="flagDefault" android:accessibilityFeedbackType="feedbackSpoken" android:notificationTimeout="100" android:canRetrieveWindowContent="true" android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity" />
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแอตทริบิวต์ XML ที่สามารถใช้ใน ไฟล์การกำหนดค่าบริการการช่วยเหลือพิเศษ โปรดดูข้อมูลอ้างอิงต่อไปนี้ เอกสารประกอบ:
android:description
android:packageNames
android:accessibilityEventTypes
android:accessibilityFlags
android:accessibilityFeedbackType
android:notificationTimeout
android:canRetrieveWindowContent
android:settingsActivity
ดูข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่าการกําหนดค่าแบบไดนามิกได้
ที่รันไทม์ โปรดดู
AccessibilityServiceInfo
เอกสารอ้างอิง
กำหนดค่าบริการการช่วยเหลือพิเศษ
คำนึงถึงสิ่งต่อไปนี้เมื่อตั้งค่าตัวแปรการกำหนดค่าสำหรับ บริการการช่วยเหลือพิเศษเพื่อบอกระบบว่าจะทำงานอย่างไรและเมื่อใด ดังนี้
- คุณต้องการให้กิจกรรมตอบสนองต่อเหตุการณ์ประเภทใด
- ต้องมีการเปิดใช้บริการดังกล่าวในทุกแอปหรือเฉพาะบางแพ็กเกจ ชื่ออะไร
- ความคิดเห็นประเภทต่างๆ ที่ใช้
คุณมี 2 ตัวเลือกสำหรับการตั้งค่าตัวแปรเหล่านี้ ตัวเลือกที่เข้ากันได้แบบย้อนหลัง
คือการตั้งค่าในโค้ดโดยใช้
setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
ในการดำเนินการนี้ ให้แทนที่
onServiceConnected()
และกำหนดค่าบริการของคุณ ดังที่ปรากฏในตัวอย่างต่อไปนี้:
Kotlin
override fun onServiceConnected() { info.apply { // Set the type of events that this service wants to listen to. Others // aren't passed to this service. eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_VIEW_FOCUSED // If you only want this service to work with specific apps, set their // package names here. Otherwise, when the service is activated, it // listens to events from all apps. packageNames = arrayOf("com.example.android.myFirstApp", "com.example.android.mySecondApp") // Set the type of feedback your service provides. feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN // Default services are invoked only if no package-specific services are // present for the type of AccessibilityEvent generated. This service is // app-specific, so the flag isn't necessary. For a general-purpose // service, consider setting the DEFAULT flag. // flags = AccessibilityServiceInfo.DEFAULT; notificationTimeout = 100 } this.serviceInfo = info }
Java
@Override public void onServiceConnected() { // Set the type of events that this service wants to listen to. Others // aren't passed to this service. info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED | AccessibilityEvent.TYPE_VIEW_FOCUSED; // If you only want this service to work with specific apps, set their // package names here. Otherwise, when the service is activated, it listens // to events from all apps. info.packageNames = new String[] {"com.example.android.myFirstApp", "com.example.android.mySecondApp"}; // Set the type of feedback your service provides. info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; // Default services are invoked only if no package-specific services are // present for the type of AccessibilityEvent generated. This service is // app-specific, so the flag isn't necessary. For a general-purpose service, // consider setting the DEFAULT flag. // info.flags = AccessibilityServiceInfo.DEFAULT; info.notificationTimeout = 100; this.setServiceInfo(info); }
ตัวเลือกที่ 2 คือการกำหนดค่าบริการโดยใช้ไฟล์ XML บางประเภท
ตัวเลือกการกำหนดค่า เช่น
canRetrieveWindowContent
จะใช้ได้เมื่อคุณกำหนดค่าบริการโดยใช้ XML เท่านั้น การกำหนดค่า
ตัวเลือกจากตัวอย่างก่อนหน้านี้มีลักษณะดังนี้เมื่อกำหนดโดยใช้ XML
<accessibility-service android:accessibilityEventTypes="typeViewClicked|typeViewFocused" android:packageNames="com.example.android.myFirstApp, com.example.android.mySecondApp" android:accessibilityFeedbackType="feedbackSpoken" android:notificationTimeout="100" android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity" android:canRetrieveWindowContent="true" />
หากคุณใช้ XML ให้อ้างถึงไฟล์ในไฟล์ Manifest โดยเพิ่ม
<meta-data>
ต่อท้าย
การประกาศบริการซึ่งชี้ไปที่ไฟล์ XML หากเก็บไฟล์ XML ไว้ใน
res/xml/serviceconfig.xml
แท็กใหม่จะมีลักษณะดังนี้
<service android:name=".MyAccessibilityService"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/serviceconfig" /> </service>
วิธีการให้บริการการช่วยเหลือพิเศษ
บริการการช่วยเหลือพิเศษต้องขยายคลาส AccessibilityService
และ
ลบล้างเมธอดต่อไปนี้จากคลาสดังกล่าว วิธีการเหล่านี้จะแสดงใน
ลำดับที่ระบบ Android เรียกผู้ใช้: ตั้งแต่เริ่มบริการ
(onServiceConnected()
) จนถึงขณะที่วิดีโอทำงานอยู่
(onAccessibilityEvent()
onInterrupt()
)
จนถึงตอนปิดตัว
(onUnbind()
)
onServiceConnected()
: (ไม่บังคับ) ระบบจะเรียกใช้เมธอดนี้เมื่อ เชื่อมต่อกับบริการการช่วยเหลือพิเศษ ใช้วิธีนี้เพื่อตั้งค่าแบบครั้งเดียว ขั้นตอนสำหรับบริการของคุณ รวมถึงการเชื่อมต่อกับระบบความคิดเห็นของผู้ใช้ เช่น โปรแกรมจัดการเสียง หรือการสั่นของอุปกรณ์ หากต้องการตั้งค่า การกำหนดค่าของบริการขณะรันไทม์ หรือทำการปรับเปลี่ยนแบบครั้งเดียว ตำแหน่งนี้ทำให้โทรหาsetServiceInfo()
ได้สะดวกonAccessibilityEvent()
: (ต้องระบุ) ระบบจะโทรกลับวิธีนี้เมื่อ ตรวจพบAccessibilityEvent
ที่ตรงกับพารามิเตอร์การกรองเหตุการณ์ที่การช่วยเหลือพิเศษระบุไว้ เช่น เมื่อผู้ใช้แตะปุ่มหรือโฟกัสที่อินเทอร์เฟซผู้ใช้ ควบคุมในแอปที่บริการการช่วยเหลือพิเศษของคุณแสดงความคิดเห็นให้ วันและเวลา ระบบเรียกใช้เมธอดนี้ ซึ่งส่งผ่านAccessibilityEvent
ที่เกี่ยวข้อง ซึ่งบริการสามารถตีความและใช้เพื่อแสดงความคิดเห็นแก่ ผู้ใช้ วิธีการนี้สามารถเรียกใช้ได้หลายครั้งตลอดวงจร service.onInterrupt()
: (ต้องระบุ) ระบบเรียกใช้เมธอดนี้เมื่อระบบ ต้องการขัดขวางความคิดเห็นที่คุณได้รับจากบริการ ซึ่งมักอยู่ใน การตอบสนองต่อการดำเนินการของผู้ใช้ เช่น การย้ายโฟกัสไปยังตัวควบคุมอื่น ช่วงเวลานี้ สามารถเรียกใช้ได้หลายครั้งตลอดวงจรของบริการของคุณonUnbind()
: (ไม่บังคับ) ระบบจะเรียกใช้เมธอดนี้เมื่อระบบ กำลังจะปิดบริการการช่วยเหลือพิเศษ ใช้วิธีการนี้เพื่อทำสิ่งต่างๆ ขั้นตอนการปิดระบบแบบครั้งเดียว รวมถึงระบบการจัดสรรความคิดเห็นของผู้ใช้ เช่น โปรแกรมจัดการเสียง หรือการสั่นของอุปกรณ์
เมธอด Callback เหล่านี้ให้โครงสร้างพื้นฐานสำหรับการช่วยเหลือพิเศษ
service. คุณสามารถเลือกวิธีประมวลผลข้อมูลที่ได้รับจากระบบ Android ใน
รูปแบบของออบเจ็กต์ AccessibilityEvent
และให้ความคิดเห็นแก่ผู้ใช้ สำหรับ
หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการรับข้อมูลจากกิจกรรมการช่วยเหลือพิเศษ โปรดดูรับ
รายละเอียดกิจกรรม
ลงทะเบียนเข้าร่วมกิจกรรมการช่วยเหลือพิเศษ
ฟังก์ชันที่สำคัญที่สุดอย่างหนึ่งของการกำหนดค่าบริการการช่วยเหลือพิเศษ ช่วยให้คุณระบุประเภทของเหตุการณ์การช่วยเหลือพิเศษของบริการได้ สามารถจัดการได้ การระบุข้อมูลนี้จะช่วยให้บริการการช่วยเหลือพิเศษทำงานร่วมกัน ระหว่างกัน และช่วยให้จัดการเฉพาะเหตุการณ์หนึ่งๆ ได้อย่างยืดหยุ่น จากแอปบางแอป การกรองเหตุการณ์อาจประกอบด้วยสิ่งต่อไปนี้ เกณฑ์:
ชื่อแพ็กเกจ: ระบุชื่อแพ็กเกจของแอปที่มีความสามารถในการเข้าถึง เหตุการณ์ที่คุณต้องการให้บริการจัดการ หากไม่ระบุพารามิเตอร์นี้ บริการการช่วยเหลือพิเศษจะถือว่าพร้อมใช้งานสำหรับการช่วยเหลือพิเศษของบริการ เหตุการณ์ของแอปใดๆ คุณตั้งค่าพารามิเตอร์นี้ในบริการการช่วยเหลือพิเศษได้ ที่มีแอตทริบิวต์
android:packageNames
เป็น รายการที่คั่นด้วยคอมมาหรือใช้AccessibilityServiceInfo.packageNames
ประเภทเหตุการณ์: ระบุประเภทของเหตุการณ์การช่วยเหลือพิเศษที่คุณต้องการให้ ที่ต้องจัดการ คุณตั้งค่าพารามิเตอร์นี้ในบริการการช่วยเหลือพิเศษได้ ที่มีแอตทริบิวต์
android:accessibilityEventTypes
เป็น รายการที่คั่นด้วยอักขระ|
ตัวอย่างเช่นaccessibilityEventTypes="typeViewClicked|typeViewFocused"
หรือคุณสามารถตั้งค่า โดยใช้AccessibilityServiceInfo.eventTypes
เมื่อตั้งค่าบริการการช่วยเหลือพิเศษ โปรดพิจารณาอย่างรอบคอบว่าเหตุการณ์ใดที่คุณ บริการจะจัดการและลงทะเบียนสำหรับกิจกรรมเหล่านั้นได้เท่านั้น เนื่องจากผู้ใช้เปิดใช้งานได้ บริการการเข้าถึงมากกว่า 1 บริการพร้อมกัน บริการของคุณจะต้องไม่ใช้ ที่ไม่สามารถรับมือได้ โปรดทราบว่าบริการอื่นๆ อาจจัดการกับ กิจกรรมเพื่อปรับปรุงประสบการณ์ของผู้ใช้
ระดับเสียงการช่วยเหลือพิเศษ
อุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไปประกอบด้วย
STREAM_ACCESSIBILITY
หมวดหมู่ระดับเสียง ซึ่งช่วยให้คุณควบคุมการช่วยเหลือพิเศษได้
เอาต์พุตเสียงของบริการแยกจากเสียงอื่นๆ ในอุปกรณ์
บริการการช่วยเหลือพิเศษสามารถใช้สตรีมประเภทนี้โดยการตั้งค่า
FLAG_ENABLE_ACCESSIBILITY_VOLUME
ตัวเลือก จากนั้นคุณจะเปลี่ยนระดับเสียงสำหรับการช่วยเหลือพิเศษของอุปกรณ์ได้ด้วยการโทร
เวลา
adjustStreamVolume()
ในอินสแตนซ์ของอุปกรณ์
AudioManager
ตัวอย่างข้อมูลโค้ดต่อไปนี้แสดงให้เห็นว่าบริการการช่วยเหลือพิเศษสามารถใช้
หมวดหมู่หนังสือชุด STREAM_ACCESSIBILITY
:
Kotlin
import android.media.AudioManager.* class MyAccessibilityService : AccessibilityService() { private val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager override fun onAccessibilityEvent(accessibilityEvent: AccessibilityEvent) { if (accessibilityEvent.source.text == "Increase volume") { audioManager.adjustStreamVolume(AudioManager.STREAM_ACCESSIBILITY, ADJUST_RAISE, 0) } } }
Java
import static android.media.AudioManager.*; public class MyAccessibilityService extends AccessibilityService { private AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE); @Override public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) { AccessibilityNodeInfo interactedNodeInfo = accessibilityEvent.getSource(); if (interactedNodeInfo.getText().equals("Increase volume")) { audioManager.adjustStreamVolume(AudioManager.STREAM_ACCESSIBILITY, ADJUST_RAISE, 0); } } }
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 6:35
ทางลัดสำหรับการช่วยเหลือพิเศษ
สำหรับอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไป ผู้ใช้สามารถเปิดใช้ และ ปิดใช้บริการการช่วยเหลือพิเศษที่ต้องการจากหน้าจอใดก็ได้โดยกดและ กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มพร้อมกัน แม้ว่าทางลัดนี้จะเปิดใช้และ จะปิดใช้ TalkBack โดยค่าเริ่มต้น ผู้ใช้สามารถกำหนดค่าปุ่มเพื่อเปิดใช้และ ปิดใช้บริการทั้งหมดที่ติดตั้งในอุปกรณ์
เพื่อให้ผู้ใช้เข้าถึงบริการการช่วยเหลือพิเศษบางอย่างได้จากการช่วยเหลือพิเศษ บริการจะต้องขอฟีเจอร์ขณะรันไทม์
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 13:25
ปุ่มการช่วยเหลือพิเศษ
ในอุปกรณ์ที่ใช้พื้นที่การนำทางที่แสดงผลด้วยซอฟต์แวร์และใช้ Android 8.0 (API ระดับ 26) ขึ้นไป ที่ด้านขวาของแถบนำทางจะมีองค์ประกอบ ปุ่มการช่วยเหลือพิเศษ เมื่อกดปุ่มนี้ ผู้ใช้จะเรียกใช้รายการใดรายการหนึ่ง ฟีเจอร์และบริการการช่วยเหลือพิเศษที่เปิดใช้หลายรายการ ขึ้นอยู่กับเนื้อหา ที่กำลังแสดงอยู่บนหน้าจอ
เพื่อให้ผู้ใช้เรียกใช้บริการการช่วยเหลือพิเศษโดยใช้การช่วยเหลือพิเศษ
บริการต้องเพิ่ม
FLAG_REQUEST_ACCESSIBILITY_BUTTON
ธงในandroid:accessibilityFlags
ของออบเจ็กต์ AccessibilityServiceInfo
จากนั้น บริการจะสามารถลงทะเบียน Callback โดยใช้
registerAccessibilityButtonCallback()
ข้อมูลโค้ดต่อไปนี้แสดงวิธีกำหนดค่าการช่วยเหลือพิเศษ เพื่อตอบสนองผู้ใช้ที่กดปุ่มการช่วยเหลือพิเศษ:
Kotlin
private var mAccessibilityButtonController: AccessibilityButtonController? = null private var accessibilityButtonCallback: AccessibilityButtonController.AccessibilityButtonCallback? = null private var mIsAccessibilityButtonAvailable: Boolean = false override fun onServiceConnected() { mAccessibilityButtonController = accessibilityButtonController mIsAccessibilityButtonAvailable = mAccessibilityButtonController?.isAccessibilityButtonAvailable ?: false if (!mIsAccessibilityButtonAvailable) return serviceInfo = serviceInfo.apply { flags = flags or AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON } accessibilityButtonCallback = object : AccessibilityButtonController.AccessibilityButtonCallback() { override fun onClicked(controller: AccessibilityButtonController) { Log.d("MY_APP_TAG", "Accessibility button pressed!") // Add custom logic for a service to react to the // accessibility button being pressed. } override fun onAvailabilityChanged( controller: AccessibilityButtonController, available: Boolean ) { if (controller == mAccessibilityButtonController) { mIsAccessibilityButtonAvailable = available } } } accessibilityButtonCallback?.also { mAccessibilityButtonController?.registerAccessibilityButtonCallback(it, null) } }
Java
private AccessibilityButtonController accessibilityButtonController; private AccessibilityButtonController .AccessibilityButtonCallback accessibilityButtonCallback; private boolean mIsAccessibilityButtonAvailable; @Override protected void onServiceConnected() { accessibilityButtonController = getAccessibilityButtonController(); mIsAccessibilityButtonAvailable = accessibilityButtonController.isAccessibilityButtonAvailable(); if (!mIsAccessibilityButtonAvailable) { return; } AccessibilityServiceInfo serviceInfo = getServiceInfo(); serviceInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; setServiceInfo(serviceInfo); accessibilityButtonCallback = new AccessibilityButtonController.AccessibilityButtonCallback() { @Override public void onClicked(AccessibilityButtonController controller) { Log.d("MY_APP_TAG", "Accessibility button pressed!"); // Add custom logic for a service to react to the // accessibility button being pressed. } @Override public void onAvailabilityChanged( AccessibilityButtonController controller, boolean available) { if (controller.equals(accessibilityButtonController)) { mIsAccessibilityButtonAvailable = available; } } }; if (accessibilityButtonCallback != null) { accessibilityButtonController.registerAccessibilityButtonCallback( accessibilityButtonCallback, null); } }
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 16:28
ท่าทางสัมผัสลายนิ้วมือ
บริการช่วยเหลือพิเศษในอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไป สามารถตอบสนองต่อการปัดตามทิศทาง (ขึ้น ลง ซ้าย และขวา) ตามแนวของอุปกรณ์ เซ็นเซอร์ลายนิ้วมือ ในการกำหนดค่าบริการเพื่อรับ Callback เกี่ยวกับ การโต้ตอบ ให้กรอกลำดับต่อไปนี้
- ประกาศ
USE_BIOMETRIC
และCAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES
แบบพื้นฐาน - ตั้งค่า
FLAG_REQUEST_FINGERPRINT_GESTURES
แฟล็กภายในแอตทริบิวต์android:accessibilityFlags
- ลงทะเบียนสำหรับการติดต่อกลับโดยใช้
registerFingerprintGestureCallback()
โปรดทราบว่าบางอุปกรณ์อาจไม่มีเซ็นเซอร์ลายนิ้วมือ เพื่อระบุ
อุปกรณ์รองรับเซ็นเซอร์หรือไม่ ให้ใช้
isHardwareDetected()
แม้ในอุปกรณ์ที่มีเซ็นเซอร์ลายนิ้วมือ บริการของคุณก็ไม่สามารถ
ใช้เซ็นเซอร์เมื่อใช้เพื่อตรวจสอบสิทธิ์ เพื่อระบุว่าเมื่อใด
เซ็นเซอร์พร้อมใช้งาน เรียกใช้
isGestureDetectionAvailable()
และนำเมตริก
onGestureDetectionAvailabilityChanged()
Callback
ข้อมูลโค้ดต่อไปนี้แสดงตัวอย่างของการใช้ท่าทางสัมผัสลายนิ้วมือเพื่อ ไปยังส่วนต่างๆ ของกระดานเกมเสมือนจริง
// AndroidManifest.xml <manifest ... > <uses-permission android:name="android.permission.USE_FINGERPRINT" /> ... <application> <service android:name="com.example.MyFingerprintGestureService" ... > <meta-data android:name="android.accessibilityservice" android:resource="@xml/myfingerprintgestureservice" /> </service> </application> </manifest>
// myfingerprintgestureservice.xml <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" ... android:accessibilityFlags=" ... |flagRequestFingerprintGestures" android:canRequestFingerprintGestures="true" ... />
Kotlin
// MyFingerprintGestureService.kt import android.accessibilityservice.FingerprintGestureController.* class MyFingerprintGestureService : AccessibilityService() { private var gestureController: FingerprintGestureController? = null private var fingerprintGestureCallback: FingerprintGestureController.FingerprintGestureCallback? = null private var mIsGestureDetectionAvailable: Boolean = false override fun onCreate() { gestureController = fingerprintGestureController mIsGestureDetectionAvailable = gestureController?.isGestureDetectionAvailable ?: false } override fun onServiceConnected() { if (mFingerprintGestureCallback != null || !mIsGestureDetectionAvailable) return fingerprintGestureCallback = object : FingerprintGestureController.FingerprintGestureCallback() { override fun onGestureDetected(gesture: Int) { when (gesture) { FINGERPRINT_GESTURE_SWIPE_DOWN -> moveGameCursorDown() FINGERPRINT_GESTURE_SWIPE_LEFT -> moveGameCursorLeft() FINGERPRINT_GESTURE_SWIPE_RIGHT -> moveGameCursorRight() FINGERPRINT_GESTURE_SWIPE_UP -> moveGameCursorUp() else -> Log.e(MY_APP_TAG, "Error: Unknown gesture type detected!") } } override fun onGestureDetectionAvailabilityChanged(available: Boolean) { mIsGestureDetectionAvailable = available } } fingerprintGestureCallback?.also { gestureController?.registerFingerprintGestureCallback(it, null) } } }
Java
// MyFingerprintGestureService.java import static android.accessibilityservice.FingerprintGestureController.*; public class MyFingerprintGestureService extends AccessibilityService { private FingerprintGestureController gestureController; private FingerprintGestureController .FingerprintGestureCallback fingerprintGestureCallback; private boolean mIsGestureDetectionAvailable; @Override public void onCreate() { gestureController = getFingerprintGestureController(); mIsGestureDetectionAvailable = gestureController.isGestureDetectionAvailable(); } @Override protected void onServiceConnected() { if (fingerprintGestureCallback != null || !mIsGestureDetectionAvailable) { return; } fingerprintGestureCallback = new FingerprintGestureController.FingerprintGestureCallback() { @Override public void onGestureDetected(int gesture) { switch (gesture) { case FINGERPRINT_GESTURE_SWIPE_DOWN: moveGameCursorDown(); break; case FINGERPRINT_GESTURE_SWIPE_LEFT: moveGameCursorLeft(); break; case FINGERPRINT_GESTURE_SWIPE_RIGHT: moveGameCursorRight(); break; case FINGERPRINT_GESTURE_SWIPE_UP: moveGameCursorUp(); break; default: Log.e(MY_APP_TAG, "Error: Unknown gesture type detected!"); break; } } @Override public void onGestureDetectionAvailabilityChanged(boolean available) { mIsGestureDetectionAvailable = available; } }; if (fingerprintGestureCallback != null) { gestureController.registerFingerprintGestureCallback( fingerprintGestureCallback, null); } } }
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 9:03
การอ่านออกเสียงข้อความหลายภาษา
ตั้งแต่ Android 8.0 (API ระดับ 26) ไปจนถึงบริการอ่านออกเสียงข้อความ (TTS) ของ Android
สามารถระบุและพูดวลีในภาษาต่างๆ ภายในบล็อกเดียว
ข้อความ เพื่อเปิดใช้ความสามารถในการเปลี่ยนภาษาอัตโนมัตินี้ในฟีเจอร์การช่วยเหลือพิเศษ
บริการ รวมสตริงทั้งหมดไว้ใน
LocaleSpan
ออบเจ็กต์ตามที่แสดง
ในข้อมูลโค้ดต่อไปนี้
Kotlin
val localeWrappedTextView = findViewById<TextView>(R.id.my_french_greeting_text).apply { text = wrapTextInLocaleSpan("Bonjour!", Locale.FRANCE) } private fun wrapTextInLocaleSpan(originalText: CharSequence, loc: Locale): SpannableStringBuilder { return SpannableStringBuilder(originalText).apply { setSpan(LocaleSpan(loc), 0, originalText.length - 1, 0) } }
Java
TextView localeWrappedTextView = findViewById(R.id.my_french_greeting_text); localeWrappedTextView.setText(wrapTextInLocaleSpan("Bonjour!", Locale.FRANCE)); private SpannableStringBuilder wrapTextInLocaleSpan( CharSequence originalText, Locale loc) { SpannableStringBuilder myLocaleBuilder = new SpannableStringBuilder(originalText); myLocaleBuilder.setSpan(new LocaleSpan(loc), 0, originalText.length() - 1, 0); return myLocaleBuilder; }
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 10:59
ดำเนินการในนามของผู้ใช้
ตั้งแต่ปี 2011 บริการการเข้าถึงสามารถดำเนินการในนามของผู้ใช้ได้ ซึ่งรวมถึง การเปลี่ยนโฟกัสอินพุตและการเลือก (เปิดใช้งาน) องค์ประกอบอินเทอร์เฟซผู้ใช้ ใน ในปี 2012 ได้ขยายช่วงการดําเนินการให้ครอบคลุมรายการแบบเลื่อนและการโต้ตอบ ด้วยช่องข้อความ บริการช่วยเหลือพิเศษยังดำเนินการต่างๆ ได้ทั่วโลก เช่น ไปยังหน้าจอหลัก กดปุ่มย้อนกลับ และเปิด หน้าจอการแจ้งเตือนและรายการแอปล่าสุด ตั้งแต่ปี 2012 เป็นต้นมา Android มี โฟกัสการช่วยเหลือพิเศษ ซึ่งทำให้เลือกองค์ประกอบที่มองเห็นได้ทั้งหมดด้วย บริการการช่วยเหลือพิเศษ
ความสามารถเหล่านี้ช่วยให้นักพัฒนาบริการการช่วยเหลือพิเศษสร้างทางเลือก โหมดการไปยังส่วนต่างๆ เช่น การนำทางด้วยท่าทางสัมผัส และให้ผู้ใช้ที่มีความพิการ ที่ปรับปรุงการควบคุมอุปกรณ์ที่ใช้ Android
ฟังท่าทางสัมผัส
บริการการช่วยเหลือพิเศษจะฟังท่าทางสัมผัสที่เจาะจงและตอบสนองได้โดยการดำเนินการตาม
แทนผู้ใช้ คุณต้องส่งคำขอบริการการช่วยเหลือพิเศษเพื่อใช้ฟีเจอร์นี้
การเปิดใช้งานฟีเจอร์สำรวจด้วยการแตะ บริการของคุณสามารถขอข้อมูลนี้ได้
การเปิดใช้งานได้โดยการตั้งค่า
flags
สมาชิกของอินสแตนซ์ AccessibilityServiceInfo
ของบริการให้กับ
FLAG_REQUEST_TOUCH_EXPLORATION_MODE
,
ดังที่ปรากฏในตัวอย่างต่อไปนี้
Kotlin
class MyAccessibilityService : AccessibilityService() { override fun onCreate() { serviceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE } ... }
Java
public class MyAccessibilityService extends AccessibilityService { @Override public void onCreate() { getServiceInfo().flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; } ... }
หลังจากบริการของคุณขอเปิดใช้งานการสำรวจด้วยการแตะ ผู้ใช้ต้องอนุญาต
ฟีเจอร์จะเปิดขึ้นหากยังไม่ได้ใช้งานอยู่ เมื่อฟีเจอร์นี้
ทำงานอยู่ บริการของคุณจะได้รับการแจ้งเตือนเกี่ยวกับท่าทางสัมผัสการช่วยเหลือพิเศษผ่าน
onGesture()
เมธอด Callback และสามารถตอบกลับโดยการดำเนินการในนามของผู้ใช้
ท่าทางสัมผัสต่อ
อุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) รองรับท่าทางสัมผัสอย่างต่อเนื่อง หรือ
ท่าทางสัมผัสแบบเป็นโปรแกรมที่มีมากกว่า 1 ท่าทางสัมผัส
Path
เมื่อระบุลำดับของเส้นโครงร่าง คุณสามารถระบุได้ว่าเส้นโครงร่างเป็นของ
ท่าทางสัมผัสแบบเป็นโปรแกรมเดียวกันโดยใช้อาร์กิวเมนต์สุดท้าย willContinue
ใน
GestureDescription.StrokeDescription
เครื่องมือสร้าง ตามที่ปรากฏในข้อมูลโค้ดต่อไปนี้
Kotlin
// Simulates an L-shaped drag path: 200 pixels right, then 200 pixels down. private fun doRightThenDownDrag() { val dragRightPath = Path().apply { moveTo(200f, 200f) lineTo(400f, 200f) } val dragRightDuration = 500L // 0.5 second // The starting point of the second path must match // the ending point of the first path. val dragDownPath = Path().apply { moveTo(400f, 200f) lineTo(400f, 400f) } val dragDownDuration = 500L val rightThenDownDrag = GestureDescription.StrokeDescription( dragRightPath, 0L, dragRightDuration, true ).apply { continueStroke(dragDownPath, dragRightDuration, dragDownDuration, false) } }
Java
// Simulates an L-shaped drag path: 200 pixels right, then 200 pixels down. private void doRightThenDownDrag() { Path dragRightPath = new Path(); dragRightPath.moveTo(200, 200); dragRightPath.lineTo(400, 200); long dragRightDuration = 500L; // 0.5 second // The starting point of the second path must match // the ending point of the first path. Path dragDownPath = new Path(); dragDownPath.moveTo(400, 200); dragDownPath.lineTo(400, 400); long dragDownDuration = 500L; GestureDescription.StrokeDescription rightThenDownDrag = new GestureDescription.StrokeDescription(dragRightPath, 0L, dragRightDuration, true); rightThenDownDrag.continueStroke(dragDownPath, dragRightDuration, dragDownDuration, false); }
สำหรับข้อมูลเพิ่มเติม โปรดดูวิดีโอเซสชันมีอะไรใหม่ในการช่วยเหลือพิเศษของ Android จาก Google I/O 2017 โดยเริ่มตั้งแต่ 15:47
ใช้การดำเนินการช่วยเหลือพิเศษ
บริการการช่วยเหลือพิเศษสามารถดำเนินการในนามของผู้ใช้เพื่อลดความซับซ้อนในการโต้ตอบกับ และทำงานได้อย่างมีประสิทธิภาพมากขึ้น ความสามารถของบริการการช่วยเหลือพิเศษเพื่อ มีการดำเนินการเพิ่มขึ้นในปี 2011 และเพิ่มขึ้นอย่างมากในปี 2012
ในการดำเนินการในนามของผู้ใช้ บริการการช่วยเหลือพิเศษของคุณต้องลงทะเบียน
เพื่อรับกิจกรรมจากแอปและขอสิทธิ์ดูเนื้อหา
โดยการตั้งค่า android:canRetrieveWindowContent
เป็น true
ในส่วน
ไฟล์การกำหนดค่าบริการ เมื่อกิจกรรมของคุณได้รับเหตุการณ์
บริการ โมเดลก็สามารถเรียก
AccessibilityNodeInfo
จากเหตุการณ์โดยใช้
getSource()
เมื่อใช้ออบเจ็กต์ AccessibilityNodeInfo
บริการจะสำรวจมุมมองได้
ลำดับชั้นในการพิจารณาว่าควรดำเนินการใด แล้วดำเนินการแทนผู้ใช้โดยใช้
performAction()
Kotlin
class MyAccessibilityService : AccessibilityService() { override fun onAccessibilityEvent(event: AccessibilityEvent) { // Get the source node of the event. event.source?.apply { // Use the event and node information to determine what action to // take. // Act on behalf of the user. performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) // Recycle the nodeInfo object. recycle() } } ... }
Java
public class MyAccessibilityService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { // Get the source node of the event. AccessibilityNodeInfo nodeInfo = event.getSource(); // Use the event and node information to determine what action to take. // Act on behalf of the user. nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD); // Recycle the nodeInfo object. nodeInfo.recycle(); } ... }
เมธอด performAction()
ช่วยให้บริการดำเนินการภายใน
แอป หากบริการของคุณจำเป็นต้องดำเนินการส่วนกลาง เช่น
การไปยังหน้าจอหลัก แตะปุ่มย้อนกลับ หรือเปิด
หน้าจอการแจ้งเตือนหรือรายการแอปล่าสุด ให้ใช้
performGlobalAction()
ใช้ประเภทโฟกัส
ในปี 2012 Android ได้เปิดตัวโฟกัสของอินเทอร์เฟซผู้ใช้ที่เรียกว่าโฟกัสการช่วยเหลือพิเศษ บริการการช่วยเหลือพิเศษสามารถใช้การโฟกัสนี้เพื่อเลือกอินเทอร์เฟซผู้ใช้ที่มองเห็นได้ องค์ประกอบและดำเนินการกับสิ่งนั้น การโฟกัสประเภทนี้แตกต่างจากโฟกัสอินพุตซึ่ง กำหนดองค์ประกอบอินเทอร์เฟซผู้ใช้บนหน้าจอที่จะได้รับข้อมูลเมื่อผู้ใช้ พิมพ์อักขระ กด Enter บนแป้นพิมพ์ หรือกดตรงกลาง ของ D-pad
องค์ประกอบหนึ่งๆ ในอินเทอร์เฟซผู้ใช้จะโฟกัสการป้อนข้อมูลได้ในขณะที่ อีกองค์ประกอบหนึ่งมีโฟกัสการช่วยเหลือพิเศษ วัตถุประสงค์ของการมุ่งเน้นการช่วยเหลือพิเศษคือ เพื่อให้บริการการช่วยเหลือพิเศษโดยมีวิธีโต้ตอบกับ องค์ประกอบบนหน้าจอ โดยไม่คำนึงว่าองค์ประกอบนั้นสามารถโฟกัสข้อมูลจาก เกี่ยวกับมุมมองของระบบ เพื่อช่วยตรวจสอบว่าบริการการช่วยเหลือพิเศษของคุณโต้ตอบ ได้อย่างถูกต้อง องค์ประกอบอินพุตต่างๆ ให้ปฏิบัติตามหลักเกณฑ์ในการทดสอบ การช่วยเหลือพิเศษเพื่อทดสอบบริการของคุณ ขณะใช้แอปทั่วไป
บริการการช่วยเหลือพิเศษระบุได้ว่าองค์ประกอบอินเทอร์เฟซผู้ใช้ใดมีข้อมูล
โฟกัสหรือการช่วยเหลือพิเศษโดยใช้
AccessibilityNodeInfo.findFocus()
คุณยังค้นหาองค์ประกอบที่สามารถเลือกโดยโฟกัสการป้อนข้อมูลได้ด้วย
โดยใช้
focusSearch()
สุดท้าย บริการการช่วยเหลือพิเศษสามารถตั้งค่าโฟกัสการช่วยเหลือพิเศษโดยใช้
เวลา
performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS)
รวบรวมข้อมูล
บริการการช่วยเหลือพิเศษมีวิธีมาตรฐานในการรวบรวมและแสดงคีย์ หน่วยข้อมูลที่ได้จากผู้ใช้ เช่น รายละเอียดเหตุการณ์ ข้อความ และตัวเลข
ดูรายละเอียดการเปลี่ยนแปลงหน้าต่าง
Android 9 (API ระดับ 28) ขึ้นไปจะช่วยให้แอปติดตามการอัปเดตกรอบเวลาได้ในกรณีที่
แอปหนึ่งวาดหน้าต่างหลายหน้าต่างซ้ำพร้อมกัน เมื่อ
TYPE_WINDOWS_CHANGED
เกิดเหตุการณ์ ให้ใช้
getWindowChanges()
API เพื่อกำหนดการเปลี่ยนแปลงของหน้าต่าง ในระหว่างการอัปเดตหลายหน้าต่าง
จะสร้างชุดเหตุการณ์ของตัวเอง เมธอด getSource()
จะแสดงรูท
หน้าต่างที่เชื่อมโยงกับแต่ละเหตุการณ์
หากแอปกำหนดแผงการช่วยเหลือพิเศษ
ชื่อ
ออบเจ็กต์ View
บริการของคุณจะรับรู้ได้เมื่อ
อัปเดต UI ของแอปแล้ว เมื่อ
TYPE_WINDOW_STATE_CHANGED
เกิดเหตุการณ์ ให้ใช้ประเภทที่แสดงผลตาม
getContentChangeTypes()
เพื่อดูว่าหน้าต่างจะเปลี่ยนแปลงไปอย่างไร เช่น เฟรมเวิร์กจะตรวจหาว่า
แผงมีชื่อใหม่หรือเมื่อแผงหายไป
ดูรายละเอียดกิจกรรม
Android ให้ข้อมูลแก่บริการการช่วยเหลือพิเศษเกี่ยวกับอินเทอร์เฟซผู้ใช้
การโต้ตอบผ่านออบเจ็กต์ AccessibilityEvent
รายการ ใน Android เวอร์ชันก่อนหน้า
ข้อมูลที่มีอยู่ในเหตุการณ์การช่วยเหลือพิเศษ ในขณะเดียวกันก็ให้
รายละเอียดเกี่ยวกับการควบคุมอินเทอร์เฟซผู้ใช้ที่ผู้ใช้เลือก เสนอแบบจำกัด
ข้อมูลบริบท ในหลายกรณี ข้อมูลบริบทที่ขาดหายไป
สำคัญอย่างยิ่งต่อการทำความเข้าใจความหมายของตัวควบคุมที่เลือก
ตัวอย่างอินเทอร์เฟซที่บริบทเป็นสิ่งสําคัญคือปฏิทินหรือวัน เครื่องมือวางแผนประสิทธิภาพ หากผู้ใช้เลือกช่วงเวลา 16:00 น. ในรายการวันจันทร์ถึงศุกร์ และบริการการช่วยเหลือพิเศษประกาศว่า "16:00 น." แต่ไม่ได้ประกาศวันธรรมดา วันของเดือน หรือชื่อเดือน ความคิดเห็นที่ได้คือ ทำให้เกิดความสับสน ในกรณีนี้ บริบทของการควบคุมอินเทอร์เฟซผู้ใช้จะมีความสำคัญอย่างยิ่ง ผู้ใช้ที่ต้องการกำหนดเวลาการประชุม
ตั้งแต่ปี 2011 เป็นต้นมา Android ได้ขยายขอบเขตของข้อมูลที่ บริการการช่วยเหลือพิเศษสามารถรับข้อมูลเกี่ยวกับการโต้ตอบกับอินเทอร์เฟซผู้ใช้ได้โดยการเขียน เหตุการณ์การช่วยเหลือพิเศษตามลำดับชั้นการดู ลำดับชั้นการดูคือชุดของ คอมโพเนนต์อินเทอร์เฟซผู้ใช้ที่มีคอมโพเนนต์ (คอมโพเนนต์หลัก) และผู้ใช้ องค์ประกอบของอินเทอร์เฟซที่อาจอยู่ภายในคอมโพเนนต์นั้น (องค์ประกอบย่อย) ใน ด้วยวิธีนี้ Android จะสามารถแสดงรายละเอียดเกี่ยวกับกิจกรรมการเข้าถึงที่ครบถ้วนยิ่งขึ้น ซึ่งช่วยให้ บริการการช่วยเหลือพิเศษจะให้ความคิดเห็นที่เป็นประโยชน์มากขึ้นแก่ผู้ใช้
บริการการช่วยเหลือพิเศษจะได้รับข้อมูลเกี่ยวกับเหตุการณ์อินเทอร์เฟซผู้ใช้ผ่าน
AccessibilityEvent
ที่ระบบส่งไปยังบริการของ
เมธอด Callback onAccessibilityEvent()
รายการ ออบเจ็กต์นี้ให้รายละเอียดเกี่ยวกับ
รวมถึงประเภทของออบเจ็กต์ที่มีการดำเนินการ ข้อความอธิบาย และ
รายละเอียดอื่นๆ
AccessibilityEvent.getRecordCount()
และgetRecord(int)
: วิธีการเหล่านี้จะช่วยให้คุณสามารถดึงชุดAccessibilityRecord
ที่มีส่วนให้ข้อมูลAccessibilityEvent
ที่ส่งให้คุณโดย ระบบ รายละเอียดระดับนี้จะให้บริบทเพิ่มเติมเกี่ยวกับเหตุการณ์ที่ เรียกใช้บริการการช่วยเหลือพิเศษAccessibilityRecord.getSource()
: เมธอดนี้จะแสดงผลออบเจ็กต์AccessibilityNodeInfo
ออบเจ็กต์นี้ช่วยให้คุณ ขอลำดับชั้นเลย์เอาต์การดู (หลักและย่อย) ของคอมโพเนนต์ที่ จะเริ่มต้นเหตุการณ์การช่วยเหลือพิเศษ ฟีเจอร์นี้ช่วยให้การช่วยเหลือพิเศษ จะตรวจสอบบริบททั้งหมดของกิจกรรม รวมถึงเนื้อหาและ สถานะของมุมมองใดๆ ที่แนบมาหรือการดูของเด็ก
แพลตฟอร์ม Android ช่วยให้ AccessibilityService
ทำการค้นหาได้
ลำดับชั้นการดู โดยรวบรวมข้อมูลเกี่ยวกับคอมโพเนนต์ UI ที่สร้าง
รวมถึงผู้ปกครองและบุตรหลาน โดยให้กำหนดบรรทัดต่อไปนี้
ในการกำหนดค่า XML ของคุณ:
android:canRetrieveWindowContent="true"
เมื่อเสร็จแล้ว รับออบเจ็กต์ AccessibilityNodeInfo
โดยใช้ getSource()
การเรียกนี้จะส่งคืนอ็อบเจกต์ก็ต่อเมื่อหน้าต่างที่เกิดเหตุการณ์เกิดขึ้นคือ
จะยังคงเป็นหน้าต่างที่ใช้งานอยู่ หากไม่ จะแสดงเป็นค่า Null ดังนั้นโปรดดำเนินการตามความเหมาะสม
ในตัวอย่างต่อไปนี้ โค้ดจะดำเนินการต่อไปนี้เมื่อได้รับเหตุการณ์
- ดึงมุมมองระดับบนสุดของตำแหน่งที่เกิดเหตุการณ์ขึ้นทันที
- ในมุมมองดังกล่าว ให้มองหาป้ายกำกับและช่องทำเครื่องหมายเมื่อเป็นมุมมองย่อย
- หากพบเจอผู้ใช้ ให้สร้างสตริงที่จะรายงานไปยังผู้ใช้ ซึ่งระบุถึง ว่ามีการตรวจสอบหรือไม่
หากมีการส่งคืนค่าว่าง ณ จุดใดก็ตามขณะข้ามลำดับชั้นการแสดงผล แต่วิธีนี้ก็ยอมแพ้อย่างเงียบๆ
Kotlin
// Alternative onAccessibilityEvent that uses AccessibilityNodeInfo. override fun onAccessibilityEvent(event: AccessibilityEvent) { val source: AccessibilityNodeInfo = event.source ?: return // Grab the parent of the view that fires the event. val rowNode: AccessibilityNodeInfo = getListItemNodeInfo(source) ?: return // Using this parent, get references to both child nodes, the label, and the // checkbox. val taskLabel: CharSequence = rowNode.getChild(0)?.text ?: run { rowNode.recycle() return } val isComplete: Boolean = rowNode.getChild(1)?.isChecked ?: run { rowNode.recycle() return } // Determine what the task is and whether it's complete based on the text // inside the label, and the state of the checkbox. if (rowNode.childCount < 2 || !rowNode.getChild(1).isCheckable) { rowNode.recycle() return } val completeStr: String = if (isComplete) { getString(R.string.checked) } else { getString(R.string.not_checked) } val reportStr = "$taskLabel$completeStr" speakToUser(reportStr) }
Java
// Alternative onAccessibilityEvent that uses AccessibilityNodeInfo. @Override public void onAccessibilityEvent(AccessibilityEvent event) { AccessibilityNodeInfo source = event.getSource(); if (source == null) { return; } // Grab the parent of the view that fires the event. AccessibilityNodeInfo rowNode = getListItemNodeInfo(source); if (rowNode == null) { return; } // Using this parent, get references to both child nodes, the label, and the // checkbox. AccessibilityNodeInfo labelNode = rowNode.getChild(0); if (labelNode == null) { rowNode.recycle(); return; } AccessibilityNodeInfo completeNode = rowNode.getChild(1); if (completeNode == null) { rowNode.recycle(); return; } // Determine what the task is and whether it's complete based on the text // inside the label, and the state of the checkbox. if (rowNode.getChildCount() < 2 || !rowNode.getChild(1).isCheckable()) { rowNode.recycle(); return; } CharSequence taskLabel = labelNode.getText(); final boolean isComplete = completeNode.isChecked(); String completeStr = null; if (isComplete) { completeStr = getString(R.string.checked); } else { completeStr = getString(R.string.not_checked); } String reportStr = taskLabel + completeStr; speakToUser(reportStr); }
ตอนนี้คุณมีบริการการช่วยเหลือพิเศษที่ใช้งานได้เต็มรูปแบบแล้ว ลองกำหนดค่าวิธี
แอปโต้ตอบกับผู้ใช้ด้วยการเพิ่มการอ่านออกเสียงข้อความ" ของ Android
เครื่องมือ
หรือใช้ Vibrator
เพื่อการตอบสนองแบบรู้สึกได้
ความคิดเห็น
ประมวลผลข้อความ
อุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไปจะมีส่วนประกอบหลายอย่าง การประมวลผลข้อความ ซึ่งช่วยให้บริการ การเข้าถึงต่างๆ ทำได้ง่ายขึ้น ระบุและดำเนินการในหน่วยข้อความเฉพาะที่ปรากฏบนหน้าจอ
เคล็ดลับเครื่องมือ
Android 9 (API ระดับ 28) มาพร้อมกับความสามารถหลายอย่างที่ช่วยให้คุณเข้าถึง
เคล็ดลับเครื่องมือใน UI ของแอป ใช้
getTooltipText()
เพื่ออ่านข้อความของเคล็ดลับเครื่องมือ และใช้
ACTION_SHOW_TOOLTIP
และ
ACTION_HIDE_TOOLTIP
เพื่อสั่งให้อินสแตนซ์ View
แสดงหรือซ่อนเคล็ดลับเครื่องมือ
ข้อความคำใบ้
ตั้งแต่ปี 2017 เป็นต้นไป Android มีวิธีโต้ตอบกับ ข้อความแนะนำของออบเจ็กต์แบบข้อความ:
-
isShowingHintText()
และsetShowingHintText()
ระบุและตั้งค่าตามลำดับว่าข้อความปัจจุบันของโหนดหรือไม่ content จะแสดงข้อความแนะนำของโหนด getHintText()
ให้การเข้าถึงข้อความแนะนำ แม้ว่าวัตถุจะไม่แสดง ข้อความบอกใบ้ การเรียกgetHintText()
สำเร็จแล้ว
ตำแหน่งของอักขระบนหน้าจอ
สำหรับอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไป บริการการช่วยเหลือพิเศษ
สามารถระบุพิกัดหน้าจอสำหรับกรอบล้อมรอบของอักขระที่ปรากฏแต่ละตัว
ภายในวิดเจ็ต TextView
บริการต่างๆ
ค้นหาพิกัดเหล่านี้ได้โดยโทร
refreshWithExtraData()
กำลังผ่านใน
EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
เป็นอาร์กิวเมนต์แรกและออบเจ็กต์ Bundle
เป็นอาร์กิวเมนต์ที่ 2 ขณะที่เมธอดดำเนินการ ระบบจะป้อนข้อมูล
อาร์กิวเมนต์ Bundle
ที่มีอาร์เรย์แบบพาร์เซลของ
ออบเจ็กต์ Rect
รายการ ออบเจ็กต์ Rect
แต่ละรายการ
หมายถึงกรอบล้อมรอบของอักขระหนึ่งๆ
ค่าของช่วงด้านเดียวที่เป็นมาตรฐาน
ออบเจ็กต์ AccessibilityNodeInfo
บางรายการใช้อินสแตนซ์ของ
AccessibilityNodeInfo.RangeInfo
เพื่อระบุว่าองค์ประกอบ UI สามารถรับช่วงของค่าได้ เมื่อสร้าง
ช่วงโดยใช้
RangeInfo.obtain()
หรือเมื่อดึงค่าที่สูงมากของช่วงโดยใช้
getMin()
และ
getMax()
,
โปรดทราบว่าอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) ขึ้นไป
ช่วงด้านเดียวในลักษณะมาตรฐาน:
- สำหรับช่วงที่ไม่มีค่าขั้นต่ำ
Float.NEGATIVE_INFINITY
แสดงถึงค่าต่ำสุด - สำหรับช่วงที่ไม่มีขีดจำกัดสูงสุด
Float.POSITIVE_INFINITY
แสดงค่าสูงสุด
ตอบกลับกิจกรรมการช่วยเหลือพิเศษ
เมื่อตั้งค่าบริการเพื่อเรียกใช้และรอเหตุการณ์แล้ว ให้เขียนโค้ดเพื่อเขียน
รู้ว่าต้องทำอะไรเมื่อ AccessibilityEvent
มาถึง เริ่มต้นด้วยการลบล้าง
onAccessibilityEvent(AccessibilityEvent)
ในวิธีการดังกล่าว ให้ใช้
getEventType()
เพื่อกำหนดประเภทของเหตุการณ์และ
getContentDescription()
เพื่อดึงข้อความป้ายกํากับที่เชื่อมโยงกับมุมมองที่ทําให้เหตุการณ์เริ่มทํางาน
Kotlin
override fun onAccessibilityEvent(event: AccessibilityEvent) { var eventText: String = when (event.eventType) { AccessibilityEvent.TYPE_VIEW_CLICKED -> "Clicked: " AccessibilityEvent.TYPE_VIEW_FOCUSED -> "Focused: " else -> "" } eventText += event.contentDescription // Do something nifty with this text, like speak the composed string back to // the user. speakToUser(eventText) ... }
Java
@Override public void onAccessibilityEvent(AccessibilityEvent event) { final int eventType = event.getEventType(); String eventText = null; switch(eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: eventText = "Clicked: "; break; case AccessibilityEvent.TYPE_VIEW_FOCUSED: eventText = "Focused: "; break; } eventText = eventText + event.getContentDescription(); // Do something nifty with this text, like speak the composed string back to // the user. speakToUser(eventText); ... }
แหล่งข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมได้ในแหล่งข้อมูลต่อไปนี้