การเปลี่ยนแปลงลักษณะการทำงาน: แอปที่กำหนดเป้าหมายเป็น Android 15 ขึ้นไป

Android 15 มีการเปลี่ยนแปลงลักษณะการทำงานที่อาจส่งผลต่อรุ่นก่อนหน้านี้ แอปของคุณ การเปลี่ยนแปลงลักษณะการทำงานต่อไปนี้มีผลเฉพาะกับแอปที่ ที่กำหนดเป้าหมายเป็น Android 15 ขึ้นไป หากแอปกำหนดเป้าหมายเป็น Android 15 ขึ้นไป คุณควรแก้ไขแอปเพื่อรองรับพฤติกรรมเหล่านี้อย่างเหมาะสม โดยที่ ที่เกี่ยวข้อง

โปรดตรวจสอบรายการการเปลี่ยนแปลงลักษณะการทำงานที่มีผลต่อแอปทั้งหมดด้วย ที่ทำงานใน Android 15 ไม่ว่าแอปจะเป็น targetSdkVersion ใดก็ตาม

ฟังก์ชันหลัก

Android 15 ช่วยดัดแปลงหรือขยายความสามารถหลักต่างๆ ของระบบ Android

การเปลี่ยนแปลงบริการที่ทำงานอยู่เบื้องหน้า

เรากำลังทำการเปลี่ยนแปลงต่อไปนี้กับบริการที่ทำงานอยู่เบื้องหน้าใน Android 15

ลักษณะการหมดเวลาของบริการที่ทำงานอยู่เบื้องหน้าสำหรับการซิงค์ข้อมูล

Android 15 เพิ่มลักษณะการทำงานใหม่ของระยะหมดเวลาใน dataSync สำหรับการกำหนดเป้าหมายแอป Android 15 (API ระดับ 35) ขึ้นไป ลักษณะการทำงานนี้ยังมีผลกับฟิลด์ บริการที่ทำงานอยู่เบื้องหน้า mediaProcessing ประเภท

ระบบอนุญาตให้บริการของ dataSync ของแอปทำงานเป็นเวลาทั้งหมด 6 ชั่วโมง ในช่วงเวลา 24 ชั่วโมง หลังจากนั้นระบบจะเรียกใช้หมายเลข เมธอด Service.onTimeout(int, int) (เปิดตัวแล้วใน Android 15) ปัจจุบันบริการมีเวลา 2-3 วินาทีในการโทร Service.stopSelf() เมื่อมีการเรียก Service.onTimeout() พารามิเตอร์ บริการไม่ถือว่าเป็นบริการที่ทำงานอยู่เบื้องหน้าอีกต่อไป หากบริการไม่ เรียกใช้ Service.stopSelf() ระบบจะแสดงข้อผิดพลาดภายใน ระบบจะบันทึกข้อยกเว้นใน Logcat โดยมีข้อความต่อไปนี้

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

ในการหลีกเลี่ยงปัญหาการเปลี่ยนแปลงลักษณะการทำงานนี้ คุณสามารถทำ ดังต่อไปนี้:

  1. ให้บริการของคุณใช้วิธีการ Service.onTimeout(int, int) ใหม่ เมื่อแอปได้รับการติดต่อกลับ โปรดโทรหา stopSelf() ภายใน ไม่กี่วินาที (หากคุณไม่หยุดแอปในทันที ระบบจะสร้าง ไม่สำเร็จ)
  2. ตรวจสอบว่าบริการ dataSync ของแอปไม่ทำงานเป็นเวลารวม 6 ชั่วโมงในช่วง 24 ชั่วโมงใดก็ได้ (เว้นแต่ผู้ใช้จะโต้ตอบกับแอป รีเซ็ตตัวจับเวลา)
  3. เริ่มบริการที่ทำงานอยู่เบื้องหน้าของ dataSync เท่านั้นจากผู้ใช้โดยตรง การโต้ตอบ เนื่องจากแอปทำงานอยู่ในเบื้องหน้าเมื่อบริการเริ่มทำงาน บริการของคุณจะมีเวลา 6 ชั่วโมงหลังจากที่แอปทำงานอยู่เบื้องหลัง
  4. แทนที่จะใช้บริการที่ทำงานอยู่เบื้องหน้า dataSync ให้ใช้ API สำรอง

หากบริการที่ทำงานอยู่เบื้องหน้า dataSync ของแอปทำงานเป็นเวลา 6 ชั่วโมงล่าสุด 24 คุณไม่สามารถเริ่มบริการที่ทำงานอยู่เบื้องหน้า dataSync อื่นได้ เว้นแต่ผู้ใช้ ได้นำแอปของคุณมาไว้เบื้องหน้าแล้ว (ซึ่งจะรีเซ็ตตัวจับเวลา) หากคุณพยายาม เริ่มบริการที่ทำงานอยู่เบื้องหน้า dataSync อื่น ระบบแสดงข้อผิดพลาด ForegroundServiceStartNotAllowedException พร้อมข้อความแสดงข้อผิดพลาด เช่น "หมดเวลาสำหรับบริการที่ทำงานอยู่เบื้องหน้าแล้ว type dataSync"

การทดสอบ

หากต้องการทดสอบลักษณะการทำงานของแอป ให้เปิดใช้ระยะหมดเวลาการซิงค์ข้อมูล แม้ว่าแอปของคุณ ไม่ได้กําหนดเป้าหมายเป็น Android 15 (ตราบใดที่แอปยังทํางานอยู่ใน Android 15 อุปกรณ์) หากต้องการเปิดใช้ระยะหมดเวลา ให้เรียกใช้คำสั่ง adb ต่อไปนี้

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

นอกจากนี้ คุณยังสามารถปรับระยะหมดเวลา เพื่อให้ทดสอบได้ง่ายขึ้นว่า จะทำงานเมื่อถึงขีดจำกัด หากต้องการกำหนดระยะหมดเวลาใหม่ ให้เรียกใช้ คำสั่ง adb ต่อไปนี้:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

ประเภทบริการที่ทำงานอยู่เบื้องหน้าสำหรับการประมวลผลสื่อใหม่

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

ระบบอนุญาตให้บริการของ mediaProcessing ของแอปทำงานรวมได้ 6 ครั้ง ชั่วโมงในรอบ 24 ชั่วโมง ซึ่งหลังจากนั้นระบบจะเรียกใช้หมายเลข เมธอด Service.onTimeout(int, int) (เปิดตัวแล้วใน Android 15) ปัจจุบันบริการมีเวลา 2-3 วินาทีในการโทร Service.stopSelf() หากบริการไม่ เรียกใช้ Service.stopSelf() ระบบจะแสดงข้อผิดพลาดภายใน ระบบจะบันทึกข้อยกเว้นใน Logcat โดยมีข้อความต่อไปนี้

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

เพื่อหลีกเลี่ยงข้อยกเว้น คุณสามารถดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้

  1. ให้บริการของคุณใช้วิธีการ Service.onTimeout(int, int) ใหม่ เมื่อแอปได้รับการติดต่อกลับ โปรดโทรหา stopSelf() ภายใน ไม่กี่วินาที (หากคุณไม่หยุดแอปในทันที ระบบจะสร้าง ไม่สำเร็จ)
  2. ตรวจสอบว่าบริการของ mediaProcessing ของแอปไม่ทำงานเกิน รวม 6 ชั่วโมงในช่วง 24 ชั่วโมงใดก็ได้ (เว้นแต่ผู้ใช้จะโต้ตอบกับแอป รีเซ็ตตัวจับเวลา)
  3. เริ่มบริการที่ทำงานอยู่เบื้องหน้าของ mediaProcessing เท่านั้นจากผู้ใช้โดยตรง การโต้ตอบ เนื่องจากแอปทำงานอยู่ในเบื้องหน้าเมื่อบริการเริ่มทำงาน บริการของคุณจะมีเวลา 6 ชั่วโมงหลังจากที่แอปทำงานอยู่เบื้องหลัง
  4. แทนที่จะใช้บริการที่ทำงานอยู่เบื้องหน้า mediaProcessing ให้ใช้ทางเลือกอื่น API เช่น WorkManager

หากบริการที่ทำงานอยู่เบื้องหน้า mediaProcessing ของแอปทำงานเป็นเวลา 6 ชั่วโมงใน 24 วันล่าสุด คุณไม่สามารถเริ่มบริการที่ทำงานอยู่เบื้องหน้า mediaProcessing อื่นได้ เว้นแต่ ผู้ใช้นำแอปของคุณมาไว้เบื้องหน้า (ซึ่งจะรีเซ็ตตัวจับเวลา) หากคุณ ลองเริ่มบริการที่ทำงานอยู่เบื้องหน้า mediaProcessing อื่น ระบบแสดงข้อผิดพลาด ForegroundServiceStartNotAllowedException พร้อมข้อความแสดงข้อผิดพลาด เช่น "หมดเวลาสำหรับบริการที่ทำงานอยู่เบื้องหน้าแล้ว การประมวลผลสื่อ"

โปรดดูข้อมูลเพิ่มเติมเกี่ยวกับประเภทบริการ mediaProcessing ที่การเปลี่ยนแปลงกับ ประเภทบริการที่ทำงานอยู่เบื้องหน้าสำหรับ Android 15: การประมวลผลสื่อ

การทดสอบ

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

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

นอกจากนี้ คุณยังสามารถปรับระยะหมดเวลา เพื่อให้ทดสอบได้ง่ายขึ้นว่า จะทำงานเมื่อถึงขีดจำกัด หากต้องการกำหนดระยะหมดเวลาใหม่ ให้เรียกใช้ คำสั่ง adb ต่อไปนี้:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

ข้อจำกัดเกี่ยวกับ Broadcast Receiver ของ BOOT_COMPLETED ที่เปิดตัวบริการที่ทำงานอยู่เบื้องหน้า

มีข้อจำกัดใหม่ในการเปิดตัว Broadcast Receiver ของ BOOT_COMPLETED บริการที่ทำงานอยู่เบื้องหน้า ระบบไม่อนุญาตให้ Receiver BOOT_COMPLETED เปิดบริการที่ทำงานอยู่เบื้องหน้าประเภทต่อไปนี้

หากตัวรับสัญญาณ BOOT_COMPLETED พยายามเปิดเบื้องหน้าประเภทใดก็ตามเหล่านี้ ระบบอาจไม่แสดง ForegroundServiceStartNotAllowedException

การทดสอบ

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

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

หากต้องการส่งประกาศBOOT_COMPLETEDโดยไม่ต้องรีสตาร์ทอุปกรณ์ ให้ทำดังนี้ เรียกใช้คำสั่ง adb ต่อไปนี้

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

ข้อจำกัดเกี่ยวกับการเริ่มบริการที่ทำงานอยู่เบื้องหน้าในขณะที่แอปถือสิทธิ์ SYSTEM_ALERT_WINDOW

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

หากแอปกำหนดเป้าหมายเป็น Android 15 การยกเว้นนี้จะแคบลงแล้ว ตอนนี้แอปต้องใช้ มีสิทธิ์ SYSTEM_ALERT_WINDOW และและมีการวางซ้อนที่มองเห็นได้ กล่าวคือ แอปจะต้องเปิดใช้งาน หน้าต่าง TYPE_APPLICATION_OVERLAY และ หน้าต่าง ต้องมองเห็นได้ก่อนเริ่มบริการที่ทำงานอยู่เบื้องหน้า

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

หากแอปประกาศสิทธิ์ SYSTEM_ALERT_WINDOW และเปิดใช้บริการที่ทำงานอยู่เบื้องหน้าจากเบื้องหลัง ก็อาจได้รับผลกระทบจากการเปลี่ยนแปลงนี้ เปลี่ยน หากแอปได้รับForegroundServiceStartNotAllowedException ให้ตรวจสอบ ลำดับการดำเนินการของแอป และตรวจสอบว่าแอปมี หน้าต่างที่วางซ้อนก่อนที่จะพยายามเริ่มบริการที่ทำงานอยู่เบื้องหน้าจาก พื้นหลัง คุณสามารถตรวจสอบได้ว่าหน้าต่างที่วางซ้อนของคุณปรากฏให้เห็นอยู่หรือไม่ โดยโทรไปที่ View.getWindowVisibility() หรือคุณ สามารถลบล้าง View.onWindowVisibilityChanged() เพื่อรับการแจ้งเตือนเมื่อมีการเปลี่ยนแปลงระดับการเข้าถึง

การทดสอบ

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

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

การเปลี่ยนแปลงเวลาที่แอปแก้ไขสถานะทั่วไปของโหมดห้ามรบกวนได้

Apps that target Android 15 (API level 35) and higher can no longer change the global state or policy of Do Not Disturb (DND) on a device (either by modifying user settings, or turning off DND mode). Instead, apps must contribute an AutomaticZenRule, which the system combines into a global policy with the existing most-restrictive-policy-wins scheme. Calls to existing APIs that previously affected global state (setInterruptionFilter, setNotificationPolicy) result in the creation or update of an implicit AutomaticZenRule, which is toggled on and off depending on the call-cycle of those API calls.

Note that this change only affects observable behavior if the app is calling setInterruptionFilter(INTERRUPTION_FILTER_ALL) and expects that call to deactivate an AutomaticZenRule that was previously activated by their owners.

การเปลี่ยนแปลง OpenJDK API

Android 15 สานต่อการปรับปรุงไลบรารีหลักของ Android ให้สอดคล้องกัน ด้วยฟีเจอร์ใน OpenJDK LTS รุ่นล่าสุด

การเปลี่ยนแปลงเหล่านี้บางส่วนอาจส่งผลต่อความเข้ากันได้ของแอปสำหรับการกำหนดเป้าหมายแอป Android 15 (API ระดับ 35):

  • การเปลี่ยนแปลง API การจัดรูปแบบสตริง: การตรวจสอบดัชนีอาร์กิวเมนต์ แฟล็ก ความกว้าง และความแม่นยำจะเข้มงวดมากขึ้นเมื่อใช้สิ่งต่อไปนี้ String.format() และ Formatter.format() API:

    ตัวอย่างเช่น มีข้อยกเว้นต่อไปนี้เมื่อดัชนีอาร์กิวเมนต์ 0 ใช้ (%0 ในสตริงรูปแบบ):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    ในกรณีนี้ ปัญหาสามารถแก้ไขได้โดยใช้ดัชนีอาร์กิวเมนต์ 1 (%1 ในสตริงรูปแบบ)

  • การเปลี่ยนแปลงประเภทคอมโพเนนต์ของ Arrays.asList(...).toArray(): เมื่อใช้ Arrays.asList(...).toArray() ประเภทคอมโพเนนต์ของอาร์เรย์ผลลัพธ์คือ เปลี่ยนเป็น Object ไม่ใช่ประเภทเอลิเมนต์ของอาร์เรย์ที่สำคัญ ดังนั้น โค้ดต่อไปนี้มีการส่ง ClassCastException

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    สำหรับกรณีนี้ เพื่อรักษา String เป็นประเภทคอมโพเนนต์ในผลลัพธ์ ใหม่ คุณสามารถใช้ Collection.toArray(Object[]) แทน ดังนี้

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • การเปลี่ยนแปลงการจัดการโค้ดภาษา: เมื่อใช้ Locale API ระบบจะไม่แปลงรหัสภาษาสำหรับฮิบรู ยิดดิช และอินโดนีเซียอีกต่อไป เป็นรูปแบบที่ล้าสมัยแล้ว (ฮิบรู: iw, ยิดดิช: ji และอินโดนีเซีย: in) เมื่อระบุรหัสภาษาสำหรับภาษาเหล่านี้ ให้ใช้รหัส จาก ISO 639-1 แทน (ฮิบรู: he, ยิดดิช: yi และอินโดนีเซีย: id)

  • การเปลี่ยนแปลงลำดับ in แบบสุ่ม: ติดตามผลการเปลี่ยนแปลงที่ทำใน https://bugs.openjdk.org/browse/JDK-8301574 ดังต่อไปนี้ ตอนนี้เมธอด Random.ints() แสดงผลลำดับตัวเลขที่แตกต่างจาก เมธอด Random.nextInt() จะทำงานดังนี้

    โดยทั่วไปแล้ว การเปลี่ยนแปลงนี้ไม่ควรส่งผลให้เกิดลักษณะการทำงานของแอปขัดข้อง แต่ โค้ดไม่ควรคาดหวังลำดับที่สร้างจากเมธอด Random.ints() ไปยัง ตรงกับ Random.nextInt()

SequencedCollection API ใหม่อาจส่งผลต่อความเข้ากันได้ของแอป หลังจากที่คุณอัปเดต compileSdk ในการกำหนดค่าบิลด์ของแอปเพื่อใช้ Android 15 (API ระดับ 35):

  • การทับซ้อนกับ MutableList.removeFirst() และ ฟังก์ชันส่วนขยาย MutableList.removeLast() ใน kotlin-stdlib

    ประเภท List ใน Java จะแมปกับประเภท MutableList ใน Kotlin เนื่องจาก API ของ List.removeFirst() และ List.removeLast() เปิดตัวใน Android 15 (API ระดับ 35) ซึ่งคอมไพเลอร์ Kotlin แปลค่าการเรียกฟังก์ชัน เช่น list.removeFirst() แบบคงที่ไปยังฟังก์ชัน API ใหม่ของ List แทนฟังก์ชันของส่วนขยายใน kotlin-stdlib

    หากแอปได้รับการคอมไพล์อีกครั้งโดยตั้งค่า compileSdk เป็น 35 และ minSdk ตั้งค่าเป็น 34 หรือต่ำกว่า แล้วแอปจะทำงานใน Android 14 และต่ำกว่า ซึ่งเป็นรันไทม์ มีข้อผิดพลาด:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    ตัวเลือก Lint NewApi ที่มีอยู่ในปลั๊กอิน Android Gradle ตรวจจับเหตุการณ์เหล่านี้ได้ การใช้งาน API ใหม่ๆ

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    หากต้องการแก้ไขข้อผิดพลาดรันไทม์และข้อผิดพลาดของโปรแกรม Linux ไฟล์ removeFirst() และ การเรียกฟังก์ชัน removeLast() สามารถแทนที่ด้วย removeAt(0) และ removeAt(list.lastIndex) ตามลำดับใน Kotlin หากคุณกำลังใช้ Ladybug ของ Android Studio | 2024.1.3 ขึ้นไป ยังช่วยแก้ปัญหาได้อย่างรวดเร็วด้วย เพื่อหาข้อผิดพลาดเหล่านี้

    ลองนำ @SuppressLint("NewApi") และ lintOptions { disable 'NewApi' } ออกหากปิดใช้ตัวเลือก Lint ไว้

  • การทับซ้อนกับวิธีการอื่นๆ ใน Java

    มีการเพิ่มเมธอดใหม่ลงในประเภทที่มีอยู่ เช่น List และ Deque เมธอดใหม่เหล่านี้อาจเข้ากันไม่ได้ ด้วยเมธอดที่มีชื่อและประเภทอาร์กิวเมนต์เหมือนกันในอินเทอร์เฟซอื่นๆ และชั้นเรียนต่างๆ ในกรณีที่ลายเซ็นเมธอดขัดแย้งกัน ความไม่เข้ากัน คอมไพเลอร์ javac จะแสดงผลข้อผิดพลาดเกี่ยวกับเวลาบิลด์ สำหรับ ตัวอย่าง:

    ข้อผิดพลาดตัวอย่าง 1

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    ข้อผิดพลาดตัวอย่าง 2

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    ข้อผิดพลาดตัวอย่าง 3

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    ในการแก้ไขข้อผิดพลาดของรุ่นเหล่านี้ คลาสที่ใช้อินเทอร์เฟซเหล่านี้ควร ลบล้างเมธอดด้วยประเภทผลลัพธ์ที่เข้ากันได้ เช่น

    @Override
    public Object getFirst() {
        return List.super.getLast();
    }
    

ความปลอดภัย

Android 15 มีการเปลี่ยนแปลงที่ส่งเสริมความปลอดภัยของระบบเพื่อช่วยปกป้องแอป และผู้ใช้จากแอปที่เป็นอันตราย

การเปิดตัวกิจกรรมในเบื้องหลังที่ปลอดภัย

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

บล็อกแอปที่ไม่ตรงกับ UID ด้านบนในสแต็กไม่ให้เปิดใช้กิจกรรม

แอปที่เป็นอันตรายสามารถเปิดกิจกรรมของแอปอื่นภายในงานเดียวกันได้ จากนั้น วางซ้อนตัวเองทับด้านบน สร้างภาพลวงตาว่าเป็นแอปดังกล่าว งานนี้ "งาน" การปล้น" เจาะข้ามผ่านข้อจำกัด การเปิดตัวในเบื้องหลัง จะเกิดขึ้นภายในงานเดียวกันที่มองเห็น เพื่อลดความเสี่ยงนี้ Android 15 จึงเพิ่ม แฟล็กที่บล็อกแอปที่ไม่ตรงกับ UID บนสุดในสแต็กไม่ให้เริ่มทำงาน กิจกรรม หากต้องการเลือกใช้กิจกรรมทั้งหมดของแอป ให้อัปเดต allowCrossUidActivitySwitchFromBelow ในไฟล์ AndroidManifest.xml ของแอป

<application android:allowCrossUidActivitySwitchFromBelow="false" >

เราจะใช้มาตรการรักษาความปลอดภัยใหม่หากทุกเงื่อนไขต่อไปนี้เป็นจริง

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

หากเปิดใช้มาตรการรักษาความปลอดภัย แอปอาจกลับไปยังหน้าแรก แทนที่จะเป็น แอปที่ปรากฏล่าสุด ถ้าพวกเขาทำงานของตัวเองเสร็จแล้ว

การเปลี่ยนแปลงอื่นๆ

นอกจากข้อจำกัดสำหรับการจับคู่ UID แล้ว การเปลี่ยนแปลงอื่นๆ เหล่านี้ยัง รวม:

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

Intent ที่ปลอดภัยขึ้น

Android 15 เปิดตัวมาตรการรักษาความปลอดภัยใหม่เพื่อให้ความตั้งใจปลอดภัยและปลอดภัยยิ่งขึ้น แข็งแกร่ง การเปลี่ยนแปลงเหล่านี้มีวัตถุประสงค์เพื่อป้องกันช่องโหว่ที่อาจเกิดขึ้น และ การใช้ความตั้งใจในทางที่ผิดซึ่งอาจแสวงหาประโยชน์จากแอปที่เป็นอันตราย ซึ่งมี 2 ผลิตภัณฑ์หลัก การปรับปรุงความปลอดภัยของ Intent ใน Android 15 มีดังนี้

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

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

ประสบการณ์ของผู้ใช้และ UI ของระบบ

Android 15 มีการเปลี่ยนแปลงบางอย่างที่มีไว้เพื่อให้มีความสอดคล้องกันมากขึ้น ที่ใช้งานง่ายขึ้น

การเปลี่ยนแปลงช่วงกรอบเวลา

There are two changes related to window insets in Android 15: edge-to-edge is enforced by default, and there are also configuration changes, such as the default configuration of system bars.

การบังคับใช้แบบไร้ขอบ

แอปจะเป็นแบบไร้ขอบโดยค่าเริ่มต้นในอุปกรณ์ที่ใช้ Android 15 หากแอปเป็นแบบ ที่กำหนดเป้าหมายเป็น Android 15 (API ระดับ 35)

วันที่
แอปที่กำหนดเป้าหมายเป็น Android 14 และไม่ได้มีเนื้อหาแบบไร้ขอบใน อุปกรณ์ Android 15


แอปที่กำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) และทำงานแบบไร้ขอบ ในอุปกรณ์ Android 15 แอปนี้ใช้คอมโพเนนต์ Compose ใน Material 3 เป็นส่วนใหญ่ ที่ใช้ส่วนแทรกโดยอัตโนมัติ หน้าจอนี้ไม่ได้รับผลกระทบเชิงลบจาก การบังคับใช้แบบไร้ขอบของ Android 15

นี่เป็นการเปลี่ยนแปลงที่ส่งผลกับส่วนอื่นในระบบซึ่งอาจส่งผลในแง่ลบต่อ UI ของแอป การเปลี่ยนแปลงจะส่งผลต่อ UI ต่อไปนี้

  • แถบนำทางสำหรับแฮนเดิลด้วยท่าทางสัมผัส
    • โปร่งใสโดยค่าเริ่มต้น
    • ออฟเซ็ตด้านล่างปิดใช้อยู่เพื่อให้แสดงเนื้อหาด้านหลังการนำทางของระบบ ยกเว้นกรณีที่มีการใช้ส่วนแทรก
    • setNavigationBarColor และ R.attr#navigationBarColor และไม่มีผลต่อการนำทางโดยใช้ท่าทางสัมผัส
    • setNavigationBarContrastEnforced และ R.attr#navigationBarContrastEnforced จะไม่มีผลกับ การนำทางด้วยท่าทางสัมผัส
  • การนำทางแบบ 3 ปุ่ม
    • ความทึบแสงจะตั้งไว้ที่ 80% โดยค่าเริ่มต้น โดยอาจมีสีที่เข้ากับหน้าต่าง พื้นหลัง
    • ปิดใช้ออฟเซ็ตด้านล่างเพื่อให้วาดเนื้อหาอยู่หลังแถบนำทางของระบบ ยกเว้นกรณีที่มีการใช้ส่วนแทรก
    • setNavigationBarColor และ R.attr#navigationBarColor ตั้งค่าให้ตรงกับพื้นหลังของหน้าต่างโดยค่าเริ่มต้น พื้นหลังหน้าต่าง ต้องเป็นสีที่วาดได้เพื่อใช้ค่าเริ่มต้นนี้ API นี้ เลิกใช้งานแล้ว แต่ยังคงมีผลกับการนำทางแบบ 3 ปุ่มอยู่
    • setNavigationBarContrastEnforced และ R.attr#navigationBarContrastEnforced เป็นจริงโดยค่าเริ่มต้น ซึ่งจะเพิ่มค่า พื้นหลังทึบแสง 80% บนการนำทางแบบ 3 ปุ่ม
  • แถบสถานะ
    • โปร่งใสโดยค่าเริ่มต้น
    • ออฟเซ็ตด้านบนถูกปิดใช้งาน ดังนั้นเนื้อหาจะแสดงอยู่หลังแถบสถานะ ยกเว้น มีการใช้ส่วนเกิน
    • setStatusBarColor และ R.attr#statusBarColor เลิกใช้งานแล้วและไม่มีผลกับ Android 15
    • setStatusBarContrastEnforced และ R.attr#statusBarContrastEnforced เลิกใช้งานแล้วแต่ยังมี ผลกระทบใน Android 15
  • หน้าจอรอยบาก
    • layoutInDisplayCutoutMode ของหน้าต่างที่ไม่ใช่แบบลอยต้องเป็น LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS SHORT_EDGES, NEVER และ ระบบจะตีความ DEFAULT เป็น ALWAYS เพื่อให้ผู้ใช้ไม่เห็น ที่เกิดจากหน้าจอรอยบากและปรากฏเป็นขอบสุด

ตัวอย่างต่อไปนี้แสดงแอปก่อนและหลังการกำหนดเป้าหมาย Android 15 (API ระดับ 35) และก่อนและหลังใช้ชุดเนื้อหา

วันที่
แอปที่กำหนดเป้าหมายเป็น Android 14 และไม่ได้มีเนื้อหาแบบไร้ขอบใน อุปกรณ์ Android 15
แอปที่กำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) และทำงานแบบไร้ขอบ ในอุปกรณ์ Android 15 แต่องค์ประกอบหลายรายการจะซ่อนไว้โดยสถานะ แถบ แถบนำทางแบบ 3 ปุ่ม หรือหน้าจอรอยบากเนื่องจาก Android 15 การบังคับใช้แบบไร้ขอบเขต UI ที่ซ่อนอยู่มี Material 2 แถบแอปด้านบน ปุ่มการทำงานแบบลอย และรายการ
แอปที่กำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) เป็นแอปที่ล้ำสมัย อุปกรณ์ Android 15 และใส่ส่วนเพิ่มเติมเพื่อไม่ให้ UI ซ่อนอยู่
สิ่งที่ต้องตรวจสอบว่าแอปของคุณเชื่อมต่อแบบไร้ขอบอยู่แล้วคืออะไร

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

  • คุณมีหน้าต่างที่ไม่ใช่แบบลอย เช่น Activity ที่ใช้ SHORT_EDGES, NEVER หรือ DEFAULT แทน LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS หากแอปขัดข้องเมื่อเปิดใช้งาน ก็เพราะหน้าจอแนะนำ คุณสามารถอัปเกรดแท็ก การใช้หน้าจอแนะนำกับ 1.2.0-alpha01 ขึ้นไป หรือตั้งค่า window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
  • อาจมีหน้าจอที่มีผู้ใช้งานจำนวนน้อยและมี UI ที่บังอยู่ ตรวจสอบรายการเหล่านี้ หน้าจอที่มีการเข้าชมน้อยจะไม่มี UI ที่ปิดกั้น หน้าจอที่มีจำนวนการเข้าชมต่ำประกอบด้วย
    • หน้าจอการเริ่มต้นใช้งานหรือลงชื่อเข้าใช้
    • หน้าการตั้งค่า
สิ่งที่ต้องตรวจสอบหากแอปของคุณไม่ได้เผยแพร่แบบ Edge to EDGE อยู่แล้ว

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

  • หากแอปใช้คอมโพเนนต์ Material 3 ( androidx.compose.material3) ในการเขียน เช่น TopAppBar, BottomAppBar และ NavigationBar องค์ประกอบเหล่านี้ไม่ จะได้รับผลกระทบเพราะจะจัดการกับส่วนแทรกโดยอัตโนมัติ
  • หากแอปใช้คอมโพเนนต์ Material 2 ( androidx.compose.material) ใน Compose คอมโพเนนต์เหล่านี้ ไม่จัดการส่วนแทรกโดยอัตโนมัติ อย่างไรก็ตาม คุณสามารถเข้าถึงเนื้อหาต่างๆ ได้ และนำไปใช้ด้วยตนเอง ใน androidx.compose.material 1.6.0 และหลังจากนั้น ให้ใช้พารามิเตอร์ windowInsets เพื่อใช้ส่วนแทรกด้วยตนเองสำหรับ BottomAppBar, TopAppBar BottomNavigation และ NavigationRail ในทำนองเดียวกัน ให้ใช้พารามิเตอร์ contentWindowInsets สำหรับ Scaffold
  • หากแอปใช้มุมมองและคอมโพเนนต์เนื้อหา (com.google.android.material) เนื้อหาที่อิงตามยอดดูมากที่สุด คอมโพเนนต์ เช่น BottomNavigationView, BottomAppBar, NavigationRailView หรือ NavigationView จัดการส่วนแทรกและไม่ต้อง งานเพิ่มเติม อย่างไรก็ตาม คุณจำเป็นต้องเพิ่ม android:fitsSystemWindows="true" หากใช้ AppBarLayout
  • สำหรับ Composable ที่กำหนดเอง ให้ใช้ส่วนที่แทรกด้วยตนเองเป็นระยะห่างจากขอบ หาก เนื้อหาอยู่ภายใน Scaffold คุณสามารถใช้เซ็ตต่างๆ ได้โดยใช้ Scaffold ค่า Padding หรือไม่เช่นนั้น ให้ใช้ระยะห่างจากขอบโดยใช้ WindowInsets
  • หากแอปใช้ข้อมูลพร็อพเพอร์ตี้และ BottomSheet, SideSheet หรือกำหนดเอง เพิ่มระยะห่างจากขอบด้วย ViewCompat.setOnApplyWindowInsetsListener สำหรับ RecyclerView ใส่ระยะห่างจากขอบโดยใช้ Listener นี้และเพิ่ม clipToPadding="false"
สิ่งที่ต้องตรวจสอบว่าแอปต้องมีการปกป้องพื้นหลังที่กำหนดเองหรือไม่

หากแอปต้องมีการปกป้องที่กำหนดเองในเบื้องหลังสำหรับการนำทางแบบ 3 ปุ่ม หรือ แถบสถานะ คุณควรวาง Composable หรือมุมมองไว้หลังแถบระบบ โดยใช้ WindowInsets.Type#tappableElement() เพื่อใช้งานแบบ 3 ปุ่ม ความสูงของแถบนำทางหรือ WindowInsets.Type#statusBars

ทรัพยากรเพิ่มเติมแบบไร้ขอบ

โปรดดูมุมมอง Edge to Edge และ Edge to Edge Compose คำแนะนำสำหรับข้อควรพิจารณาเพิ่มเติมเกี่ยวกับการใช้ส่วนแทรก

API ที่เลิกใช้งานแล้ว

API ต่อไปนี้เลิกใช้งานแล้ว

การกำหนดค่าที่เสถียร

หากแอปกำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) ขึ้นไป Configuration ไม่ควร ที่ไม่มีแถบระบบอีกต่อไป หากคุณใช้ขนาดหน้าจอในคลาส Configuration สำหรับการคำนวณเลย์เอาต์ คุณควรแทนที่ด้วยทางเลือกที่ดีกว่า เช่น ViewGroup, WindowInsets หรือ WindowMetricsCalculator ที่เหมาะสม ทั้งนี้ขึ้นอยู่กับความต้องการ

Configuration เปิดให้ใช้งานแล้วตั้งแต่ API 1 โดยปกติแล้วจะได้รับจาก Activity.onConfigurationChanged โดยจะให้ข้อมูล เช่น ความหนาแน่นของหน้าต่าง การวางแนว และขนาด ลักษณะสำคัญอย่างหนึ่งของขนาดหน้าต่าง แสดงผลจาก Configuration คือได้ยกเว้นแถบระบบก่อนหน้านี้

โดยปกติแล้วขนาดการกําหนดค่าจะใช้สําหรับการเลือกทรัพยากร เช่น /res/layout-h500dp และนี่ยังคงเป็นกรณีการใช้งานที่ถูกต้อง แต่การใช้งานสำหรับ ไม่สนับสนุนการคำนวณการจัดวาง หากคุณทำเช่นนั้น คุณควรย้าย ออกจากแชทนี้เดี๋ยวนี้ คุณควรแทนที่การใช้ Configuration ด้วยเนื้อหา เหมาะสมมากขึ้น ขึ้นอยู่กับกรณีการใช้งานของคุณ

หากใช้เพื่อคํานวณเลย์เอาต์ ให้ใช้ ViewGroup ที่เหมาะสม เช่น CoordinatorLayout หรือ ConstraintLayout ถ้าคุณใช้เพื่อหาความสูง ของแถบนำทางของระบบ ให้ใช้ WindowInsets หากต้องการทราบขนาดปัจจุบันของหน้าต่างแอป ให้ใช้ computeCurrentWindowMetrics

รายการต่อไปนี้จะอธิบายช่องต่างๆ ที่ได้รับผลกระทบจากการเปลี่ยนแปลงนี้

  • ขนาด Configuration.screenWidthDp และ screenHeightDp ใช้ไม่ได้แล้ว ไม่รวมแถบระบบ
  • Configuration.smallestScreenWidthDp ได้รับผลกระทบโดยอ้อมจากการเปลี่ยนแปลงscreenWidthDpและscreenHeightDp
  • Configuration.orientation ได้รับผลกระทบทางอ้อมจากการเปลี่ยนแปลงของ screenWidthDp และ screenHeightDp ในอุปกรณ์ที่ใกล้สี่เหลี่ยมจัตุรัส
  • Display.getSize(Point) ได้รับผลกระทบโดยอ้อมจากการเปลี่ยนแปลงใน Configuration เราเลิกใช้งานฟีเจอร์นี้ตั้งแต่ API ระดับ 30
  • Display.getMetrics() ทำงานแบบนี้มาตั้งแต่ API ระดับ 33

แอตทริบิวต์ DesignedTextHeight มีค่าเริ่มต้นเป็น true

For apps targeting Android 15 (API level 35), the elegantTextHeight TextView attribute becomes true by default, replacing the compact font used by default with some scripts that have large vertical metrics with one that is much more readable. The compact font was introduced to prevent breaking layouts; Android 13 (API level 33) prevents many of these breakages by allowing the text layout to stretch the vertical height utilizing the fallbackLineSpacing attribute.

In Android 15, the compact font still remains in the system, so your app can set elegantTextHeight to false to get the same behavior as before, but it is unlikely to be supported in upcoming releases. So, if your app supports the following scripts: Arabic, Lao, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Odia, Telugu or Thai, test your app by setting elegantTextHeight to true.

elegantTextHeight behavior for apps targeting Android 14 (API level 34) and lower.
elegantTextHeight behavior for apps targeting Android 15.

TextView ที่เปลี่ยนแปลงความกว้างของรูปร่างตัวอักษรที่ซับซ้อน

ใน Android เวอร์ชันก่อนหน้า แบบอักษรหรือภาษาแบบตัวเขียนบางแบบที่มี รูปร่างที่ซับซ้อนอาจวาดตัวอักษรในพื้นที่ของอักขระก่อนหน้าหรือถัดไป ในบางกรณี ตัวอักษรเหล่านั้นอาจถูกตัดออกตั้งแต่จุดเริ่มต้นหรือจุดสิ้นสุด ตั้งแต่ Android 15 เป็นต้นไป TextView จะจัดสรรความกว้างเพื่อให้มีพื้นที่เพียงพอ สำหรับตัวอักษรเหล่านั้น และอนุญาตให้แอปขอระยะห่างจากขอบด้านซ้ายเพิ่มขึ้นเพื่อ เพื่อป้องกันการตัด

เนื่องจากการเปลี่ยนแปลงนี้ส่งผลต่อวิธีที่ TextView กำหนดความกว้าง TextView จัดสรรความกว้างมากขึ้นโดยค่าเริ่มต้นหากแอปกำหนดเป้าหมายเป็น Android 15 (API ระดับ 35) หรือ สูงขึ้น คุณสามารถเปิดหรือปิดการทำงานนี้โดยเรียกใช้ setUseBoundsForWidth API ใน TextView

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

ตัวอย่างต่อไปนี้แสดงให้เห็นว่าการเปลี่ยนแปลงเหล่านี้จะช่วยปรับปรุงเลย์เอาต์ข้อความสำหรับ แบบอักษรและภาษา

เลย์เอาต์มาตรฐานสำหรับข้อความภาษาอังกฤษในแบบอักษรที่ตัวห้อย บางส่วนของ ตัวอักษรจะถูกตัด นี่คือ XML ที่เกี่ยวข้อง:

วันที่
<TextView
    android:fontFamily="cursive"
    android:text="java" />
การจัดวางข้อความภาษาอังกฤษเดียวกันที่มีความกว้างเพิ่มเติมและ ระยะห่างจากขอบ นี่คือ XML ที่เกี่ยวข้อง:

วันที่
<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
รูปแบบมาตรฐานสำหรับข้อความภาษาไทย ตัวอักษรบางตัวถูกตัด นี่คือ XML ที่เกี่ยวข้อง:

วันที่
<TextView
    android:text="คอมพิวเตอร์" />
การจัดวางข้อความภาษาไทยเดียวกันโดยมีความกว้างเพิ่มเติมและ ระยะห่างจากขอบ นี่คือ XML ที่เกี่ยวข้อง:

วันที่
<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

ความสูงของบรรทัดเริ่มต้นที่รับรู้ภาษาสำหรับ EditText

In previous versions of Android, the text layout stretched the height of the text to meet the line height of the font that matched the current locale. For example, if the content was in Japanese, because the line height of the Japanese font is slightly larger than the one of a Latin font, the height of the text became slightly larger. However, despite these differences in line heights, the EditText element was sized uniformly, regardless of the locale being used, as illustrated in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText is the same, even though these languages have different line heights from each other.

For apps targeting Android 15 (API level 35), a minimum line height is now reserved for EditText to match the reference font for the specified Locale, as shown in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText now includes space to accommodate the default line height for these languages' fonts.

If needed, your app can restore the previous behavior by specifying the useLocalePreferredLineHeightForMinimum attribute to false, and your app can set custom minimum vertical metrics using the setMinimumFontMetrics API in Kotlin and Java.

กล้องและสื่อ

Android 15 เปลี่ยนแปลงลักษณะการทํางานของกล้องและสื่อสําหรับแอปดังต่อไปนี้ ที่กำหนดเป้าหมายเป็น Android 15 ขึ้นไป

ข้อจำกัดเกี่ยวกับการขอโฟกัสเสียง

Apps that target Android 15 (API level 35) must be the top app or running a foreground service in order to request audio focus. If an app attempts to request focus when it does not meet one of these requirements, the call returns AUDIOFOCUS_REQUEST_FAILED.

You can learn more about audio focus at Manage audio focus.

ข้อจำกัดที่ไม่ใช่ SDK ที่อัปเดต

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

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

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

To learn more about the changes in this release of Android, see Updates to non-SDK interface restrictions in Android 15. To learn more about non-SDK interfaces generally, see Restrictions on non-SDK interfaces.