API ของ Android 4.4

ระดับ API: 19

Android 4.4 (KITKAT) เป็นเวอร์ชันใหม่สำหรับแพลตฟอร์ม Android ที่มาพร้อมฟีเจอร์ใหม่ๆ สำหรับผู้ใช้และนักพัฒนาแอป เอกสารนี้จะแนะนำ API ใหม่ที่โดดเด่นที่สุด

ในฐานะนักพัฒนาแอป คุณควรดาวน์โหลดภาพระบบ Android 4.4 และแพลตฟอร์ม SDK จาก SDK Manager โดยเร็วที่สุด หากไม่มีอุปกรณ์ที่ใช้ Android 4.4 ในการทดสอบแอป ให้ใช้ภาพระบบ Android 4.4 เพื่อทดสอบแอปในโปรแกรมจำลอง Android จากนั้นสร้างแอปสำหรับแพลตฟอร์ม Android 4.4 เพื่อเริ่มใช้ API เวอร์ชันล่าสุด

อัปเดตระดับ API เป้าหมาย

หากต้องการเพิ่มประสิทธิภาพแอปสำหรับอุปกรณ์ที่ใช้ Android 4.4 ให้ดีขึ้น คุณควรตั้งค่า targetSdkVersion เป็น "19" ติดตั้งในภาพระบบ Android 4.4 ทดสอบ แล้วเผยแพร่การอัปเดตที่มีการเปลี่ยนแปลงนี้

คุณสามารถใช้ API ใน Android 4.4 ไปพร้อมกับรองรับเวอร์ชันเก่าได้ด้วยการเพิ่มเงื่อนไขลงในโค้ดที่ตรวจสอบระดับ API ของระบบก่อนที่จะเรียกใช้ API ที่ minSdkVersion ไม่รองรับ ดูข้อมูลเพิ่มเติมเกี่ยวกับการคงความเข้ากันได้ย้อนหลังได้ที่การรองรับเวอร์ชันแพลตฟอร์มที่แตกต่างกัน

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของระดับ API ได้ที่ระดับ API คืออะไร

การเปลี่ยนแปลงที่สำคัญเกี่ยวกับลักษณะการทำงาน

หากคุณเคยเผยแพร่แอปสำหรับ Android โปรดทราบว่าแอปอาจได้รับผลกระทบจากการเปลี่ยนแปลงใน Android 4.4

หากแอปอ่านจากที่จัดเก็บข้อมูลภายนอก...

แอปของคุณจะอ่านไฟล์ที่แชร์ในที่จัดเก็บข้อมูลภายนอกไม่ได้เมื่อทำงานบน Android 4.4 เว้นแต่ว่าแอปจะมีสิทธิ์ READ_EXTERNAL_STORAGE กล่าวคือ ไฟล์ภายในไดเรกทอรีที่ getExternalStoragePublicDirectory() แสดงผลจะเข้าถึงไม่ได้อีกต่อไปหากไม่มีสิทธิ์ อย่างไรก็ตาม หากต้องการเข้าถึงเฉพาะไดเรกทอรีเฉพาะแอปที่ getExternalFilesDir() ระบุไว้ คุณไม่จำเป็นต้องมีสิทธิ์ READ_EXTERNAL_STORAGE

หากแอปใช้ WebView

แอปอาจทำงานแตกต่างจากปกติเมื่อทำงานบน Android 4.4 โดยเฉพาะอย่างยิ่งเมื่อคุณอัปเดต targetSdkVersion ของแอปเป็น "19" ขึ้นไป

โค้ดที่อยู่เบื้องหลังคลาส WebView และ API ที่เกี่ยวข้องได้รับการอัปเกรดให้อิงตามสแนปชอตล่าสุดของซอร์สโค้ด Chromium ซึ่งจะนำมาซึ่งการปรับปรุงประสิทธิภาพที่หลากหลาย รองรับฟีเจอร์ HTML5 ใหม่ และรองรับการแก้ไขข้อบกพร่องจากระยะไกลของเนื้อหา WebView ขอบเขตของการอัปเกรดนี้หมายความว่าหากแอปของคุณใช้ WebView ลักษณะการทํางานของแอปอาจได้รับผลกระทบในบางกรณี แม้ว่าจะมีบันทึกการเปลี่ยนแปลงลักษณะการทำงานที่ทราบและส่วนใหญ่จะส่งผลต่อแอปของคุณก็ต่อเมื่อคุณอัปเดต targetSdkVersion ของแอปเป็น "19" ขึ้นไป แต่ WebView เวอร์ชันใหม่จะทำงานใน "โหมดการทำงานพิเศษ" เพื่อมอบฟังก์ชันการทำงานเดิมบางส่วนในแอปที่กำหนดเป้าหมายเป็น API ระดับ 18 และต่ำกว่า เป็นไปได้ว่าแอปของคุณอาจใช้ลักษณะการทำงานที่ไม่รู้จักจาก WebView เวอร์ชันก่อนหน้า

ดังนั้นหากแอปที่มีอยู่ใช้ WebView คุณควรทดสอบบน Android 4.4 โดยเร็วที่สุดและดูข้อมูลเกี่ยวกับผลกระทบที่อาจเกิดขึ้นกับแอปเมื่อคุณอัปเดต targetSdkVersion เป็น "19" ขึ้นไปในการย้ายข้อมูลไปยัง WebView ใน Android 4.4

หากแอปใช้ AlarmManager

เมื่อคุณตั้งค่า targetSdkVersion ของแอปเป็น "19" ขึ้นไป การปลุกที่คุณสร้างโดยใช้ set() หรือ setRepeating() จะมีความคลาดเคลื่อน

ตอนนี้ Android จะรวมการปลุกจากแอปทั้งหมดที่เกิดขึ้นในช่วงเวลาใกล้เคียงกันไว้ในกลุ่มเดียวกันเพื่อปรับปรุงประสิทธิภาพการใช้พลังงาน ระบบจึงจะปลุกอุปกรณ์เพียงครั้งเดียวแทนที่จะปลุกหลายครั้งเพื่อจัดการการปลุกแต่ละรายการ

หากการปลุกไม่ได้เชื่อมโยงกับเวลาของนาฬิกาที่แน่นอน แต่ยังคงต้องการให้ระบบเรียกใช้การปลุกในช่วงที่เจาะจง (เช่น ระหว่างเวลา 14:00 น. - 16:00 น.) คุณก็ใช้เมธอด setWindow() ใหม่ได้ ซึ่งจะยอมรับเวลา "เร็วที่สุด" สำหรับการปลุกและ "กรอบเวลา" หลังจากเวลาเร็วที่สุดที่ระบบควรเรียกใช้การปลุก

หากการปลุกต้องปักหมุดไว้กับเวลาของนาฬิกาที่แน่นอน (เช่น สำหรับการช่วยเตือนกิจกรรมในปฏิทิน) คุณจะใช้เมธอด setExact() ใหม่ได้

ลักษณะการรวมกลุ่มที่ไม่แน่นอนนี้มีผลกับแอปที่อัปเดตแล้วเท่านั้น หากคุณตั้งค่า targetSdkVersion เป็น "18" หรือต่ำกว่า ระบบจะยังคงตั้งปลุกตามลักษณะการทำงานในเวอร์ชันก่อนหน้าเมื่อใช้ Android 4.4

หากแอปซิงค์ข้อมูลโดยใช้ ContentResolver

เมื่อคุณตั้งค่า targetSdkVersion ของแอปเป็น "19" ขึ้นไป การสร้างการซิงค์ด้วย addPeriodicSync() จะดำเนินการซิงค์ภายในช่วงเวลาแบบยืดหยุ่นเริ่มต้นประมาณ 4% ของระยะเวลาที่คุณระบุ ตัวอย่างเช่น หากความถี่ในการสำรวจคือ 24 ชั่วโมง การดำเนินการซิงค์อาจเกิดขึ้นภายในกรอบเวลาประมาณ 1 ชั่วโมงในแต่ละวันแทนที่จะดำเนินการในเวลาเดียวกันทุกวัน

หากต้องการระบุช่วงเวลาที่ยืดหยุ่นของคุณเองสําหรับการดำเนินการซิงค์ คุณควรเริ่มใช้เมธอด requestSync() ใหม่ โปรดดูรายละเอียดเพิ่มเติมในส่วนด้านล่างเกี่ยวกับอะแดปเตอร์การซิงค์

ลักษณะการทำงานของช่วงเวลาแบบยืดหยุ่นนี้มีผลกับแอปที่อัปเดตแล้วเท่านั้น หากคุณตั้งค่า targetSdkVersion เป็น "18" หรือต่ำกว่า คำขอซิงค์ที่มีอยู่จะยังคงทำงานเหมือนเดิมในเวอร์ชันก่อนหน้าเมื่อใช้ Android 4.4

เฟรมเวิร์กการพิมพ์

ตอนนี้ Android มีเฟรมเวิร์กครบถ้วนที่ช่วยให้ผู้ใช้พิมพ์เอกสารใดก็ได้โดยใช้เครื่องพิมพ์ที่เชื่อมต่อผ่าน Wi-Fi, บลูทูธ หรือบริการอื่นๆ ระบบจะจัดการธุรกรรมระหว่างแอปที่ต้องการพิมพ์เอกสารกับบริการที่ส่งงานพิมพ์ไปยังเครื่องพิมพ์ เฟรมเวิร์ก android.print มี API ทั้งหมดที่จำเป็นในการระบุเอกสารที่จะพิมพ์และส่งไปยังระบบเพื่อพิมพ์ API ที่คุณต้องใช้จริงสำหรับงานพิมพ์หนึ่งๆ จะขึ้นอยู่กับเนื้อหาของคุณ

การพิมพ์เนื้อหาทั่วไป

หากต้องการพิมพ์เนื้อหาจาก UI เป็นเอกสาร คุณจะต้องสร้างคลาสย่อยของ PrintDocumentAdapter ก่อน ในคลาสนี้ คุณต้องติดตั้งใช้งานเมธอดการเรียกกลับ 2-3 เมธอด ซึ่งรวมถึง onLayout() เพื่อกำหนดเลย์เอาต์ตามพร็อพเพอร์ตี้การพิมพ์ที่ระบุ และ onWrite() เพื่อจัดรูปแบบเนื้อหาที่พิมพ์ได้ให้เป็น ParcelFileDescriptor

หากต้องการเขียนเนื้อหาลงใน ParcelFileDescriptor คุณต้องส่งไฟล์ PDF PdfDocument API ใหม่นำเสนอวิธีที่สะดวกในการทำเช่นนี้โดยระบุ Canvas จาก getCanvas() ซึ่งคุณสามารถวาดเนื้อหาที่พิมพ์ได้ จากนั้นเขียน PdfDocument ไปยัง ParcelFileDescriptor โดยใช้วิธีการ writeTo()

เมื่อกำหนดการใช้งานสำหรับ PrintDocumentAdapter แล้ว คุณจะดำเนินการพิมพ์ตามคำขอของผู้ใช้ได้โดยใช้เมธอด PrintManager print() ซึ่งใช้ PrintDocumentAdapter เป็นอาร์กิวเมนต์รายการใดรายการหนึ่ง

การพิมพ์รูปภาพ

หากต้องการพิมพ์เฉพาะรูปภาพหรือบิตแมปอื่นๆ API ตัวช่วยในไลบรารีสนับสนุนจะทํางานทั้งหมดให้คุณ เพียงสร้างอินสแตนซ์ใหม่ของ PrintHelper ตั้งค่าโหมดการปรับขนาดด้วย setScaleMode() แล้วส่ง Bitmap ไปยัง printBitmap() เท่านี้เอง ไลบรารีจะจัดการการโต้ตอบที่เหลือทั้งหมดกับระบบเพื่อส่งบิตแมปไปยังเครื่องพิมพ์

บริการพิมพ์สำหรับอาคาร

ในฐานะ OEM ของเครื่องพิมพ์ คุณสามารถใช้เฟรมเวิร์ก android.printservice เพื่อมอบความสามารถในการทำงานร่วมกันกับเครื่องพิมพ์จากอุปกรณ์ Android คุณสามารถสร้างและเผยแพร่บริการพิมพ์เป็น APK ซึ่งผู้ใช้จะติดตั้งลงในอุปกรณ์ได้ แอปบริการพิมพ์จะทํางานเป็นหลักในฐานะบริการแบบไม่มีส่วนหัวโดยการแยกคลาสย่อยของคลาส PrintService ซึ่งจะรับงานพิมพ์จากระบบและสื่อสารงานกับเครื่องพิมพ์โดยใช้โปรโตคอลที่เหมาะสม

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีพิมพ์เนื้อหาแอปได้ที่การพิมพ์เนื้อหา

ผู้ให้บริการ SMS

ผู้ให้บริการเนื้อหา Telephony ("ผู้ให้บริการ SMS") อนุญาตให้แอปอ่านและเขียนข้อความ SMS และ MMS ในอุปกรณ์ ซึ่งรวมถึงตารางสำหรับข้อความ SMS และ MMS ที่ได้รับ ร่าง ส่ง รอดำเนินการ และอื่นๆ

ตั้งแต่ Android 4.4 การตั้งค่าระบบอนุญาตให้ผู้ใช้เลือก "แอปรับส่ง SMS เริ่มต้น" เมื่อเลือกแล้ว จะมีเพียงแอป SMS เริ่มต้นเท่านั้นที่เขียนไปยังผู้ให้บริการ SMS และจะมีเพียงแอป SMS เริ่มต้นเท่านั้นที่รับการออกอากาศ SMS_DELIVER_ACTION เมื่อผู้ใช้ได้รับ SMS หรือรับการออกอากาศ WAP_PUSH_DELIVER_ACTION เมื่อผู้ใช้ได้รับ MMS แอป SMS เริ่มต้นมีหน้าที่เขียนรายละเอียดไปยังผู้ให้บริการ SMS เมื่อได้รับหรือส่งข้อความใหม่

แอปอื่นๆ ที่ไม่ได้เลือกเป็นแอป SMS เริ่มต้นจะอ่านได้เฉพาะผู้ให้บริการ SMS แต่อาจได้รับการแจ้งเตือนเมื่อ SMS ใหม่มาถึงด้วยการฟังการออกอากาศ SMS_RECEIVED_ACTION ซึ่งเป็นการออกอากาศที่หยุดกลางคันไม่ได้ซึ่งอาจส่งไปยังแอปหลายแอป การออกอากาศนี้มีไว้สำหรับแอปที่แม้จะไม่ได้เลือกเป็นแอป SMS เริ่มต้น แต่จำเป็นต้องอ่านข้อความขาเข้าพิเศษ เช่น เพื่อดำเนินการยืนยันหมายเลขโทรศัพท์

อ่านข้อมูลเพิ่มเติมได้ในบล็อกโพสต์การเตรียมแอป SMS ให้พร้อมใช้งานกับ KitKat

การเชื่อมต่อไร้สาย

การจําลองบัตรของโฮสต์

ตอนนี้แอป Android สามารถจําลองการ์ด NFC ISO14443-4 (ISO-DEP) ที่ใช้ APDU เพื่อแลกเปลี่ยนข้อมูลได้แล้ว (ตามที่ระบุไว้ใน ISO7816-4) ซึ่งจะช่วยให้อุปกรณ์ที่เปิดใช้ NFC ที่ใช้ Android 4.4 สามารถจําลองบัตร NFC หลายใบพร้อมกัน และช่วยให้เครื่องชำระเงิน NFC หรือเครื่องอ่าน NFC อื่นๆ เริ่มธุรกรรมด้วยบัตร NFC ที่เหมาะสมตามตัวระบุแอปพลิเคชัน (AID) ได้

หากต้องการจําลองการ์ด NFC ที่ใช้โปรโตคอลเหล่านี้ในแอป ให้สร้างคอมโพเนนต์บริการตามคลาส HostApduService แต่หากแอปใช้องค์ประกอบที่ปลอดภัยสำหรับการจําลองบัตรแทน คุณจะต้องสร้างบริการตามคลาส OffHostApduService ซึ่งจะไม่เกี่ยวข้องกับธุรกรรมโดยตรง แต่จําเป็นต้องลงทะเบียน AID ที่ควรจัดการโดยองค์ประกอบที่ปลอดภัย

อ่านข้อมูลเพิ่มเติมได้ที่คู่มือการจําลองบัตร NFC

โหมดเครื่องอ่าน NFC

โหมดเครื่องอ่าน NFC ใหม่ช่วยให้กิจกรรมจำกัดกิจกรรม NFC ทั้งหมดให้อ่านเฉพาะประเภทแท็กที่กิจกรรมสนใจขณะที่ทำงานอยู่เบื้องหน้า คุณสามารถเปิดใช้โหมดผู้อ่านสําหรับกิจกรรมด้วย enableReaderMode() โดยระบุการใช้งาน NfcAdapter.ReaderCallback ที่จะได้รับการเรียกกลับเมื่อตรวจพบแท็กใหม่

ความสามารถใหม่นี้เมื่อใช้ร่วมกับการจําลองบัตรโฮสต์จะช่วยให้ Android ทํางานได้ทั้งสองฝั่งของอินเทอร์เฟซการชําระเงินผ่านอุปกรณ์เคลื่อนที่ โดยอุปกรณ์หนึ่งทํางานเป็นเครื่องชำระเงิน (อุปกรณ์ที่ทํางานในโหมดเครื่องอ่าน) และอีกอุปกรณ์หนึ่งทํางานเป็นไคลเอ็นต์การชําระเงิน (อุปกรณ์ที่จําลองบัตร NFC)

เครื่องส่งสัญญาณอินฟราเรด

เมื่อใช้งานในอุปกรณ์ที่มีเครื่องส่งสัญญาณอินฟราเรด (IR) ตอนนี้คุณสามารถส่งสัญญาณ IR โดยใช้ ConsumerIrManager API หากต้องการรับอินสแตนซ์ของ ConsumerIrManager ให้เรียกใช้ getSystemService() โดยมี CONSUMER_IR_SERVICE เป็นอาร์กิวเมนต์ จากนั้นคุณสามารถค้นหาความถี่ IR ที่อุปกรณ์รองรับด้วย getCarrierFrequencies() และส่งสัญญาณโดยส่งความถี่และรูปแบบสัญญาณที่ต้องการด้วย transmit()

คุณควรตรวจสอบก่อนเสมอว่าอุปกรณ์มีเครื่องส่ง IR หรือไม่โดยเรียกใช้ hasIrEmitter() แต่หากแอปของคุณเข้ากันได้เฉพาะกับอุปกรณ์ที่มีเครื่องส่ง IR คุณควรใส่องค์ประกอบ <uses-feature> ในไฟล์ Manifest สำหรับ "android.hardware.consumerir" (FEATURE_CONSUMER_IR)

มัลติมีเดีย

การเล่นแบบปรับอัตโนมัติ

ตอนนี้ MediaCodec API พร้อมรองรับการเล่นวิดีโอแบบปรับเปลี่ยนได้ ซึ่งช่วยให้เปลี่ยนความละเอียดได้อย่างราบรื่นระหว่างการเล่นบน Surface โดยคุณสามารถป้อนเฟรมอินพุตของโปรแกรมถอดรหัสที่มีความละเอียดใหม่ และความละเอียดของบัฟเฟอร์เอาต์พุตจะเปลี่ยนไปโดยแทบไม่ขาดตอน

คุณเปิดใช้การเล่นแบบปรับเปลี่ยนได้โดยการเพิ่มคีย์ 2 รายการลงใน MediaFormat ซึ่งระบุความละเอียดสูงสุดที่แอปของคุณต้องการจากตัวแปลงรหัส ได้แก่ KEY_MAX_WIDTH และ KEY_MAX_HEIGHT เมื่อเพิ่มรายการเหล่านี้ลงใน MediaFormat แล้ว ให้ส่ง MediaFormat ไปยังอินสแตนซ์ MediaCodec ด้วย configure()

โปรแกรมเปลี่ยนรหัสจะเปลี่ยนความละเอียดระหว่างความละเอียดที่เท่ากับหรือน้อยกว่าค่าเหล่านี้อย่างราบรื่น นอกจากนี้ โปรแกรมเปลี่ยนไฟล์ยังอาจรองรับความละเอียดที่มากกว่าความละเอียดสูงสุดที่ระบุ (ตราบใดที่ความละเอียดนั้นไม่เกินขีดจำกัดของโปรไฟล์ที่รองรับ) แต่การเปลี่ยนไปใช้ความละเอียดที่สูงขึ้นอาจไม่ราบรื่น

หากต้องการเปลี่ยนความละเอียดขณะถอดรหัสวิดีโอ H.264 ให้จัดคิวเฟรมต่อไปโดยใช้ MediaCodec.queueInputBuffer() แต่ตรวจสอบว่าคุณได้ระบุค่าชุดพารามิเตอร์ลำดับ (SPS) และชุดพารามิเตอร์รูปภาพ (PPS) ใหม่พร้อมกับเฟรมการรีเฟรชตัวถอดรหัสทันที (IDR) ในบัฟเฟอร์เดียว

อย่างไรก็ตาม ก่อนที่จะพยายามกำหนดค่าตัวแปลงรหัสสำหรับการเล่นแบบปรับเปลี่ยนได้ คุณต้องยืนยันว่าอุปกรณ์รองรับการเล่นแบบปรับเปลี่ยนได้โดยการเรียกใช้ isFeatureSupported(String) ด้วย FEATURE_AdaptivePlayback

หมายเหตุ: การรองรับการเล่นแบบปรับเปลี่ยนจะแตกต่างกันไปตามผู้ให้บริการ โปรแกรมเปลี่ยนไฟล์บางประเภทอาจต้องใช้หน่วยความจำมากขึ้นสำหรับคำแนะนำความละเอียดที่สูงขึ้น ดังนั้น คุณควรตั้งค่าความละเอียดสูงสุดตามเนื้อหาต้นทางที่คุณกำลังถอดรหัส

การประทับเวลาของเสียงแบบออนดีมานด์

คลาส AudioTimestamp ใหม่จะแสดงรายละเอียดไทม์ไลน์เกี่ยวกับ "เฟรม" ที่เฉพาะเจาะจงในสตรีมเสียงที่ AudioTrack จัดการ เพื่อให้ซิงค์เสียงและวิดีโอได้ง่ายขึ้น หากต้องการรับการประทับเวลาล่าสุดที่มีอยู่ ให้สร้างอินสแตนซ์ออบเจ็กต์ AudioTimestamp แล้วส่งไปยัง getTimestamp() หากคําขอการประทับเวลาสําเร็จ ระบบจะกรอกอินสแตนซ์ AudioTrack ด้วยตําแหน่งในหน่วยเฟรม พร้อมกับเวลาโดยประมาณที่เฟรมนั้นแสดงหรือจะแสดง

คุณสามารถใช้ค่าของ nanoTime ใน AudioTimestamp (ซึ่งเป็นค่าที่เพิ่มขึ้นเรื่อยๆ) เพื่อค้นหาเฟรมวิดีโอที่เกี่ยวข้องซึ่งใกล้เคียงที่สุดเมื่อเทียบกับ framePosition เพื่อให้คุณวาง คัดลอก หรือหาค่าเฉลี่ยระหว่างเฟรมวิดีโอเพื่อจับคู่กับเสียงได้ หรือจะกำหนดเวลาเดลต้าระหว่างค่า nanoTime กับเวลาที่คาดไว้ของเฟรมวิดีโอในอนาคต (โดยพิจารณาจากอัตราตัวอย่าง) เพื่อคาดการณ์เฟรมเสียงที่คาดว่าจะเล่นพร้อมกันกับเฟรมวิดีโอก็ได้

เครื่องอ่านรูปภาพบนพื้นผิว

ImageReader API ใหม่ช่วยให้คุณเข้าถึงบัฟเฟอร์รูปภาพได้โดยตรงเมื่อมีการเรนเดอร์เป็น Surface คุณรับ ImageReader ได้ด้วยเมธอดแบบคงที่ newInstance() จากนั้นเรียกใช้ getSurface() เพื่อสร้าง Surface ใหม่และส่งข้อมูลรูปภาพด้วยโปรแกรมสร้าง เช่น MediaPlayer หรือ MediaCodec หากต้องการรับการแจ้งเตือนเมื่อมีรูปภาพใหม่จากแพลตฟอร์ม ให้ใช้อินเทอร์เฟซ ImageReader.OnImageAvailableListener และลงทะเบียนกับ setOnImageAvailableListener()

เมื่อคุณวาดเนื้อหาลงใน Surface ขณะนี้ ImageReader.OnImageAvailableListener จะได้รับคอลไปยัง onImageAvailable() เมื่อเฟรมรูปภาพใหม่แต่ละเฟรมพร้อมใช้งาน ซึ่งจะแสดง ImageReader ที่เกี่ยวข้อง คุณสามารถใช้ ImageReader เพื่อรับข้อมูลรูปภาพของเฟรมเป็นออบเจ็กต์ Image ได้โดยเรียกใช้ acquireLatestImage() หรือ acquireNextImage()

ออบเจ็กต์ Image ให้สิทธิ์เข้าถึงการประทับเวลา รูปแบบ ขนาด และข้อมูลพิกเซลของรูปภาพโดยตรงใน ByteBuffer อย่างไรก็ตาม รูปภาพต้องอยู่ในรูปแบบตามประเภทใดประเภทหนึ่งที่กำหนดโดยค่าคงที่ใน ImageFormat หรือ PixelFormat เพื่อให้คลาส Image ตีความรูปภาพได้

การวัดค่าสูงสุดและ RMS

ตอนนี้คุณสามารถค้นหาค่าสูงสุดและ RMS ของสตรีมเสียงปัจจุบันจาก Visualizer ได้โดยการสร้างอินสแตนซ์ใหม่ของ Visualizer.MeasurementPeakRms และส่งไปยัง getMeasurementPeakRms() เมื่อคุณเรียกใช้เมธอดนี้ ระบบจะตั้งค่าค่าสูงสุดและ RMS ของ Visualizer.MeasurementPeakRms ที่ระบุเป็นค่าที่วัดล่าสุด

ตัวเพิ่มระดับเสียง

LoudnessEnhancer เป็นคลาสย่อยใหม่ของ AudioEffect ที่ช่วยให้คุณเพิ่มระดับเสียงที่ได้ยินของ MediaPlayer หรือ AudioTrack ได้ ซึ่งจะมีประโยชน์อย่างยิ่งเมื่อใช้ร่วมกับวิธีการ getMeasurementPeakRms() ใหม่ที่เราได้พูดถึงข้างต้น เพื่อเพิ่มระดับเสียงของแทร็กเสียงที่พูดขณะที่สื่ออื่นๆ กำลังเล่นอยู่

ตัวควบคุมระยะไกล

Android 4.0 (API ระดับ 14) ได้เปิดตัว RemoteControlClient API ที่ช่วยให้แอปสื่อใช้เหตุการณ์ตัวควบคุมสื่อจากไคลเอ็นต์ระยะไกลได้ เช่น การควบคุมสื่อบนหน้าจอล็อก ตอนนี้ RemoteController API ใหม่ช่วยให้คุณสร้างรีโมตคอนโทรลของคุณเองได้ ซึ่งจะเปิดโอกาสให้สร้างแอปและอุปกรณ์ต่อพ่วงใหม่ๆ ที่ล้ำสมัยซึ่งควบคุมการเล่นของแอปสื่อที่ผสานรวมกับ RemoteControlClient ได้

หากต้องการสร้างรีโมตคอนโทรลเลอร์ คุณสามารถใช้อินเทอร์เฟซผู้ใช้ในลักษณะใดก็ได้ที่ต้องการ แต่หากต้องการส่งเหตุการณ์ของปุ่มสื่อไปยังแอปสื่อของผู้ใช้ คุณต้องสร้างบริการที่ขยายคลาส NotificationListenerService และใช้อินเทอร์เฟซ RemoteController.OnClientUpdateListener การใช้ NotificationListenerService เป็นพื้นฐานเป็นสิ่งสําคัญเนื่องจากมีข้อจํากัดด้านความเป็นส่วนตัวที่เหมาะสม ซึ่งกําหนดให้ผู้ใช้ต้องเปิดใช้แอปของคุณเป็นผู้ฟังการแจ้งเตือนในการตั้งค่าความปลอดภัยของระบบ

คลาส NotificationListenerService มีเมธอดนามธรรม 2 รายการที่คุณต้องติดตั้งใช้งาน แต่หากคุณสนใจเฉพาะเหตุการณ์ตัวควบคุมสื่อเพื่อจัดการการเล่นสื่อ ก็ปล่อยการติดตั้งใช้งานสำหรับเหตุการณ์เหล่านั้นว่างไว้ แล้วมุ่งเน้นที่เมธอด RemoteController.OnClientUpdateListener แทน

การให้คะแนนจากรีโมตคอนโทรล

Android 4.4 พัฒนาความสามารถที่มีอยู่สำหรับไคลเอ็นต์รีโมตคอนโทรล (แอปที่รับเหตุการณ์การควบคุมสื่อด้วย RemoteControlClient) โดยเพิ่มความสามารถในการให้คะแนนแทร็กปัจจุบันจากรีโมตคอนโทรล

คลาส Rating ใหม่จะรวมข้อมูลเกี่ยวกับคะแนนของผู้ใช้ การจัดประเภทจะกำหนดโดยรูปแบบการจัดประเภท (RATING_HEART, RATING_THUMB_UP_DOWN, RATING_3_STARS, RATING_4_STARS, RATING_5_STARS หรือ RATING_PERCENTAGE) และค่าการจัดประเภทที่เหมาะสมกับรูปแบบนั้น

วิธีอนุญาตให้ผู้ใช้ให้คะแนนแทร็กจากรีโมตคอนโทรล

หากต้องการรับการเรียกกลับเมื่อผู้ใช้เปลี่ยนการจัดประเภทจากรีโมตคอนโทรล ให้ใช้อินเทอร์เฟซ RemoteControlClient.OnMetadataUpdateListener ใหม่และส่งอินสแตนซ์ไปยัง setMetadataUpdateListener() เมื่อผู้ใช้เปลี่ยนการจัดประเภท RemoteControlClient.OnMetadataUpdateListener ของคุณจะได้รับคําเรียก onMetadataUpdate() โดยส่ง RATING_KEY_BY_USER เป็นคีย์และออบเจ็กต์ Rating เป็นค่า

คำบรรยาย

VideoView รองรับแทร็กคำบรรยาย WebVTT เมื่อเล่นวิดีโอ HTTP Live Stream (HLS) แล้ว โดยจะแสดงแทร็กคำบรรยายตามค่ากำหนดคำบรรยายแทนเสียงที่ผู้ใช้กำหนดไว้ในการตั้งค่าระบบ

นอกจากนี้ คุณยังระบุแทร็กคำบรรยาย WebVTT ให้กับ VideoView โดยใช้เมธอด addSubtitleSource() ได้ด้วย เมธอดนี้จะยอมรับ InputStream ที่มีข้อมูลคำบรรยายและออบเจ็กต์ MediaFormat ที่ระบุรูปแบบสำหรับข้อมูลคำบรรยาย ซึ่งคุณระบุได้โดยใช้ createSubtitleFormat() คำบรรยายเหล่านี้จะปรากฏเหนือวิดีโอตามค่ากำหนดของผู้ใช้ด้วย

หากคุณไม่ได้ใช้ VideoView เพื่อแสดงเนื้อหาวิดีโอ คุณควรทำให้คำบรรยายแทนเสียงที่วางซ้อนตรงกับค่ากำหนดคำบรรยายแทนเสียงของผู้ใช้มากที่สุด CaptioningManager API ใหม่ช่วยให้คุณค้นหาค่ากำหนดคำบรรยายแทนเสียงของผู้ใช้ รวมถึงรูปแบบที่ CaptioningManager.CaptionStyle กำหนด เช่น แบบตัวพิมพ์และสี ในกรณีที่ผู้ใช้ปรับค่ากําหนดบางอย่างเมื่อวิดีโอเล่นไปแล้ว คุณควรรอฟังการเปลี่ยนแปลงค่ากําหนดโดยการลงทะเบียนอินสแตนซ์ของ CaptioningManager.CaptioningChangeListener เพื่อรับการเรียกกลับเมื่อมีการเปลี่ยนแปลงค่ากําหนด จากนั้นอัปเดตคำบรรยายตามที่จำเป็น

ภาพเคลื่อนไหวและกราฟิก

ฉากและทรานซิชัน

เฟรมเวิร์ก android.transition ใหม่มี API ที่อำนวยความสะดวกในการสร้างภาพเคลื่อนไหวระหว่างสถานะต่างๆ ของอินเทอร์เฟซผู้ใช้ ฟีเจอร์หลักคือความสามารถในการกำหนดสถานะที่แตกต่างกันของ UI หรือที่เรียกว่า "ฉาก" โดยการสร้างเลย์เอาต์แยกกันสำหรับแต่ละสถานะ เมื่อต้องการแสดงภาพเคลื่อนไหวจากฉากหนึ่งไปยังอีกฉากหนึ่ง ให้ใช้ "ทรานซิชัน" ซึ่งจะคำนวณภาพเคลื่อนไหวที่จำเป็นเพื่อเปลี่ยนเลย์เอาต์จากฉากปัจจุบันไปยังฉากถัดไป

โดยทั่วไปแล้ว หากต้องการเปลี่ยนระหว่าง 2 ฉาก คุณจะต้องดำเนินการต่อไปนี้

  1. ระบุ ViewGroup ที่มีคอมโพเนนต์ UI ที่ต้องการเปลี่ยน
  2. ระบุเลย์เอาต์ที่แสดงผลลัพธ์สุดท้ายของการเปลี่ยนแปลง (ฉากถัดไป)
  3. ระบุประเภทการเปลี่ยนที่ควรแสดงภาพเคลื่อนไหวการเปลี่ยนแปลงเลย์เอาต์
  4. ดำเนินการเปลี่ยน

คุณใช้ออบเจ็กต์ Scene เพื่อทําขั้นตอนที่ 1 และ 2 ได้ Scene มีข้อมูลเมตาที่อธิบายพร็อพเพอร์ตี้ของเลย์เอาต์ที่จําเป็นสําหรับการเปลี่ยนฉาก ซึ่งรวมถึงมุมมองหลักของฉากและเลย์เอาต์ของฉาก คุณสามารถสร้าง Scene โดยใช้ตัวสร้างคลาสหรือเมธอดแบบคงที่ getSceneForLayout()

จากนั้นให้ใช้ TransitionManager เพื่อทําขั้นตอนที่ 3 และ 4 วิธีหนึ่งคือส่ง Scene ไปยังเมธอดแบบคงที่ go() ซึ่งจะค้นหามุมมองหลักของฉากในเลย์เอาต์ปัจจุบันและทำการทรานซิชันในมุมมองย่อยเพื่อไปยังเลย์เอาต์ที่ Scene กำหนด

หรือคุณจะไม่ต้องสร้างออบเจ็กต์ Scene เลยก็ได้ แต่เรียกใช้ beginDelayedTransition() แทน โดยระบุ ViewGroup ที่มีมุมมองที่ต้องการเปลี่ยน จากนั้นเพิ่ม นําออก หรือกําหนดค่ามุมมองเป้าหมายใหม่ หลังจากระบบแสดงการเปลี่ยนแปลงตามที่จำเป็นแล้ว ทรานซิชันจะเริ่มแสดงภาพเคลื่อนไหวของมุมมองทั้งหมดที่ได้รับผลกระทบ

หากต้องการการควบคุมเพิ่มเติม คุณสามารถกำหนดชุดทรานซิชันที่ควรเกิดขึ้นระหว่างฉากที่กําหนดไว้ล่วงหน้าได้โดยใช้ไฟล์ XML ในไดเรกทอรี res/transition/ ของโปรเจ็กต์ ภายในองค์ประกอบ <transitionManager> ให้ระบุแท็ก <transition> อย่างน้อย 1 รายการที่ระบุฉาก (การอ้างอิงไฟล์เลย์เอาต์) และทรานซิชันที่จะใช้เมื่อเข้าสู่และ/หรือออกจากฉากนั้น จากนั้นขยายชุดทรานซิชันนี้โดยใช้ inflateTransitionManager() ใช้ TransitionManager ที่แสดงผลเพื่อเรียกใช้การเปลี่ยนแต่ละรายการด้วย transitionTo() โดยส่ง Scene ที่แสดงโดยแท็ก <transition> รายการใดรายการหนึ่ง นอกจากนี้ คุณยังกำหนดชุดทรานซิชันแบบเป็นโปรแกรมด้วย TransitionManager API ได้ด้วย

เมื่อระบุทรานซิชัน คุณจะใช้ประเภทที่กําหนดไว้ล่วงหน้าหลายประเภทซึ่งกําหนดโดยคลาสย่อยของ Transition ได้ เช่น Fade และ ChangeBounds หากคุณไม่ระบุประเภททรานซิชัน ระบบจะใช้ AutoTransition โดยค่าเริ่มต้น ซึ่งจะค่อยๆ จาง ย้าย และปรับขนาดมุมมองโดยอัตโนมัติตามความจำเป็น นอกจากนี้ คุณยังสร้างทรานซิชันที่กำหนดเองได้โดยขยายคลาสใดก็ได้เหล่านี้เพื่อแสดงภาพเคลื่อนไหวตามที่คุณต้องการ การเปลี่ยนที่กำหนดเองสามารถติดตามการเปลี่ยนแปลงพร็อพเพอร์ตี้ที่คุณต้องการ และสร้างภาพเคลื่อนไหวตามการเปลี่ยนแปลงเหล่านั้นได้ เช่น คุณอาจระบุคลาสย่อยของ Transition ที่คอยฟังการเปลี่ยนแปลงพร็อพเพอร์ตี้ "rotation" ของมุมมอง แล้วแสดงภาพการเปลี่ยนแปลงเป็นภาพเคลื่อนไหว

ดูข้อมูลเพิ่มเติมได้ที่เอกสารประกอบของ TransitionManager

การหยุดตัวสร้างภาพเคลื่อนไหวชั่วคราว

ตอนนี้ Animator API ให้คุณหยุดภาพเคลื่อนไหวที่ดำเนินอยู่ชั่วคราวและเล่นต่อได้ด้วยเมธอด pause() และ resume()

หากต้องการติดตามสถานะของภาพเคลื่อนไหว ให้ใช้อินเทอร์เฟซ Animator.AnimatorPauseListener ซึ่งจะให้การเรียกกลับเมื่อภาพเคลื่อนไหวหยุดชั่วคราวและเล่นต่อ pause() และ resume() จากนั้นเพิ่มตัวรับฟังลงในออบเจ็กต์ Animator ด้วย addPauseListener()

หรือจะสร้างคลาสย่อยของคลาสนามธรรม AnimatorListenerAdapter ก็ได้ ซึ่งตอนนี้มีการใช้งานว่างสำหรับคอลแบ็กการหยุดชั่วคราวและดำเนินการต่อที่ Animator.AnimatorPauseListener กำหนดไว้

บิตแมปแบบใช้ซ้ำได้

ตอนนี้คุณสามารถนําบิตแมปที่เปลี่ยนแปลงได้ใน BitmapFactory มาใช้ซ้ำเพื่อถอดรหัสบิตแมปอื่นได้ แม้ว่าบิตแมปใหม่จะมีขนาดต่างกันก็ตาม ตราบใดที่จำนวนไบต์ที่ได้ของบิตแมปที่ถอดรหัสแล้ว (ดูได้จาก getByteCount()) น้อยกว่าหรือเท่ากับจำนวนไบต์ที่จัดสรรของบิตแมปที่ใช้ซ้ำ (ดูได้จาก getAllocationByteCount() ดูข้อมูลเพิ่มเติมได้ที่ inBitmap

API ใหม่สําหรับ Bitmap อนุญาตให้กําหนดค่าใหม่ในลักษณะที่คล้ายกันเพื่อนําไปใช้ซ้ำนอก BitmapFactory (สําหรับการสร้างบิตแมปด้วยตนเองหรือตรรกะการถอดรหัสที่กําหนดเอง) ตอนนี้คุณตั้งค่าขนาดของบิตแมปด้วยเมธอด setHeight() และ setWidth() รวมถึงระบุ Bitmap.Config ใหม่ด้วย setConfig() ได้แล้วโดยไม่ส่งผลต่อการจัดสรรบิตแมปพื้นฐาน นอกจากนี้ วิธี reconfigure() ยังช่วยให้คุณรวมการเปลี่ยนแปลงเหล่านี้ไว้ในการเรียกใช้เพียงครั้งเดียวได้อีกด้วย

อย่างไรก็ตาม คุณไม่ควรกำหนดค่าบิตแมปที่ระบบมุมมองใช้อยู่ในปัจจุบันใหม่ เนื่องจากระบบจะไม่แมปบัฟเฟอร์พิกเซลที่อยู่เบื้องหลังใหม่ในลักษณะที่คาดการณ์ได้

เนื้อหาของผู้ใช้

เฟรมเวิร์กการเข้าถึงพื้นที่เก็บข้อมูล

ใน Android เวอร์ชันก่อนหน้า หากต้องการให้แอปดึงข้อมูลไฟล์บางประเภทจากแอปอื่น แอปจะต้องเรียกใช้ Intent ที่มีการดำเนินการ ACTION_GET_CONTENT การดำเนินการนี้ยังคงเป็นวิธีที่เหมาะในการขอไฟล์ที่ต้องการนำเข้าไปยังแอป อย่างไรก็ตาม Android 4.4 ได้เปิดตัวการดำเนินการ ACTION_OPEN_DOCUMENT ซึ่งช่วยให้ผู้ใช้เลือกไฟล์ประเภทที่ต้องการและอนุญาตให้แอปของคุณมีสิทธิ์อ่านไฟล์นั้นในระยะยาว (อาจมีสิทธิ์เขียนด้วย) โดยไม่ต้องนำเข้าไฟล์ไปยังแอป

หากกำลังพัฒนาแอปที่ให้บริการพื้นที่เก็บข้อมูลสำหรับไฟล์ (เช่น บริการบันทึกในระบบคลาวด์) คุณสามารถเข้าร่วม UI แบบรวมนี้เพื่อเลือกไฟล์ได้โดยการใช้ผู้ให้บริการเนื้อหาเป็นคลาสย่อยของคลาส DocumentsProvider ใหม่ คลาสย่อยของ DocumentsProvider ต้องมีตัวกรอง Intent ที่ยอมรับการดำเนินการ PROVIDER_INTERFACE ("android.content.action.DOCUMENTS_PROVIDER") จากนั้นคุณต้องใช้เมธอดนามธรรม 4 รายการใน DocumentsProvider ดังนี้

queryRoots()
การดำเนินการนี้ต้องแสดงผล Cursor ที่อธิบายไดเรกทอรีรูททั้งหมดของพื้นที่เก็บข้อมูลเอกสารโดยใช้คอลัมน์ที่กําหนดไว้ใน DocumentsContract.Root
queryChildDocuments()
การดำเนินการนี้ต้องแสดงผล Cursor ที่อธิบายไฟล์ทั้งหมดในไดเรกทอรีที่ระบุ โดยใช้คอลัมน์ที่กําหนดไว้ใน DocumentsContract.Document
queryDocument()
การดำเนินการนี้ต้องแสดงผล Cursor ที่อธิบายไฟล์ที่ระบุโดยใช้คอลัมน์ที่กําหนดไว้ใน DocumentsContract.Document
openDocument()
การดำเนินการนี้ต้องแสดงผล ParcelFileDescriptor ที่แสดงไฟล์ที่ระบุ ระบบจะเรียกใช้เมธอดนี้เมื่อผู้ใช้เลือกไฟล์และแอปไคลเอ็นต์ขอสิทธิ์เข้าถึงโดยเรียกใช้ openFileDescriptor()

ดูข้อมูลเพิ่มเติมได้ที่คู่มือเฟรมเวิร์กการเข้าถึงพื้นที่เก็บข้อมูล

การเข้าถึงพื้นที่เก็บข้อมูลภายนอก

ตอนนี้คุณสามารถอ่านและเขียนไฟล์เฉพาะแอปในสื่อจัดเก็บข้อมูลภายนอกรองได้แล้ว เช่น เมื่ออุปกรณ์มีทั้งพื้นที่เก็บข้อมูลจำลองและการ์ด SD เมธอดใหม่ getExternalFilesDirs() ทำงานเหมือนกับเมธอด getExternalFilesDir() ที่มีอยู่ ยกเว้นว่าจะแสดงผลอาร์เรย์ของออบเจ็กต์ File ก่อนที่จะอ่านหรือเขียนไปยังเส้นทางใดๆ ที่เมธอดนี้แสดงผล ให้ส่งออบเจ็กต์ File ไปยังเมธอด getStorageState() ใหม่เพื่อยืนยันว่ามีพื้นที่เก็บข้อมูลในขณะนี้

ตอนนี้วิธีการอื่นๆ ในการเข้าถึงไดเรกทอรีแคชเฉพาะแอปและไดเรกทอรี OBB ก็มีเวอร์ชันที่สอดคล้องกันซึ่งให้สิทธิ์เข้าถึงอุปกรณ์เก็บข้อมูลรองด้วย ได้แก่ getExternalCacheDirs() และ getObbDirs() ตามลำดับ

รายการแรกในอาร์เรย์ File ที่แสดงผลจะถือว่าเป็นพื้นที่เก็บข้อมูลภายนอกหลักของอุปกรณ์ ซึ่งเหมือนกับ File ที่แสดงผลโดยเมธอดที่มีอยู่ เช่น getExternalFilesDir()

หมายเหตุ: ตั้งแต่ Android 4.4 เป็นต้นไป แพลตฟอร์มจะไม่กำหนดให้แอปของคุณต้องขอ WRITE_EXTERNAL_STORAGE หรือ READ_EXTERNAL_STORAGE อีกต่อไปเมื่อคุณต้องการเข้าถึงเฉพาะภูมิภาคของที่จัดเก็บข้อมูลภายนอกสำหรับแอปของคุณโดยใช้วิธีการข้างต้น อย่างไรก็ตาม คุณต้องมีสิทธิ์ดังกล่าวหากต้องการเข้าถึงภูมิภาคที่แชร์ได้ของพื้นที่เก็บข้อมูลภายนอกซึ่ง getExternalStoragePublicDirectory() เป็นผู้จัดหา

อะแดปเตอร์การซิงค์

เมธอด requestSync() ใหม่ใน ContentResolver ช่วยลดขั้นตอนบางอย่างในการกําหนดคําขอซิงค์สําหรับ ContentProvider โดยการรวมคําขอไว้ในออบเจ็กต์ SyncRequest ใหม่ ซึ่งคุณสร้างได้ด้วย SyncRequest.Builder พร็อพเพอร์ตี้ใน SyncRequest มีฟังก์ชันการทำงานเหมือนกับการเรียกใช้การซิงค์ ContentProvider ที่มีอยู่ แต่เพิ่มความสามารถในการระบุว่าควรยกเลิกการซิงค์หากเครือข่ายมีการวัดปริมาณโดยเปิดใช้ setDisallowMetered()

ข้อมูลจากผู้ใช้

เซ็นเซอร์ประเภทใหม่

เซ็นเซอร์ TYPE_GEOMAGNETIC_ROTATION_VECTOR ใหม่จะให้ข้อมูลเวกเตอร์การหมุนตามเครื่องวัดค่าความเข้มข้นของสนามแม่เหล็ก ซึ่งเป็นทางเลือกที่มีประโยชน์สำหรับเซ็นเซอร์ TYPE_ROTATION_VECTOR เมื่อไม่มีเครื่องวัดการหมุน หรือเมื่อใช้กับเหตุการณ์เซ็นเซอร์แบบเป็นกลุ่มเพื่อบันทึกการวางแนวของอุปกรณ์ขณะที่โทรศัพท์อยู่ในโหมดสลีป เซ็นเซอร์นี้ใช้พลังงานน้อยกว่า TYPE_ROTATION_VECTOR แต่อาจเสี่ยงที่จะเกิดข้อมูลเหตุการณ์ที่มีสัญญาณรบกวน และมีประสิทธิภาพสูงสุดเมื่อผู้ใช้อยู่กลางแจ้ง

ตอนนี้ Android ยังรองรับเซ็นเซอร์การนับก้าวในตัวในฮาร์ดแวร์ด้วย

TYPE_STEP_DETECTOR
เซ็นเซอร์นี้จะทริกเกอร์เหตุการณ์ทุกครั้งที่ผู้ใช้ก้าวเดิน เมื่อผู้ใช้ดำเนินการแต่ละขั้นตอน เซ็นเซอร์นี้จะส่งเหตุการณ์ที่มีค่า 1.0 และการประทับเวลาซึ่งระบุเวลาที่เกิดขั้นตอนนั้น
TYPE_STEP_COUNTER
เซ็นเซอร์นี้จะทริกเกอร์เหตุการณ์เมื่อตรวจพบการก้าวแต่ละครั้งด้วย แต่จะให้จํานวนก้าวทั้งหมดที่สะสมตั้งแต่แอปลงทะเบียนเซ็นเซอร์นี้เป็นครั้งแรกแทน

โปรดทราบว่าเซ็นเซอร์แบบ 2 ขั้นตอนเหล่านี้อาจให้ผลลัพธ์ไม่เหมือนกันเสมอไป เหตุการณ์ TYPE_STEP_COUNTER เกิดขึ้นโดยมีความล่าช้าสูงกว่าเหตุการณ์จาก TYPE_STEP_DETECTOR แต่นั่นเป็นเพราะอัลกอริทึม TYPE_STEP_COUNTER ประมวลผลมากกว่าเพื่อกำจัดผลบวกลวง ดังนั้น TYPE_STEP_COUNTER จึงอาจส่งเหตุการณ์ช้ากว่า แต่ผลลัพธ์ก็น่าจะแม่นยำมากขึ้น

เซ็นเซอร์การเดินทั้ง 2 ประเภทขึ้นอยู่กับฮาร์ดแวร์ (Nexus 5 เป็นอุปกรณ์แรกที่รองรับ) คุณจึงควรตรวจสอบความพร้อมใช้งานด้วย hasSystemFeature() โดยใช้ค่าคงที่ FEATURE_SENSOR_STEP_DETECTOR และ FEATURE_SENSOR_STEP_COUNTER

เหตุการณ์เซ็นเซอร์แบบเป็นกลุ่ม

ตอนนี้ SensorManager API ให้คุณระบุความถี่ที่คุณต้องการให้ระบบส่งเหตุการณ์เซ็นเซอร์เป็นกลุ่มไปยังแอปได้แล้ว เพื่อจัดการพลังงานของอุปกรณ์ได้ดียิ่งขึ้น ซึ่งจะไม่ลดจํานวนเหตุการณ์เซ็นเซอร์จริงที่พร้อมใช้งานสําหรับแอปของคุณในระยะเวลาที่กําหนด แต่จะเป็นการเพิ่มความถี่ที่ระบบเรียก SensorEventListener ของคุณด้วยข้อมูลอัปเดตเซ็นเซอร์แทน กล่าวคือ ระบบจะบันทึกเหตุการณ์ทั้งหมดที่เกิดขึ้นในช่วงระยะเวลาหนึ่ง จากนั้นส่งเหตุการณ์เหล่านั้นไปยังแอปของคุณพร้อมกันแทนที่จะส่งเหตุการณ์แต่ละรายการทันทีที่เหตุการณ์เกิดขึ้น

คลาส SensorManager จะเพิ่มเมธอด registerListener() เวอร์ชันใหม่ 2 เวอร์ชันเพื่อให้คุณระบุ "เวลาในการตอบสนองสูงสุดของรายงาน" ได้ พารามิเตอร์ใหม่นี้จะระบุความล่าช้าสูงสุดที่ SensorEventListener จะยอมรับสำหรับการนำส่งเหตุการณ์เซ็นเซอร์ใหม่ ตัวอย่างเช่น หากคุณระบุเวลาในการตอบสนองของกลุ่มเป็น 1 นาที ระบบจะส่งชุดเหตุการณ์ล่าสุดที่จัดกลุ่มเป็นกลุ่มๆ โดยเว้นระยะไม่เกิน 1 นาทีด้วยการเรียกใช้เมธอด onSensorChanged() ติดต่อกัน 1 ครั้งสําหรับแต่ละเหตุการณ์ที่จัดกลุ่ม เหตุการณ์เซ็นเซอร์จะไม่ล่าช้านานกว่าค่าเวลาในการตอบสนองสูงสุดของรายงาน แต่อาจมาถึงเร็วกว่านั้นหากแอปอื่นๆ ขอเวลาในการตอบสนองที่สั้นลงสำหรับเซ็นเซอร์เดียวกัน

อย่างไรก็ตาม โปรดทราบว่าเซ็นเซอร์จะส่งเหตุการณ์แบบเป็นกลุ่มไปยังแอปตามเวลาในการตอบสนองของรายงานเฉพาะในขณะที่ CPU ทำงานอยู่ แม้ว่าเซ็นเซอร์ฮาร์ดแวร์ที่รองรับการจัดกลุ่มจะรวบรวมเหตุการณ์ของเซ็นเซอร์ต่อไปขณะที่ CPU อยู่ในโหมดสลีป แต่จะไม่ปลุก CPU เพื่อส่งเหตุการณ์ที่จัดกลุ่มไปยังแอป เมื่อเซ็นเซอร์หมดหน่วยความจำสำหรับเหตุการณ์แล้ว ก็จะเริ่มทิ้งเหตุการณ์ที่เก่าที่สุดเพื่อบันทึกเหตุการณ์ล่าสุด คุณสามารถหลีกเลี่ยงการสูญเสียเหตุการณ์ได้โดยการปลุกอุปกรณ์ก่อนที่เซ็นเซอร์จะเต็มหน่วยความจำ จากนั้นเรียกใช้ flush() เพื่อบันทึกเหตุการณ์กลุ่มล่าสุด หากต้องการประมาณว่าหน่วยความจำจะเต็มเมื่อใดและควรล้าง ให้เรียก getFifoMaxEventCount() เพื่อรับจำนวนเหตุการณ์เซ็นเซอร์สูงสุดที่หน่วยความจำจะบันทึกได้ แล้วหารด้วยอัตราที่แอปต้องการแต่ละเหตุการณ์ ใช้การคํานวณดังกล่าวเพื่อตั้งการปลุกด้วย AlarmManager ที่เรียกใช้ Service (ซึ่งใช้ SensorEventListener) เพื่อล้างเซ็นเซอร์

หมายเหตุ: อุปกรณ์บางรุ่นไม่รองรับการจัดกลุ่มเหตุการณ์เซ็นเซอร์ เนื่องจากเซ็นเซอร์ฮาร์ดแวร์ต้องรองรับ อย่างไรก็ตาม ตั้งแต่ Android 4.4 เป็นต้นไป คุณควรใช้เมธอด registerListener() ใหม่เสมอ เนื่องจากหากอุปกรณ์ไม่รองรับการรวมกลุ่ม ระบบจะไม่สนใจอาร์กิวเมนต์เวลาในการตอบสนองของกลุ่มและส่งเหตุการณ์เซ็นเซอร์แบบเรียลไทม์

ข้อมูลประจำตัวของผู้ควบคุมข้อมูล

ตอนนี้ Android จะระบุตัวควบคุมที่เชื่อมต่อแต่ละตัวด้วยจำนวนเต็มที่ไม่ซ้ำกันซึ่งคุณค้นหาได้ด้วย getControllerNumber() ซึ่งจะช่วยให้คุณเชื่อมโยงตัวควบคุมแต่ละตัวกับผู้เล่นคนละคนในเกมได้ง่ายขึ้น หมายเลขสำหรับตัวควบคุมแต่ละตัวอาจเปลี่ยนแปลงเนื่องจากผู้ใช้ยกเลิกการเชื่อมต่อ เชื่อมต่อ หรือกำหนดค่าตัวควบคุมใหม่ คุณจึงควรติดตามว่าหมายเลขตัวควบคุมใดสอดคล้องกับอุปกรณ์อินพุตแต่ละเครื่องโดยลงทะเบียนอินสแตนซ์ของ InputManager.InputDeviceListener จากนั้นเรียกใช้ getControllerNumber() สำหรับ InputDevice แต่ละรายการเมื่อมีการเปลี่ยนแปลง

ตอนนี้อุปกรณ์ที่เชื่อมต่อยังระบุรหัสผลิตภัณฑ์และรหัสผู้ให้บริการที่พร้อมใช้งานจาก getProductId() และ getVendorId() ด้วย หากต้องการแก้ไขการแมปแป้นตามชุดแป้นที่ใช้ได้บนอุปกรณ์ คุณสามารถค้นหาอุปกรณ์เพื่อดูว่าแป้นบางแป้นพร้อมใช้งานหรือไม่ด้วย hasKeys(int...)

อินเทอร์เฟซผู้ใช้

โหมดเต็มหน้าจอสมจริง

หากต้องการให้แอปมีเลย์เอาต์ที่เต็มหน้าจอ Flag SYSTEM_UI_FLAG_IMMERSIVE ใหม่สําหรับ setSystemUiVisibility() (เมื่อใช้ร่วมกับ SYSTEM_UI_FLAG_HIDE_NAVIGATION) จะเปิดใช้โหมดเต็มหน้าจอแบบสมจริงใหม่ ขณะที่เปิดใช้โหมดเต็มหน้าจอที่สมจริง กิจกรรมจะยังคงรับเหตุการณ์การสัมผัสทั้งหมด ผู้ใช้สามารถแสดงแถบระบบด้วยการปัดเข้าด้านในบริเวณที่แถบระบบปรากฏตามปกติ ซึ่งจะล้าง Flag SYSTEM_UI_FLAG_HIDE_NAVIGATION (และ Flag SYSTEM_UI_FLAG_FULLSCREEN หากมี) เพื่อให้แถบระบบยังคงปรากฏอยู่ อย่างไรก็ตาม หากต้องการให้แถบระบบซ่อนอีกครั้งหลังจากผ่านไป 2-3 วินาที คุณสามารถใช้ Flag SYSTEM_UI_FLAG_IMMERSIVE_STICKY แทนได้

แถบระบบแบบโปร่งแสง

ตอนนี้คุณสามารถทำให้แถบระบบโปร่งแสงได้บางส่วนด้วยธีมใหม่ Theme.Holo.NoActionBar.TranslucentDecor และ Theme.Holo.Light.NoActionBar.TranslucentDecor การเปิดใช้แถบระบบแบบโปร่งแสงจะทำให้เลย์เอาต์ของคุณแสดงเต็มพื้นที่ด้านหลังแถบระบบ คุณจึงต้องเปิดใช้ fitsSystemWindows สำหรับส่วนของเลย์เอาต์ที่ไม่ควรถูกแถบระบบบดบังด้วย

หากกำลังสร้างธีมที่กำหนดเอง ให้ตั้งค่าธีมใดธีมหนึ่งเป็นธีมหลัก หรือใส่พร็อพเพอร์ตี้สไตล์ windowTranslucentNavigation และ windowTranslucentStatus ไว้ในธีม

Listener การแจ้งเตือนที่ปรับปรุงแล้ว

Android 4.3 เพิ่ม NotificationListenerService API ซึ่งช่วยให้แอปได้รับข้อมูลเกี่ยวกับการแจ้งเตือนใหม่เมื่อระบบโพสต์การแจ้งเตือน ใน Android 4.4 โปรแกรมรับฟังการแจ้งเตือนจะดึงข้อมูลเมตาเพิ่มเติมสำหรับการแจ้งเตือนและรายละเอียดการดำเนินการของการแจ้งเตือนได้ดังนี้

ช่อง Notification.extras ใหม่จะมี Bundle เพื่อส่งข้อมูลเมตาเพิ่มเติมไปยังเครื่องมือสร้างการแจ้งเตือน เช่น EXTRA_TITLE และ EXTRA_PICTURE คลาส Notification.Action ใหม่จะกำหนดลักษณะของการดําเนินการซึ่งแนบมากับการแจ้งเตือน ซึ่งคุณจะดึงข้อมูลได้จากช่อง actions ใหม่

การมิเรอร์ Drawable สำหรับเลย์เอาต์ RTL

ใน Android เวอร์ชันเก่า หากแอปมีรูปภาพที่ควรกลับการวางแนวแนวนอนสำหรับเลย์เอาต์จากขวาไปซ้าย คุณต้องใส่รูปภาพที่กลับด้านในไดเรกทอรีทรัพยากร drawables-ldrtl/ ตอนนี้ระบบจะมิเรอร์รูปภาพให้คุณโดยอัตโนมัติด้วยการเปิดใช้แอตทริบิวต์ autoMirrored ในทรัพยากรที่วาดได้ หรือเรียกใช้ setAutoMirrored() เมื่อเปิดใช้ Drawable จะแสดงกลับด้านโดยอัตโนมัติเมื่อเลย์เอาต์เป็นจากขวาไปซ้าย

การช่วยเหลือพิเศษ

ตอนนี้คลาส View ให้คุณประกาศ "พื้นที่โฆษณาแบบเรียลไทม์" สำหรับส่วนของ UI ที่อัปเดตแบบไดนามิกด้วยเนื้อหาข้อความใหม่ได้แล้ว โดยการเพิ่มแอตทริบิวต์ accessibilityLiveRegion ใหม่ลงในเลย์เอาต์ XML หรือเรียกใช้ setAccessibilityLiveRegion() เช่น หน้าจอการเข้าสู่ระบบที่มีช่องข้อความที่แสดงการแจ้งเตือน "รหัสผ่านไม่ถูกต้อง" ควรทำเครื่องหมายเป็นพื้นที่ที่ใช้งานอยู่เพื่อให้โปรแกรมอ่านหน้าจออ่านออกเสียงข้อความเมื่อข้อความมีการเปลี่ยนแปลง

ตอนนี้แอปที่ให้บริการการช่วยเหลือพิเศษยังเพิ่มประสิทธิภาพด้วย API ใหม่ที่ให้ข้อมูลเกี่ยวกับคอลเล็กชันมุมมอง เช่น มุมมองรายการหรือตารางกริด โดยใช้ AccessibilityNodeInfo.CollectionInfo และ AccessibilityNodeInfo.CollectionItemInfo

สิทธิ์ของแอป

ต่อไปนี้คือสิทธิ์ใหม่ที่แอปของคุณต้องขอด้วยแท็ก <uses-permission> เพื่อใช้ API ใหม่บางรายการ

INSTALL_SHORTCUT
อนุญาตให้แอปพลิเคชันติดตั้งทางลัดใน Launcher
UNINSTALL_SHORTCUT
อนุญาตให้แอปพลิเคชันถอนการติดตั้งทางลัดใน Launcher
TRANSMIT_IR
อนุญาตให้แอปพลิเคชันใช้ตัวส่งสัญญาณอินฟราเรดของอุปกรณ์ (หากมี)

หมายเหตุ: ตั้งแต่ Android 4.4 เป็นต้นไป แพลตฟอร์มจะไม่กำหนดให้แอปของคุณต้องขอ WRITE_EXTERNAL_STORAGE หรือ READ_EXTERNAL_STORAGE อีกต่อไปเมื่อคุณต้องการเข้าถึงพื้นที่เก็บข้อมูลภายนอกเฉพาะแอปโดยใช้วิธีการต่างๆ เช่น getExternalFilesDir() อย่างไรก็ตาม คุณยังคงต้องใช้สิทธิ์หากต้องการเข้าถึงภูมิภาคที่แชร์ได้ของพื้นที่เก็บข้อมูลภายนอกที่ getExternalStoragePublicDirectory() เป็นผู้จัดหา

ฟีเจอร์ของอุปกรณ์

ต่อไปนี้คือฟีเจอร์ใหม่ของอุปกรณ์ที่คุณประกาศได้ด้วยแท็ก <uses-feature> เพื่อประกาศข้อกำหนดของแอปและเปิดใช้การกรองใน Google Play หรือตรวจสอบขณะรันไทม์

FEATURE_CONSUMER_IR
อุปกรณ์สื่อสารกับอุปกรณ์ IR ของผู้บริโภคได้
FEATURE_DEVICE_ADMIN
อุปกรณ์รองรับการบังคับใช้นโยบายด้านอุปกรณ์ผ่านผู้ดูแลระบบอุปกรณ์
FEATURE_NFC_HOST_CARD_EMULATION
อุปกรณ์รองรับการจำลองบัตร NFC แบบโฮสต์
FEATURE_SENSOR_STEP_COUNTER
อุปกรณ์มีตัวนับก้าวแบบฮาร์ดแวร์
FEATURE_SENSOR_STEP_DETECTOR
อุปกรณ์มีตัวตรวจจับการก้าวของฮาร์ดแวร์

ดูรายละเอียดการเปลี่ยนแปลง API ทั้งหมดใน Android 4.4 ได้ที่รายงานความแตกต่างของ API