การเปลี่ยนแปลงลักษณะการทำงานของ Android 8.0

นอกจากฟีเจอร์และความสามารถใหม่ๆ แล้ว Android 8.0 (API ระดับ 26) ยังมีการเปลี่ยนแปลงลักษณะการทำงานของระบบและ API หลายอย่าง เอกสารนี้จะไฮไลต์การเปลี่ยนแปลงที่สำคัญบางอย่างที่คุณควรทำความเข้าใจและพิจารณาในแอป

การเปลี่ยนแปลงส่วนใหญ่เหล่านี้จะมีผลกับแอปทั้งหมด ไม่ว่าจะกำหนดเป้าหมายเป็น Android เวอร์ชันใดก็ตาม อย่างไรก็ตาม การเปลี่ยนแปลงหลายรายการจะส่งผลต่อแอปที่กำหนดเป้าหมายเป็น Android 8.0 เท่านั้น เพื่อความชัดเจนสูงสุด หน้านี้จึงแบ่งออกเป็น 2 ส่วน ได้แก่ การเปลี่ยนแปลงสำหรับแอปทั้งหมดและการเปลี่ยนแปลงสำหรับแอปที่กำหนดเป้าหมายเป็น Android 8.0

การเปลี่ยนแปลงสำหรับแอปทั้งหมด

การเปลี่ยนแปลงลักษณะการทำงานเหล่านี้มีผลกับแอปทั้งหมดเมื่อทำงานบนแพลตฟอร์ม Android 8.0 (API ระดับ 26) โดยไม่คำนึงถึงระดับ API ที่กําหนดเป้าหมาย นักพัฒนาแอปทุกรายควรตรวจสอบการเปลี่ยนแปลงเหล่านี้และแก้ไขแอปให้รองรับการเปลี่ยนแปลงดังกล่าวอย่างเหมาะสม หากแอปมีการเปลี่ยนแปลงดังกล่าว

ขีดจำกัดการดำเนินการในเบื้องหลัง

หนึ่งในการเปลี่ยนแปลงที่ Android 8.0 (ระดับ API 26) นำมาใช้เพื่อปรับปรุงอายุการใช้งานแบตเตอรี่คือ เมื่อแอปของคุณเข้าสู่สถานะแคชโดยไม่มีคอมโพเนนต์ที่ใช้งานอยู่ ระบบจะปล่อย Wakelock ที่แอปถือครองไว้

นอกจากนี้ ระบบจะจำกัดลักษณะการทำงานบางอย่างของแอปที่ไม่ได้ทำงานอยู่เบื้องหน้าเพื่อปรับปรุงประสิทธิภาพของอุปกรณ์ ดังนี้

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

โดยค่าเริ่มต้น ข้อจำกัดเหล่านี้จะมีผลกับแอปที่กำหนดเป้าหมายเป็น O เท่านั้น อย่างไรก็ตาม ผู้ใช้สามารถเปิดใช้ข้อจำกัดเหล่านี้สำหรับแอปใดก็ได้จากหน้าจอการตั้งค่า แม้ว่าแอปจะไม่กำหนดเป้าหมายเป็น O ก็ตาม

Android 8.0 (API ระดับ 26) ยังมีการเปลี่ยนแปลงวิธีการบางอย่างดังต่อไปนี้ด้วย

  • ตอนนี้เมธอด startService() จะแสดง IllegalStateException หากแอปที่กำหนดเป้าหมายเป็น Android 8.0 พยายามใช้เมธอดดังกล่าวในสถานการณ์ที่ไม่ได้รับอนุญาตให้สร้างบริการในเบื้องหลัง
  • เมธอด Context.startForegroundService() ใหม่จะเริ่มบริการที่ทำงานอยู่เบื้องหน้า ระบบอนุญาตให้แอปเรียกใช้ Context.startForegroundService() แม้ในขณะที่แอปอยู่ในเบื้องหลัง อย่างไรก็ตาม แอปต้องเรียกใช้เมธอด startForeground() ของบริการนั้นภายใน 5 วินาทีหลังจากที่สร้างบริการ

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

ขีดจํากัดตําแหน่งในเบื้องหลังของ Android

แอปที่ทำงานอยู่เบื้องหลังจะได้รับการอัปเดตตำแหน่งน้อยลงเมื่อใช้บนอุปกรณ์ที่ใช้ Android 8.0 เพื่อรักษาแบตเตอรี่ ประสบการณ์ของผู้ใช้ และประสิทธิภาพของระบบ การเปลี่ยนแปลงลักษณะการทํางานนี้มีผลกับแอปทั้งหมดที่ได้รับข้อมูลอัปเดตตําแหน่ง รวมถึงบริการ Google Play

การเปลี่ยนแปลงเหล่านี้มีผลกับ API ต่อไปนี้

  • ผู้ให้บริการ Fused Location (FLP)
  • การกำหนดเขตพื้นที่เสมือน
  • การวัด GNSS
  • ผู้จัดการสถานที่
  • เครื่องมือจัดการ Wi-Fi

ทําตามขั้นตอนต่อไปนี้เพื่อให้แอปทํางานตามที่คาดไว้

  • ตรวจสอบตรรกะของแอปและตรวจสอบว่าคุณใช้ Location API เวอร์ชันล่าสุด
  • ทดสอบว่าแอปของคุณแสดงลักษณะการทำงานตามที่คาดไว้สำหรับ Use Case แต่ละรายการ
  • ลองใช้ Fused Location Provider (FLP) หรือการกำหนดเขตพื้นที่เสมือนเพื่อจัดการกรณีการใช้งานที่ขึ้นอยู่กับตำแหน่งปัจจุบันของผู้ใช้

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

แป้นพิมพ์ลัดของแอป

Android 8.0 (API ระดับ 26) มีการเปลี่ยนแปลงต่อไปนี้กับทางลัดของแอป

  • การออกอากาศ com.android.launcher.action.INSTALL_SHORTCUT ไม่มีผลกับแอปของคุณอีกต่อไป เนื่องจากตอนนี้เป็นการออกอากาศแบบส่วนตัวโดยนัย แต่คุณควรสร้างทางลัดของแอปโดยใช้เมธอด requestPinShortcut() จากคลาส ShortcutManager
  • ตอนนี้ Intent ACTION_CREATE_SHORTCUT สามารถสร้างทางลัดของแอปที่คุณจัดการโดยใช้คลาส ShortcutManager แล้ว Intent นี้ยังสร้างทางลัดของ Launcher เดิมที่ไม่โต้ตอบกับ ShortcutManager ได้ด้วย ก่อนหน้านี้ Intent นี้สร้างได้เฉพาะทางลัดของ Launcher รุ่นเดิม
  • ทางลัดที่สร้างโดยใช้ requestPinShortcut() และทางลัดที่สร้างในกิจกรรมที่จัดการ Intent ACTION_CREATE_SHORTCUT กลายเป็นทางลัดของแอปที่สมบูรณ์แล้ว ด้วยเหตุนี้ แอปจึงอัปเดตได้โดยใช้วิธีการใน ShortcutManager
  • ทางลัดเดิมจะยังคงทำงานตามฟังก์ชันการทำงานจาก Android เวอร์ชันก่อนหน้า แต่คุณต้องแปลงเป็นทางลัดของแอปด้วยตนเองในแอป

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

ภาษาและการปรับให้เป็นสากล

Android 7.0 (API ระดับ 24) ได้เปิดตัวแนวคิดในการระบุภาษาท้องถิ่นของหมวดหมู่เริ่มต้น แต่ API บางรายการยังคงใช้เมธอด Locale.getDefault() แบบทั่วไปโดยไม่มีอาร์กิวเมนต์ต่อไป แม้ว่าควรจะใช้ภาษาท้องถิ่นของหมวดหมู่ DISPLAY เริ่มต้นแทน ใน Android 8.0 (API ระดับ 26) ตอนนี้เมธอดต่อไปนี้ใช้ Locale.getDefault(Category.DISPLAY) แทน Locale.getDefault()

Locale.getDisplayScript(Locale) จะกลับไปเป็น Locale.getDefault() เมื่อค่า displayScript ที่ระบุสำหรับอาร์กิวเมนต์ Locale ไม่พร้อมใช้งาน

การเปลี่ยนแปลงเพิ่มเติมที่เกี่ยวข้องกับภาษาและการปรับให้เป็นสากลมีดังนี้

  • การเรียกใช้ Currency.getDisplayName(null) จะแสดงข้อยกเว้น NullPointerException ซึ่งตรงกับลักษณะการทำงานที่บันทึกไว้
  • การเปลี่ยนแปลงการแยกวิเคราะห์ชื่อเขตเวลา ก่อนหน้านี้อุปกรณ์ Android ใช้ค่านาฬิกาของระบบที่สุ่มตัวอย่างเมื่อบูตเพื่อแคชชื่อเขตเวลาที่ใช้ในการแยกวิเคราะห์วันที่และเวลา ด้วยเหตุนี้ การแยกวิเคราะห์จึงอาจได้รับผลกระทบในทางลบหากนาฬิกาของระบบไม่ถูกต้องในเวลาบูตหรือในกรณีอื่นๆ ที่พบได้น้อย

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

  • Android 8.0 (API ระดับ 26) จะอัปเดต ICU เป็นเวอร์ชัน 58

กรอบเวลาการแจ้งเตือน

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

...แล้วหน้าต่างเหล่านี้จะปรากฏใต้หน้าต่างที่ใช้ประเภท TYPE_APPLICATION_OVERLAY window เสมอ หากแอปกำหนดเป้าหมายเป็น Android 8.0 (API ระดับ 26) แอปจะใช้ประเภท TYPE_APPLICATION_OVERLAY window เพื่อแสดงหน้าต่างการแจ้งเตือน

ดูข้อมูลเพิ่มเติมได้ที่ส่วนประเภทหน้าต่างทั่วไปสำหรับหน้าต่างข้อความแจ้งภายในการเปลี่ยนแปลงลักษณะการทํางานของแอปที่กําหนดเป้าหมายเป็น Android 8.0

การป้อนข้อมูลและการนำทาง

เมื่อมีแอป Android ใน ChromeOS และอุปกรณ์รูปแบบอื่นๆ ที่มีขนาดใหญ่ เช่น แท็บเล็ต เราพบว่าการใช้การไปยังส่วนต่างๆ ด้วยแป้นพิมพ์ในแอป Android กลับมาได้รับความนิยมอีกครั้ง ใน Android 8.0 (API ระดับ 26) เราได้แก้ไขการใช้แป้นพิมพ์เป็นอุปกรณ์อินพุตการไปยังส่วนต่างๆ อีกครั้ง ซึ่งทำให้การไปยังส่วนต่างๆ ด้วยปุ่มลูกศรและแท็บมีความน่าเชื่อถือและคาดการณ์ได้มากขึ้น

โดยเฉพาะอย่างยิ่ง เราได้ทำการเปลี่ยนแปลงต่อไปนี้กับลักษณะการโฟกัสองค์ประกอบ

  • หากคุณยังไม่ได้กำหนดสีสถานะโฟกัสสำหรับออบเจ็กต์ View (ออบเจ็กต์ที่วาดได้ในส่วนหน้าหรือพื้นหลัง) ตอนนี้เฟรมเวิร์กจะกำหนดสีไฮไลต์โฟกัสเริ่มต้นสำหรับ View ไฮไลต์โฟกัสนี้เป็นภาพวาดแบบกระเพื่อมที่อิงตามธีมของกิจกรรม

    หากไม่ต้องการให้ออบเจ็กต์ View ใช้ไฮไลต์เริ่มต้นนี้เมื่อได้รับโฟกัส ให้ตั้งค่าแอตทริบิวต์ android:defaultFocusHighlightEnabled เป็น false ในไฟล์ XML เลย์เอาต์ที่มี View หรือส่ง false ไปยัง setDefaultFocusHighlightEnabled() ในตรรกะ UI ของแอป

  • หากต้องการทดสอบว่าการป้อนข้อมูลด้วยแป้นพิมพ์ส่งผลต่อโฟกัสขององค์ประกอบ UI อย่างไร ให้เปิดใช้ตัวเลือกการวาด > แสดงขอบเขตเลย์เอาต์สำหรับนักพัฒนาซอฟต์แวร์ ใน Android 8.0 ตัวเลือกนี้จะแสดงไอคอน "X" เหนือองค์ประกอบที่มีโฟกัสอยู่

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีปรับปรุงการรองรับการไปยังส่วนต่างๆ ด้วยแป้นพิมพ์ภายในแอปได้จากคู่มือการรองรับการไปยังส่วนต่างๆ ด้วยแป้นพิมพ์

กรอกข้อมูลเว็บฟอร์มอัตโนมัติ

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

WebSettings
  • ตอนนี้เมธอด getSaveFormData() แสดงผล false ก่อนหน้านี้ เมธอดนี้จะแสดงผลเป็น true แทน
  • การเรียกใช้ setSaveFormData() ไม่มีผลอีกต่อไป
WebViewDatabase
  • การเรียกใช้ clearFormData() ไม่มีผลอีกต่อไป
  • ตอนนี้เมธอด hasFormData() จะแสดง false ก่อนหน้านี้วิธีนี้แสดงผล true เมื่อแบบฟอร์มมีข้อมูล

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

Android 8.0 (API ระดับ 26) มีการเปลี่ยนแปลงต่อไปนี้เกี่ยวกับการช่วยเหลือพิเศษ

  • ตอนนี้เฟรมเวิร์กการช่วยเหลือพิเศษจะแปลงท่าทางสัมผัสด้วยการแตะสองครั้งทั้งหมดเป็นการดำเนินการ ACTION_CLICK การเปลี่ยนแปลงนี้จะช่วยให้ TalkBack ทำงานได้คล้ายกับบริการการช่วยเหลือพิเศษอื่นๆ มากขึ้น

    หากViewออบเจ็กต์ของแอปใช้การจัดการการสัมผัสที่กําหนดเอง คุณควรตรวจสอบว่าออบเจ็กต์เหล่านั้นยังคงทํางานร่วมกับ TalkBack ได้ คุณอาจต้องลงทะเบียนตัวแฮนเดิลการคลิกที่ออบเจ็กต์ View ใช้ หาก TalkBack ยังคงไม่รู้จักท่าทางสัมผัสที่ทำกับวัตถุเหล่านี้ ให้ลบล้าง View performAccessibilityAction()

  • ตอนนี้บริการการช่วยเหลือพิเศษจะรับรู้อินสแตนซ์ ClickableSpan ทั้งหมดภายในออบเจ็กต์ TextView ของแอป

ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีทําให้แอปเข้าถึงได้ง่ายขึ้นได้ที่การช่วยเหลือพิเศษ

เครือข่ายและการเชื่อมต่อ HTTP(S)

Android 8.0 (API ระดับ 26) มีการเปลี่ยนแปลงลักษณะการทำงานต่อไปนี้ใน เครือข่ายและการเชื่อมต่อ HTTP(S)

  • คำขอ OPTIONS ที่ไม่มีเนื้อหาจะมีส่วนหัว Content-Length: 0 ก่อนหน้านี้ไม่มีส่วนหัว Content-Length
  • HttpURLConnection จะปรับ URL ที่มีเส้นทางว่างให้เป็นมาตรฐานโดยใส่เครื่องหมายทับต่อท้ายชื่อโฮสต์หรือชื่อโดเมน เช่น แปลง http://example.com เป็น http://example.com/
  • ตัวเลือกพร็อกซีที่กำหนดเองซึ่งตั้งค่าผ่าน ProxySelector.setDefault() จะกำหนดเป้าหมายเฉพาะที่อยู่ (รูปแบบ โฮสต์ และพอร์ต) ของ URL ที่ขอเท่านั้น ดังนั้น การเลือกพร็อกซีอาจอิงตามค่าเหล่านั้นเท่านั้น URL ที่ส่งไปยังตัวเลือกพร็อกซีที่กำหนดเองจะไม่รวมเส้นทาง พารามิเตอร์การค้นหา หรือข้อมูลโค้ดของ URL ที่ขอ
  • URI ต้องไม่มีป้ายกำกับที่ว่างเปล่า

    ก่อนหน้านี้ แพลตฟอร์มรองรับวิธีแก้ปัญหาเพื่อยอมรับป้ายกำกับว่างในชื่อโฮสต์ ซึ่งเป็นการใช้ URI ที่ผิดกฎหมาย วิธีแก้ปัญหานี้มีไว้เพื่อเพิ่มความเข้ากันได้กับ libcore เวอร์ชันเก่า นักพัฒนาซอฟต์แวร์ที่ใช้ API อย่างไม่ถูกต้องจะเห็นข้อความ ADB ว่า "URI example..com มีป้ายกำกับว่างในชื่อโฮสต์ ข้อมูลนี้อยู่ในรูปแบบที่ไม่ถูกต้องและระบบจะไม่ยอมรับใน Android เวอร์ชันในอนาคต" Android 8.0 นำวิธีแก้ปัญหานี้ออก ระบบจะแสดงผล Null สำหรับ URI ที่ไม่ถูกต้อง

  • การใช้งาน HttpsURLConnection ของ Android 8.0 จะไม่ใช้โปรโตคอล TLS/SSL เวอร์ชันที่ไม่ปลอดภัยเป็นทางเลือก
  • มีการเปลี่ยนแปลงการจัดการการเชื่อมต่อ HTTP(S) ของ Tunnel ดังนี้
    • เมื่อส่งผ่านการเชื่อมต่อ HTTPS ผ่านการเชื่อมต่อ ระบบจะใส่หมายเลขพอร์ต (:443) ในบรรทัดโฮสต์อย่างถูกต้องเมื่อส่งข้อมูลนี้ไปยังเซิร์ฟเวอร์กลาง ก่อนหน้านี้ หมายเลขพอร์ตจะปรากฏในบรรทัด CONNECT เท่านั้น
    • ระบบจะไม่ส่งส่วนหัว User-Agent และ Proxy-Authorization จากคำขอที่ส่งผ่านอุโมงค์ไปยังเซิร์ฟเวอร์พร็อกซีอีกต่อไป

      ระบบจะไม่ส่งส่วนหัวการให้สิทธิ์พร็อกซีใน Http(s)URLConnection ที่มีการเชื่อมต่อไปยังพร็อกซีอีกต่อไปเมื่อตั้งค่าอุโมงค์ข้อมูล แต่ระบบจะสร้างส่วนหัวการให้สิทธิ์พร็อกซีแทน และส่งไปยังพร็อกซีเมื่อพร็อกซีดังกล่าวส่ง HTTP 407 เพื่อตอบกลับคำขอแรก

      ในทํานองเดียวกัน ระบบจะไม่คัดลอกส่วนหัว User-Agent จากคําขอที่ส่งผ่านอุโมงค์ไปยังคําขอพร็อกซีที่ตั้งค่าอุโมงค์อีกต่อไป แต่ไลบรารีจะสร้างส่วนหัว User Agent สําหรับคําขอนั้นแทน

  • เมธอด send(java.net.DatagramPacket) จะแสดงข้อยกเว้น SocketException หากเมธอด connect() ที่เรียกใช้ก่อนหน้านี้ไม่สำเร็จ
    • DatagramSocket.connect() จะตั้งค่า pendingSocketException หากมีข้อผิดพลาดภายใน ก่อนที่จะเป็น Android 8.0 การเรียกใช้ recv() ตามมาจะทำให้เกิด SocketException แม้ว่าการเรียกใช้ send() จะสำเร็จก็ตาม เพื่อความสอดคล้อง ตอนนี้การโทรทั้งสองจะมี SocketException
  • InetAddress.isReachable() จะพยายามใช้ ICMP ก่อนเปลี่ยนไปใช้โปรโตคอล TCP Echo
    • โฮสต์บางรายการที่บล็อกพอร์ต 7 (TCP Echo) เช่น google.com อาจเข้าถึงได้หากยอมรับโปรโตคอล ICMP Echo
    • สําหรับโฮสต์ที่เข้าถึงไม่ได้จริงๆ การเปลี่ยนแปลงนี้หมายความว่าระบบจะใช้เวลานานขึ้น 2 เท่าก่อนที่จะมีการเรียกกลับ

บลูทูธ

Android 8.0 (API ระดับ 26) ทำการเปลี่ยนแปลงต่อไปนี้กับความยาวของข้อมูลที่เมธอด ScanRecord.getBytes() retrieving ดึงข้อมูล

  • เมธอด getBytes() จะไม่คาดเดาจำนวนไบต์ที่ได้รับ ดังนั้น แอปไม่ควรใช้จำนวนไบต์ขั้นต่ำหรือสูงสุดที่แสดงผล แต่ควรประเมินความยาวของอาร์เรย์ผลลัพธ์แทน
  • อุปกรณ์ที่เข้ากันได้กับบลูทูธ 5 อาจแสดงผลความยาวข้อมูลเกินกว่าค่าสูงสุดก่อนหน้านี้ที่ประมาณ 60 ไบต์
  • หากอุปกรณ์ระยะไกลไม่ตอบสนองการสแกน ระบบอาจแสดงผลน้อยกว่า 60 ไบต์ด้วย

การเชื่อมต่อที่ราบรื่น

Android 8.0 (API ระดับ 26) ปรับปรุงการตั้งค่า Wi-Fi หลายอย่างเพื่อให้เลือกเครือข่าย Wi-Fi ที่มอบประสบการณ์การใช้งานที่ดีที่สุดแก่ผู้ใช้ได้ง่ายขึ้น การเปลี่ยนแปลงที่เจาะจงมีดังนี้

  • ปรับปรุงความเสถียรและความน่าเชื่อถือ
  • UI ที่อ่านง่ายขึ้น
  • เมนูค่ากำหนด Wi-Fi แบบรวมที่ใช้งานง่าย
  • ในอุปกรณ์ที่รองรับ การเปิดใช้งาน Wi-Fi โดยอัตโนมัติเมื่ออยู่ใกล้เครือข่ายที่บันทึกไว้ซึ่งมีคุณภาพสูง

ความปลอดภัย

Android 8.0 มีการเปลี่ยนแปลงที่เกี่ยวข้องกับความปลอดภัยดังต่อไปนี้

  • แพลตฟอร์มนี้ไม่สนับสนุน SSLv3 อีกต่อไป
  • เมื่อสร้างการเชื่อมต่อ HTTPS กับเซิร์ฟเวอร์ที่ใช้การเจรจาต่อรองเวอร์ชันโปรโตคอล TLS อย่างไม่ถูกต้อง HttpsURLConnection จะไม่พยายามแก้ปัญหาชั่วคราวด้วยการกลับไปใช้โปรโตคอล TLS เวอร์ชันเก่าแล้วลองใหม่อีกต่อไป
  • Android 8.0 (API ระดับ 26) ใช้ตัวกรองการประมวลผลที่ปลอดภัย (SECCOMP) กับแอปทั้งหมด รายการ syscall ที่อนุญาตจะจํากัดไว้เฉพาะ syscall ที่แสดงผ่าน bionic แม้ว่าจะมี syscall อื่นๆ อีกหลายรายการที่ระบุไว้เพื่อใช้งานร่วมกันได้แบบย้อนหลัง แต่เราไม่แนะนำให้ใช้
  • ตอนนี้ออบเจ็กต์ WebView ของแอปจะทำงานในโหมดหลายกระบวนการ ระบบจะจัดการเนื้อหาเว็บในกระบวนการแยกต่างหากจากกระบวนการของแอปที่มีเนื้อหาเว็บเพื่อเพิ่มความปลอดภัย
  • คุณไม่สามารถถือว่า APK อยู่ในไดเรกทอรีที่มีชื่อลงท้ายด้วย -1 หรือ -2 ได้อีกต่อไป แอปควรใช้ sourceDir เพื่อรับไดเรกทอรี และไม่ควรใช้รูปแบบไดเรกทอรีโดยตรง
  • ดูข้อมูลเกี่ยวกับการปรับปรุงความปลอดภัยที่เกี่ยวข้องกับการใช้ไลบรารีแบบเนทีฟได้ที่ไลบรารีแบบเนทีฟ

นอกจากนี้ Android 8.0 (API ระดับ 26) ยังมาพร้อมกับการเปลี่ยนแปลงต่อไปนี้ซึ่งเกี่ยวข้องกับการติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มาที่ไม่รู้จัก

  • ตอนนี้ค่าของการตั้งค่าเดิม INSTALL_NON_MARKET_APPS จะเป็น 1 เสมอ หากต้องการตรวจสอบว่าแหล่งที่มาที่ไม่รู้จักสามารถติดตั้งแอปโดยใช้โปรแกรมติดตั้งแพ็กเกจได้หรือไม่ คุณควรใช้ผลลัพธ์ของ canRequestPackageInstalls() แทน
  • หากคุณพยายามเปลี่ยนค่าของ INSTALL_NON_MARKET_APPS โดยใช้ setSecureSetting() ระบบจะแสดง UnsupportedOperationException หากต้องการป้องกันไม่ให้ผู้ใช้ติดตั้งแอปที่ไม่รู้จักโดยใช้แหล่งที่มาที่ไม่รู้จัก คุณควรใช้DISALLOW_INSTALL_UNKNOWN_SOURCESข้อจำกัดของผู้ใช้แทน
  • โปรไฟล์ที่มีการจัดการที่สร้างในอุปกรณ์ที่ใช้ Android 8.0 (API ระดับ 26) จะเปิดใช้ข้อจำกัดDISALLOW_INSTALL_UNKNOWN_SOURCESของผู้ใช้โดยอัตโนมัติ สำหรับโปรไฟล์ที่มีการจัดการที่มีอยู่ซึ่งอัปเกรดเป็น Android 8.0 ระบบจะเปิดใช้ข้อจำกัดDISALLOW_INSTALL_UNKNOWN_SOURCESของผู้ใช้โดยอัตโนมัติ เว้นแต่ว่าเจ้าของโปรไฟล์จะปิดใช้ข้อจำกัดนี้อย่างชัดเจน (ก่อนการอัปเกรด) โดยการตั้งค่าINSTALL_NON_MARKET_APPSเป็น 1

ดูรายละเอียดเพิ่มเติมเกี่ยวกับการติดตั้งแอปที่ไม่รู้จักได้ที่คู่มือสิทธิ์ในการติดตั้งแอปที่ไม่รู้จัก

ดูหลักเกณฑ์เพิ่มเติมเกี่ยวกับการทำให้แอปปลอดภัยยิ่งขึ้นได้ที่ความปลอดภัยสำหรับนักพัฒนาแอป Android

ความเป็นส่วนตัว

Android 8.0 (API ระดับ 26) ทำการเปลี่ยนแปลงต่อไปนี้ที่เกี่ยวข้องกับความเป็นส่วนตัวในแพลตฟอร์ม

  • ปัจจุบันแพลตฟอร์มจะจัดการกับตัวระบุในลักษณะที่ต่างออกไป
    • สําหรับแอปที่ติดตั้งก่อนการอัปเดต OTA เป็น Android 8.0 (API ระดับ 26) (API ระดับ 26) ค่าของ ANDROID_ID จะยังคงเหมือนเดิม เว้นแต่จะมีการถอนการติดตั้งแล้วติดตั้งอีกครั้งหลังจาก OTA หากต้องการเก็บค่าไว้หลังจากการถอนการติดตั้ง OTA นักพัฒนาแอปสามารถเชื่อมโยงค่าเก่าและค่าใหม่ได้โดยใช้ การสำรองข้อมูลคีย์/ค่า
    • สำหรับแอปที่ติดตั้งในอุปกรณ์ที่ใช้ Android 8.0 ตอนนี้ค่าของ ANDROID_ID จะกำหนดขอบเขตตามคีย์ App Signing ของแอปแต่ละรายการและตามผู้ใช้แต่ละราย ค่าของ ANDROID_ID จะไม่ซ้ำกันสำหรับชุดค่าผสมของคีย์การรับรองแอป ผู้ใช้ และอุปกรณ์แต่ละชุด ด้วยเหตุนี้ แอปที่มีคีย์การรับรองต่างกันซึ่งทำงานในอุปกรณ์เครื่องเดียวกันจึงไม่เห็นรหัส Android เดียวกันอีกต่อไป (แม้ว่าจะเป็นผู้ใช้รายเดียวกันก็ตาม)
    • ค่าของ ANDROID_ID จะไม่เปลี่ยนแปลงเมื่อถอนการติดตั้งหรือติดตั้งแพ็กเกจใหม่ ตราบใดที่มีคีย์ Signing เหมือนกัน (และแอปไม่ได้ติดตั้งก่อน OTA ใน Android เวอร์ชัน 8.0)
    • ค่าของ ANDROID_ID จะไม่มีการเปลี่ยนแปลงแม้ว่าการอัปเดตระบบจะทําให้คีย์การรับรองแพ็กเกจเปลี่ยนแปลงก็ตาม
    • ในอุปกรณ์ที่มาพร้อมกับบริการ Google Play และรหัสโฆษณา คุณต้องใช้ รหัสโฆษณา ระบบมาตรฐานที่ใช้งานง่ายในการสร้างรายได้จากแอป รหัสโฆษณาคือรหัสที่ไม่ซ้ำกันซึ่งผู้ใช้รีเซ็ตได้สำหรับใช้กับโฆษณา ซึ่งให้บริการโดยบริการ Google Play

      ผู้ผลิตอุปกรณ์รายอื่นๆ ควรให้บริการ ANDROID_ID ต่อไป

  • การค้นหาพร็อพเพอร์ตี้ระบบ net.hostname ให้ผลลัพธ์เป็นค่าว่าง

การบันทึกข้อยกเว้นที่ตรวจไม่พบ

หากแอปติดตั้ง Thread.UncaughtExceptionHandler ที่ไม่ได้เรียกใช้ Thread.UncaughtExceptionHandler เริ่มต้น ระบบจะไม่หยุดแอปเมื่อเกิดข้อยกเว้นที่ตรวจไม่พบ เริ่มตั้งแต่ Android 8.0 (API ระดับ 26) ระบบจะบันทึกสแต็กเทรซข้อยกเว้นในสถานการณ์นี้ แต่ในแพลตฟอร์มเวอร์ชันก่อนหน้า ระบบจะไม่บันทึกสแต็กเทรซข้อยกเว้น

เราขอแนะนำให้การติดตั้งใช้งาน Thread.UncaughtExceptionHandler แบบกำหนดเองเรียกใช้ตัวแฮนเดิลเริ่มต้นเสมอ แอปที่เป็นไปตามคำแนะนำนี้จะไม่ได้รับผลกระทบจากการเปลี่ยนแปลงใน Android 8.0

การเปลี่ยนแปลงลายเซ็น findViewById()

ตอนนี้อินสแตนซ์ทั้งหมดของเมธอด findViewById() จะแสดงผล <T extends View> T แทน View การเปลี่ยนแปลงนี้ส่งผลดังต่อไปนี้

  • ซึ่งอาจส่งผลให้โค้ดที่มีอยู่มีประเภทผลลัพธ์ที่ไม่ชัดเจน เช่น หากมีทั้ง someMethod(View) และ someMethod(TextView) ที่ใช้ผลลัพธ์ของการเรียก findViewById()
  • เมื่อใช้ภาษาแหล่งที่มาของ Java 8 จะต้องแคสต์เป็น View อย่างชัดแจ้งเมื่อประเภทผลลัพธ์ไม่จำกัด (เช่น assertNotNull(findViewById(...)).someViewMethod())
  • การลบล้างวิธีการ findViewById() ที่ไม่ใช่ขั้นสุดท้าย (เช่น Activity.findViewById()) จะต้องอัปเดตประเภทผลลัพธ์

การเปลี่ยนแปลงสถิติการใช้งานผู้ให้บริการรายชื่อติดต่อ

ใน Android เวอร์ชันก่อนหน้า คอมโพเนนต์ผู้ให้บริการรายชื่อติดต่อช่วยให้นักพัฒนาซอฟต์แวร์รับข้อมูลการใช้งานของรายชื่อติดต่อแต่ละรายการได้ ข้อมูลการใช้งานนี้จะแสดงข้อมูลของอีเมลและหมายเลขโทรศัพท์แต่ละรายการที่เชื่อมโยงกับรายชื่อติดต่อ รวมถึงจํานวนครั้งที่ติดต่อรายชื่อติดต่อและเวลาที่ติดต่อครั้งล่าสุด แอปที่ขอสิทธิ์ READ_CONTACTS จะอ่านข้อมูลนี้ได้

แอปจะยังคงอ่านข้อมูลนี้ได้หากขอสิทธิ์ READ_CONTACTS ใน Android 8.0 (API ระดับ 26) ขึ้นไป การค้นหาข้อมูลการใช้งานจะแสดงผลค่าโดยประมาณแทนที่จะเป็นค่าที่แน่นอน ระบบ Android จะเก็บค่าที่แน่นอนไว้ภายใน ดังนั้นการเปลี่ยนแปลงนี้จึงไม่ส่งผลต่อ API เติมข้อความอัตโนมัติ

การเปลี่ยนแปลงลักษณะการทํางานนี้มีผลต่อพารามิเตอร์การค้นหาต่อไปนี้

การจัดการคอลเล็กชัน

AbstractCollection.removeAll() และ AbstractCollection.retainAll() ในปัจจุบันจะส่ง NullPointerException เสมอ และก่อนหน้านี้ไม่มีการแสดง NullPointerException เมื่อคอลเล็กชันว่างเปล่า การเปลี่ยนแปลงนี้ทําให้ลักษณะการทํางานสอดคล้องกับเอกสารประกอบ

Android Enterprise

Android 8.0 (API ระดับ 26) เปลี่ยนลักษณะการทำงานของ API และฟีเจอร์บางอย่างสำหรับแอประดับองค์กร ซึ่งรวมถึงเครื่องมือควบคุมนโยบายด้านอุปกรณ์ (DPC) การเปลี่ยนแปลงมีดังนี้

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

หากต้องการดูการเปลี่ยนแปลงทั้งหมดระดับองค์กรใน Android 8.0 (API ระดับ 26) และเรียนรู้ว่า การเปลี่ยนแปลงนี้อาจส่งผลต่อแอปของคุณอย่างไร โปรดอ่าน Android ใน Enterprise

แอปที่กําหนดเป้าหมายเป็น Android 8.0

การเปลี่ยนแปลงลักษณะการทำงานเหล่านี้มีผลกับแอปที่กำหนดเป้าหมายเป็น Android 8.0 (API ระดับ 26) ขึ้นไปเท่านั้น แอปที่คอมไพล์กับ Android 8.0 หรือตั้งค่า targetSdkVersion เป็น Android 8.0 ขึ้นไปต้องแก้ไข แอปเพื่อรองรับลักษณะการทำงานเหล่านี้อย่างถูกต้อง ในกรณีที่เกี่ยวข้องกับแอป

กรอบเวลาการแจ้งเตือน

แอปที่ใช้สิทธิ์ SYSTEM_ALERT_WINDOW จะไม่สามารถแสดงหน้าต่างประเภทต่อไปนี้เหนือแอปอื่นๆ และหน้าต่างของระบบเพื่อแสดงหน้าต่างแจ้งเตือนได้อีกต่อไป

แต่แอปต้องใช้หน้าต่างประเภทใหม่ที่เรียกว่า TYPE_APPLICATION_OVERLAY แทน

เมื่อใช้ประเภทหน้าต่าง TYPE_APPLICATION_OVERLAY เพื่อแสดงหน้าต่างแจ้งเตือนสําหรับแอป โปรดคํานึงถึงลักษณะต่อไปนี้ของประเภทหน้าต่างใหม่

  • หน้าต่างการแจ้งเตือนของแอปจะปรากฏใต้หน้าต่างระบบที่สำคัญเสมอ เช่น แถบสถานะและ IME
  • ระบบย้ายหรือปรับขนาดหน้าต่างที่ใช้หน้าต่างประเภท TYPE_APPLICATION_OVERLAY เพื่อปรับปรุงการนำเสนอหน้าจอได้
  • เมื่อเปิดหน้าต่างแจ้งเตือน ผู้ใช้จะเข้าถึงการตั้งค่าเพื่อบล็อกแอปไม่ให้แสดงหน้าต่างการแจ้งเตือนที่ใช้ประเภทหน้าต่าง TYPE_APPLICATION_OVERLAY ได้

การแจ้งเตือนการเปลี่ยนแปลงเนื้อหา

Android 8.0 (API ระดับ 26) เปลี่ยนแปลงลักษณะการทํางานของ ContentResolver.notifyChange() และ registerContentObserver(Uri, boolean, ContentObserver) สําหรับแอปที่กําหนดเป้าหมายเป็น Android 8.0

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

ดูโฟกัส

ออบเจ็กต์ View ที่คลิกได้ยังโฟกัสได้โดยค่าเริ่มต้น หากต้องการให้ออบเจ็กต์ View คลิกได้แต่โฟกัสไม่ได้ ให้ตั้งค่าแอตทริบิวต์ android:focusable เป็น false ในไฟล์ XML เลย์เอาต์ที่มี View หรือส่ง false ไปยัง setFocusable() ในตรรกะ UI ของแอป

การจับคู่ User Agent ในการตรวจหาเบราว์เซอร์

Android 8.0 (API ระดับ 26) ขึ้นไปจะมีสตริงตัวระบุบิลด์ OPR การจับคู่รูปแบบบางอย่างอาจทําให้ตรรกะการตรวจหาเบราว์เซอร์ระบุเบราว์เซอร์ที่ไม่ใช่ Opera เป็น Opera อย่างไม่ถูกต้อง ตัวอย่างการจับคู่รูปแบบดังกล่าวอาจเป็นดังนี้

if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}

หากต้องการหลีกเลี่ยงปัญหาที่เกิดจากการระบุที่ไม่ถูกต้องดังกล่าว ให้ใช้สตริงอื่นที่ไม่ใช่ OPR เป็นรายการที่ตรงกันของรูปแบบสําหรับเบราว์เซอร์ Opera

ความปลอดภัย

การเปลี่ยนแปลงต่อไปนี้ส่งผลต่อความปลอดภัยใน Android 8.0 (API ระดับ 26)

  • หากการกำหนดค่าความปลอดภัยของเครือข่ายของแอปเลือกไม่รองรับการรับส่งข้อมูลแบบข้อความธรรมดา (Cleartext) ออบเจ็กต์ WebView ของแอปจะเข้าถึงเว็บไซต์ผ่าน HTTP ไม่ได้ ออบเจ็กต์ WebView แต่ละรายการต้องใช้ HTTPS แทน
  • ระบบได้นำการตั้งค่าอนุญาตแหล่งที่มาที่ไม่รู้จักออกแล้ว แทนที่ด้วยสิทธิ์ติดตั้งแอปที่ไม่รู้จักซึ่งจะจัดการการติดตั้งแอปที่ไม่รู้จักจากแหล่งที่มาที่ไม่รู้จัก ดูข้อมูลเพิ่มเติมเกี่ยวกับสิทธิ์ใหม่นี้ได้ในคู่มือสิทธิ์ในการติดตั้งแอปที่ไม่รู้จัก

ดูหลักเกณฑ์เพิ่มเติมเกี่ยวกับการทำให้แอปปลอดภัยยิ่งขึ้นได้ที่ความปลอดภัยสำหรับนักพัฒนาแอป Android

การเข้าถึงบัญชีและการค้นพบ

ใน Android 8.0 (API ระดับ 26) แอปจะเข้าถึงบัญชีผู้ใช้ไม่ได้อีกต่อไป เว้นแต่โปรแกรมตรวจสอบสิทธิ์จะเป็นเจ้าของบัญชีหรือผู้ใช้ให้สิทธิ์เข้าถึง สิทธิ์ GET_ACCOUNTS ไม่เพียงพออีกต่อไป แอปควรใช้ AccountManager.newChooseAccountIntent() หรือวิธีการที่เจาะจงสำหรับโปรแกรมตรวจสอบสิทธิ์เพื่อรับสิทธิ์เข้าถึงบัญชี หลังจากได้รับสิทธิ์เข้าถึงบัญชีแล้ว แอปจะเรียกใช้ AccountManager.getAccounts() เพื่อเข้าถึงบัญชีได้

Android 8.0 เลิกใช้งาน LOGIN_ACCOUNTS_CHANGED_ACTION แอป ควรใช้ addOnAccountsUpdatedListener() เพื่อรับข้อมูลอัปเดตเกี่ยวกับบัญชีระหว่างรันไทม์แทน

สำหรับข้อมูลเกี่ยวกับ API ใหม่และวิธีการใหม่ๆ ที่เพิ่มเข้ามาสำหรับการเข้าถึงและการค้นพบบัญชี โปรดดูสิทธิ์เข้าถึงและการค้นพบบัญชีในส่วน API ใหม่ของเอกสารนี้

ความเป็นส่วนตัว

การเปลี่ยนแปลงต่อไปนี้ส่งผลต่อความเป็นส่วนตัวใน Android 8.0 (API ระดับ 26)

  • พร็อพเพอร์ตี้ของระบบ net.dns1, net.dns2, net.dns3 และ net.dns4 จะใช้งานไม่ได้อีกต่อไป ซึ่งเป็นการเปลี่ยนแปลงที่ช่วยปรับปรุงความเป็นส่วนตัวบนแพลตฟอร์ม
  • หากต้องการรับข้อมูลเครือข่าย เช่น เซิร์ฟเวอร์ DNS แอปที่มีACCESS_NETWORK_STATEสิทธิ์จะลงทะเบียนออบเจ็กต์ NetworkRequest หรือ NetworkCallback ได้ คลาสเหล่านี้พร้อมใช้งานใน Android 5.0 (API ระดับ 21) ขึ้นไป
  • เลิกใช้งาน Build.SERIAL แล้ว แอปที่ต้องการทราบหมายเลขซีเรียลของฮาร์ดแวร์ควรใช้เมธอด Build.getSerial() ใหม่แทน ซึ่งต้องใช้สิทธิ์ READ_PHONE_STATE
  • LauncherApps API ไม่อนุญาตให้แอปในโปรไฟล์งานรับข้อมูลเกี่ยวกับโปรไฟล์หลักอีกต่อไป เมื่อผู้ใช้อยู่ในโปรไฟล์งาน LauncherApps API จะทํางานราวกับว่าไม่มีการติดตั้งแอปในโปรไฟล์อื่นๆ ภายในกลุ่มโปรไฟล์เดียวกัน และเช่นเคย การพยายามเข้าถึงโปรไฟล์ที่ไม่เกี่ยวข้องจะทำให้ SecurityException

สิทธิ์

ก่อนที่จะมีการเปิดตัว Android 8.0 (API ระดับ 26) หากแอปขอสิทธิ์ขณะรันไทม์และได้รับสิทธิ์ ระบบก็จะให้สิทธิ์ที่เหลือแก่แอปอย่างไม่ถูกต้อง ซึ่งสิทธิ์เหล่านั้นเป็นของกลุ่มสิทธิ์เดียวกันและได้ลงทะเบียนไว้ในไฟล์ Manifest

สำหรับแอปที่กำหนดเป้าหมายเป็น Android 8.0 ลักษณะการทำงานนี้ได้รับการแก้ไขแล้ว แอปจะได้รับเฉพาะสิทธิ์ที่ขอไว้อย่างชัดเจนเท่านั้น อย่างไรก็ตาม เมื่อผู้ใช้ให้สิทธิ์แก่แอป คำขอสิทธิ์ครั้งต่อๆ ไปทั้งหมดในกลุ่มสิทธิ์นั้นจะ ได้รับอนุญาตโดยอัตโนมัติ

ตัวอย่างเช่น สมมติว่าแอปแสดงทั้ง READ_EXTERNAL_STORAGE และ WRITE_EXTERNAL_STORAGE ในไฟล์ Manifest แอปขอ READ_EXTERNAL_STORAGE และผู้ใช้ให้สิทธิ์ หากแอปกำหนดเป้าหมายเป็น API ระดับ 25 หรือต่ำกว่า ระบบจะมอบสิทธิ์ WRITE_EXTERNAL_STORAGE ให้ด้วยในขณะเดียวกัน เนื่องจากสิทธิ์ดังกล่าวอยู่ในกลุ่มสิทธิ์ STORAGE เดียวกันและยังลงทะเบียนไว้ในไฟล์ Manifest ด้วย หากแอปกำหนดเป้าหมายเป็น Android 8.0 (API ระดับ 26) ระบบจะให้สิทธิ์ READ_EXTERNAL_STORAGE เท่านั้น ณ ขณะนั้น แต่หากแอปขอ WRITE_EXTERNAL_STORAGE ในภายหลัง ระบบจะให้สิทธิ์ดังกล่าวทันทีโดยไม่ต้องแจ้งให้ผู้ใช้ทราบ

สื่อ

  • เฟรมเวิร์กสามารถลดระดับเสียงอัตโนมัติได้ด้วยตนเอง ในกรณีนี้ เมื่อแอปพลิเคชันอื่นขอโฟกัสด้วย AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK แอปพลิเคชันที่มีโฟกัสจะลดระดับเสียง แต่โดยปกติแล้วจะไม่ได้รับการเรียกกลับ onAudioFocusChange() และจะไม่เสียโฟกัสเสียง มี API ใหม่ให้ใช้เพื่อลบล้างลักษณะการทำงานนี้สำหรับแอปพลิเคชันที่ต้องหยุดชั่วคราวแทนการลดระดับเสียง
  • เมื่อผู้ใช้รับสาย สตรีมสื่อที่ใช้งานอยู่จะปิดเสียงตลอดระยะเวลาการโทร
  • API ทั้งหมดที่เกี่ยวข้องกับเสียงควรใช้ AudioAttributes แทนประเภทสตรีมเสียงเพื่ออธิบาย Use Case การเล่นเสียง ใช้ประเภทสตรีมเสียงเพื่อควบคุมระดับเสียงเท่านั้นต่อไป การใช้ประเภทสตรีมอื่นๆ จะยังคงใช้งานได้ (เช่น อาร์กิวเมนต์ streamType ไปยังตัวสร้าง AudioTrack ที่เลิกใช้งานแล้ว) แต่ระบบจะบันทึกการดำเนินการนี้ว่าเป็นข้อผิดพลาด
  • เมื่อใช้ AudioTrack หากแอปพลิเคชันขอบัฟเฟอร์เสียงขนาดใหญ่พอ เฟรมเวิร์กจะพยายามใช้เอาต์พุตบัฟเฟอร์เชิงลึกหากมี
  • ใน Android 8.0 (API ระดับ 26) การจัดการเหตุการณ์ของปุ่มสื่อจะแตกต่างออกไปดังนี้
    1. การจัดการปุ่มสื่อในกิจกรรม UI ไม่ได้เปลี่ยนแปลงไป กิจกรรมที่ทำงานอยู่เบื้องหน้าจะยังคงมีความสำคัญในการจัดการเหตุการณ์ของปุ่มสื่อ
    2. หากกิจกรรมที่ทำงานอยู่เบื้องหน้าไม่จัดการเหตุการณ์ของปุ่มสื่อ ระบบจะส่งเหตุการณ์ไปยังแอปที่เล่นเสียงในเครื่องล่าสุด ระบบจะไม่พิจารณาสถานะใช้งาน สถานะการเล่น และสถานะเซสชันสื่อเมื่อพิจารณาว่าแอปใดจะได้รับเหตุการณ์ปุ่มสื่อ
    3. หากมีการปล่อยเซสชันสื่อของแอป ระบบจะส่งเหตุการณ์ปุ่มสื่อไปยังMediaButtonReceiverของแอป หากมี
    4. สำหรับกรณีอื่นๆ ทั้งหมด ระบบจะทิ้งเหตุการณ์ปุ่มสื่อ

ไลบรารีที่มาพร้อมเครื่อง

ในแอปที่กำหนดเป้าหมายเป็น Android 8.0 (API ระดับ 26) ไลบรารีแบบเนทีฟจะไม่โหลดอีกต่อไปหากมีส่วนโหลดที่เขียนได้และเรียกใช้ได้ แอปบางแอปอาจหยุดทำงานเนื่องจากการเปลี่ยนแปลงนี้หากมีไลบรารีแบบเนทีฟที่มีกลุ่มการโหลดไม่ถูกต้อง การดำเนินการนี้เป็นมาตรการเพิ่มความแข็งแกร่งให้กับการรักษาความปลอดภัย

ดูข้อมูลเพิ่มเติมได้ที่ กลุ่มที่เขียนได้และกลุ่มที่เรียกใช้ได้

การเปลี่ยนแปลง linker จะเชื่อมโยงกับระดับ API ที่แอปกำหนดเป้าหมาย หากมีการเปลี่ยนแปลง Linker ในระดับ API เป้าหมาย แอปจะโหลดไลบรารีไม่ได้ หากคุณกําหนดเป้าหมายไปที่ระดับ API ต่ำกว่าระดับ API ที่การเปลี่ยนแปลง linker เกิดขึ้น แสดงว่า logcat จะแสดงคําเตือน

การจัดการคอลเล็กชัน

ใน Android 8.0 (API ระดับ 26) มีการใช้งาน Collections.sort() ที่ด้านบนสุดของ List.sort() ในทางกลับกัน List.sort() ที่ใช้โดยค่าเริ่มต้นใน Android 7.x (API ระดับ 24 และ 25) จะเรียกว่า Collections.sort()

การเปลี่ยนแปลงนี้ช่วยให้ Collections.sort() ใช้ข้อได้เปรียบของการใช้งาน List.sort() ที่เพิ่มประสิทธิภาพได้ แต่มีข้อจำกัดต่อไปนี้

  • การใช้งาน List.sort() ต้องไม่เรียก Collections.sort() เนื่องจากจะส่งผลให้สแต็กล้นเนื่องจากการเรียกซ้ำแบบไม่สิ้นสุด แต่หากต้องการลักษณะการทำงานเริ่มต้นในListการใช้งาน คุณควรหลีกเลี่ยงการลบล้างsort()

    หากคลาสหลักใช้ sort() อย่างไม่เหมาะสม โดยทั่วไปแล้วการลบล้าง List.sort() ด้วยการติดตั้งใช้งานที่สร้างขึ้นจาก List.toArray(), Arrays.sort() และ ListIterator.set() นั้นไม่มีปัญหา เช่น

    @Override
    public void sort(Comparator<? super E> c) {
      Object[] elements = toArray();
      Arrays.sort(elements, c);
      ListIterator<E> iterator = (ListIterator<Object>) listIterator();
      for (Object element : elements) {
        iterator.next();
        iterator.set((E) element);
      }
    }

    ในกรณีส่วนใหญ่ คุณสามารถลบล้าง List.sort() ด้วยการใช้งานที่มอบสิทธิ์ให้กับการใช้งานเริ่มต้นที่แตกต่างกัน ทั้งนี้ขึ้นอยู่กับระดับ API เช่น

    @Override
    public void sort(Comparator<? super E> comparator) {
      if (Build.VERSION.SDK_INT <= 25) {
        Collections.sort(this);
      } else {
        super.sort(comparator);
      }
    }

    หากคุณทําแบบหลังเพียงเพราะต้องการมีเมธอด sort() ที่พร้อมใช้งานในทุกระดับ API ให้ลองตั้งชื่อที่ไม่ซ้ำกัน เช่น sortCompat() แทนการลบล้าง sort()

  • ตอนนี้ Collections.sort() จะนับเป็นการแก้ไขโครงสร้างในการใช้งานลิสต์ที่เรียก sort() ตัวอย่างเช่น ในแพลตฟอร์มเวอร์ชันก่อน Android 8.0 (API ระดับ 26) การวนซ้ำ ArrayList และเรียกใช้ sort() ในระหว่างการวนซ้ำจะทำให้เกิด ConcurrentModificationException หากการเรียงลำดับเสร็จสิ้นแล้วโดยการเรียกใช้ List.sort() Collections.sort() ไม่ได้ส่งข้อยกเว้น

    การเปลี่ยนแปลงนี้ทําให้ลักษณะการทํางานของแพลตฟอร์มสอดคล้องกันมากขึ้น ตอนนี้ทั้ง 2 วิธีจะให้ผลลัพธ์เป็น ConcurrentModificationException

ลักษณะการโหลดคลาส

Android 8.0 (API ระดับ 26) จะตรวจสอบว่าตัวโหลดคลาสไม่ละเมิดสมมติฐานของรันไทม์เมื่อโหลดคลาสใหม่ ระบบจะดำเนินการตรวจสอบเหล่านี้ไม่ว่าจะมีการอ้างอิงคลาสจาก Java (จาก forName()), บิตโค้ด Dalvik หรือ JNI ก็ตาม แพลตฟอร์มจะไม่สกัดกั้นการเรียกใช้โดยตรงจาก Java ไปยังเมธอด loadClass() และไม่ได้ตรวจสอบผลลัพธ์ของการเรียกดังกล่าว ลักษณะการทํางานนี้ไม่ควรส่งผลต่อการทำงานของโปรแกรมโหลดคลาสที่ทำงานอย่างถูกต้อง

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

นอกจากนี้ แพลตฟอร์มจะตรวจสอบว่าตัวบ่งชี้ของคลาสที่ขอนั้นถูกต้องด้วย การตรวจสอบนี้จะตรวจจับการเรียกใช้ JNI ที่โหลดคลาสโดยอ้อม เช่น GetFieldID() ซึ่งส่งผ่านข้อบ่งชี้ที่ไม่ถูกต้องไปยังคลาสเหล่านั้น ตัวอย่างเช่น ไม่พบช่องที่มีลายเซ็น java/lang/String เนื่องจากลายเซ็นดังกล่าวไม่ถูกต้อง ช่องนี้ควรเป็น Ljava/lang/String;

ซึ่งแตกต่างจากการเรียก JNI ไปยัง FindClass() โดยที่ java/lang/String เป็นชื่อที่สมบูรณ์ในตัวเองที่ถูกต้อง

Android 8.0 (API ระดับ 26) ไม่รองรับการที่ตัวโหลดคลาสหลายตัวพยายามกำหนดคลาสโดยใช้ออบเจ็กต์ DexFile เดียวกัน การพยายามดำเนินการดังกล่าวจะทำให้รันไทม์ Android แสดงInternalErrorข้อผิดพลาดพร้อมข้อความ "พยายามลงทะเบียนไฟล์ dex <filename> ด้วยตัวโหลดคลาสหลายรายการ"

DexFile API เลิกใช้งานแล้ว และเราขอแนะนําอย่างยิ่งให้คุณใช้คลาสโหลดเดอร์ของแพลตฟอร์มอย่างใดอย่างหนึ่ง ซึ่งรวมถึง PathClassLoader หรือ BaseDexClassLoader แทน

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

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

ข้อควรระวัง: ในแพลตฟอร์มเวอร์ชันที่ต่ำกว่า Android 8.0 (ระดับ API 26) การละเมิดข้อสมมติเหล่านี้อาจทําให้ต้องกําหนดคลาสเดียวกันหลายครั้ง กองข้อมูลเสียหายเนื่องจากความสับสนของคลาส และผลที่ไม่พึงประสงค์อื่นๆ