การเปลี่ยนแปลงลักษณะการทํางาน: แอปทั้งหมด

แพลตฟอร์ม Android 17 มีการเปลี่ยนแปลงลักษณะการทำงานที่อาจส่งผลต่อแอปของคุณ การเปลี่ยนแปลงลักษณะการทำงานต่อไปนี้จะมีผลกับแอปทั้งหมดเมื่อทำงานบน Android 17 ไม่ว่าtargetSdkVersion จะเป็นอะไรก็ตาม คุณควรทดสอบแอป แล้วแก้ไข ตามที่จำเป็นเพื่อรองรับการเปลี่ยนแปลงเหล่านี้ หากเกี่ยวข้อง

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

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

Android 17 (API ระดับ 37) มีการเปลี่ยนแปลงต่อไปนี้ซึ่งจะแก้ไขหรือ ขยายความสามารถหลักต่างๆ ของระบบ Android

การจำกัดการใช้หน่วยความจำของแอป

Android 17 introduces app memory limits based on the device's total RAM to create a more stable and deterministic environment for your apps and Android users. In Android 17, limits are set conservatively to establish system baselines, targeting extreme memory leaks and other outliers before they trigger system-wide instability resulting in UI stuttering, higher battery drain, and apps being killed. While we anticipate minimal impact on the vast majority of app sessions, we recommend the following memory best practices, including establishing a baseline for memory.

You can determine if your app session was impacted by calling getDescription in ApplicationExitInfo; if your app was affected, the exit reason will be REASON_OTHER and the description will contain the string "MemoryLimiter:AnonSwap" along with other information. You can also use trigger-based profiling with TRIGGER_TYPE_ANOMALY to get heap dumps that are collected when the memory limit is hit.

The Manage your app's memory documentation gives information to help you diagnose your app's memory issues and optimize its resource consumption.

Test your app's behavior under the memory constraints

You can use Android Debug Bridge (adb) to adjust or disable the memory limits on any device that imposes them. The shell command am provides three subcommands to adjust the memory limits. (These commands have no effect on a device which does not impose memory limits.)

  • am memory-limiter ignore <uid>|none|all
  • am memory-limiter manual <pid> <limit>|max|none
  • am memory-limiter status
ignore

Instructs the memory limiter to ignore some or all processes. Passing a UID (Android User ID) instructs the memory limiter to ignore enforcement on all processes associated with that UID. You can also pass all (ignore all apps) or none (do not ignore any apps). Passing none overrides any previous calls to am memory-limiter ignore.

If you instruct the memory limiter to ignore a UID, you can still apply a manual memory limit to a process within the app by calling am memory-limiter manual.

manual

Instructs the system to impose a memory constraint on the process with the specified PID (Process ID). The memory constraint is specified as an integer number of MB; for example, passing 30 specifies that the process is limited to 30 MB of memory. Passing max removes all memory limits on that process. Passing none removes any manual limits set on the process, restoring the system's default limit (if any).

status

Reports the current status of the memory limiter. The status includes the memory limits imposed on visible and non-visible processes.

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

Android 17 มีการเปลี่ยนแปลงต่อไปนี้เพื่อปรับปรุงความเป็นส่วนตัวของผู้ใช้

การป้องกัน OTP ทาง SMS

ตั้งแต่ Android 17 เป็นต้นไป Android จะขยายการปกป้อง ข้อความ SMS ที่มีรหัสผ่านที่สามารถใช้งานได้เพียงครั้งเดียว (OTP)

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

ตั้งแต่ Android 17 เป็นต้นไป การป้องกันจะใช้กับข้อความรูปแบบ WebOTP ด้วย หากแอปมีสิทธิ์อ่านข้อความ SMS แต่ไม่ใช่ ผู้รับข้อความ WebOTP ที่ตั้งใจไว้ (ตามที่กำหนดโดยการยืนยันโดเมน) แอปจะเข้าถึงข้อความไม่ได้จนกว่าจะผ่านไป 3 ชั่วโมงหลังจากได้รับข้อความ การเปลี่ยนแปลงนี้มีวัตถุประสงค์เพื่อปรับปรุงความปลอดภัยของผู้ใช้โดยการตรวจสอบว่ามีเพียงแอปที่เชื่อมโยงกับโดเมนที่ระบุในข้อความเท่านั้นที่สามารถอ่านรหัสยืนยันโดยอัตโนมัติได้

ในระหว่างการหน่วงเวลา 3 ชั่วโมงนี้ ระบบจะระงับการออกอากาศของ SMS_RECEIVED_ACTION และกรองการค้นหาฐานข้อมูลของผู้ให้บริการ SMS ข้อความ SMS จะพร้อมใช้งานในแอปเหล่านี้หลังจากผ่านไประยะเวลาหนึ่ง การเปลี่ยนแปลงนี้จะมีผลกับแอปทั้งหมด ไม่ว่าระดับ API เป้าหมายจะเป็นเท่าใดก็ตาม

แอปบางแอป เช่น แอปผู้ช่วย SMS เริ่มต้น แอปคู่ของอุปกรณ์ที่เชื่อมต่อ ฯลฯ จะได้รับการยกเว้นจากความล่าช้านี้ แอปทั้งหมดที่ต้องอ่านข้อความ SMS เพื่อดึงข้อมูล OTP ควรเปลี่ยนไปใช้ API SMS Retriever หรือ SMS User Consent เพื่อให้มั่นใจว่าฟังก์ชันการทำงานจะดำเนินต่อไปได้

ความปลอดภัย

Android 17 มีการปรับปรุงความปลอดภัยของอุปกรณ์และแอป ดังต่อไปนี้

แผนการเลิกใช้งาน usesClearTraffic

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

โปรดทราบว่าไฟล์การกำหนดค่าความปลอดภัยของเครือข่ายใช้ได้ใน API ระดับ 24 ขึ้นไปเท่านั้น หากแอปมีระดับ API ขั้นต่ำต่ำกว่า 24 คุณควรทำทั้ง 2 อย่างต่อไปนี้

  • ตั้งค่าแอตทริบิวต์ usesCleartextTraffic เป็น true
  • ใช้ไฟล์การกำหนดค่าเครือข่าย

หากระดับ API ขั้นต่ำของแอปคือ 24 ขึ้นไป คุณจะใช้ไฟล์การกำหนดค่าเครือข่ายได้และไม่จำเป็นต้องตั้งค่า usesCleartextTraffic

จำกัดการให้สิทธิ์ URI โดยนัย

ปัจจุบัน หากแอปเปิดใช้ Intent ที่มี URI ซึ่งมีการดำเนินการ ACTION_SEND, ACTION_SEND_MULTIPLE หรือ ACTION_IMAGE_CAPTURE ระบบจะให้สิทธิ์อ่านและ เขียน URI แก่แอปเป้าหมายโดยอัตโนมัติ แต่ตั้งแต่ Android 18 เป็นต้นไป ระบบจะ ไม่ให้สิทธิ์เหล่านี้โดยอัตโนมัติอีกต่อไป ด้วยเหตุนี้ เราจึงแนะนำให้แอปให้สิทธิ์ URI ที่เกี่ยวข้องอย่างชัดเจนแทนที่จะอาศัยให้ระบบให้สิทธิ์

หากต้องการตรวจหาการใช้งาน Intent เหล่านี้ในแอป ให้ใช้ StrictMode กับ detectImplicitUriPermissionGrant() เพื่อทริกเกอร์การละเมิด

Kotlin

val policy = StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build()
StrictMode.setVmPolicy(policy)

Java

StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build();
StrictMode.setVmPolicy(policy);

หรือคุณจะตรวจสอบข้อยกเว้นที่บันทึกไว้ซึ่งมีข้อความ Please set the grant explicitly in the app ที่ปรากฏขึ้นเมื่อระบบตั้งค่าการให้สิทธิ์โดยนัยก็ได้ คุณตรวจสอบบันทึกเหล่านี้ได้โดยใช้คำสั่ง adb ต่อไปนี้

adb logcat | grep "Please set the grant explicitly in the app"

หากต้องการให้สิทธิ์ที่จำเป็นอย่างชัดเจน ให้เพิ่มแฟล็ก FLAG_GRANT_READ_URI_PERMISSION ลงใน Intent ACTION_SEND และ ACTION_SEND_MULTIPLE ดังนี้

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

Java

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

รวมทั้งFLAG_GRANT_READ_URI_PERMISSION และ FLAG_GRANT_WRITE_URI_PERMISSION สำหรับ ACTION_IMAGE_CAPTURE ดังนี้

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

Java

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

ขีดจำกัดของที่เก็บคีย์ต่อแอป

แอปควรหลีกเลี่ยงการสร้างคีย์จำนวนมากเกินไปใน Android Keystore เนื่องจากเป็นทรัพยากรที่แชร์สำหรับแอปทั้งหมดในอุปกรณ์ ตั้งแต่ Android 17 เป็นต้นไป ระบบจะบังคับใช้ขีดจํากัดจํานวนคีย์ที่แอปเป็นเจ้าของได้ โดยจำกัดไว้ที่ 50,000 คีย์สำหรับแอปที่ไม่ใช่ระบบที่กำหนดเป้าหมายเป็น Android 17 (ระดับ API 37) ขึ้นไป และ 200,000 คีย์สำหรับแอปอื่นๆ ทั้งหมด แอปของระบบมีขีดจำกัดคีย์อยู่ที่ 200,000 คีย์ ไม่ว่าแอปจะกำหนดเป้าหมายเป็นระดับ API ใดก็ตาม

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

  • แอปที่กำหนดเป้าหมายเป็น Android 17 (API ระดับ 37) ขึ้นไป: getNumericErrorCode() จะแสดงค่า ERROR_TOO_MANY_KEYS ใหม่
  • แอปอื่นๆ ทั้งหมด: getNumericErrorCode() คืนค่า ERROR_INCORRECT_USAGE

บล็อกการเข้าชมแบบวนรอบข้ามโปรไฟล์

ตั้งแต่ Android 17 เป็นต้นไป ระบบจะไม่อนุญาตการรับส่งข้อมูลแบบ Loopback ข้ามโปรไฟล์โดยค่าเริ่มต้น การรับส่งข้อมูลแบบ Loopback ภายในโปรไฟล์เดียวกันจะไม่ได้รับผลกระทบ การเปลี่ยนแปลงนี้จะมีผลกับแอปทั้งหมดที่ทำงานบน Android 17 ขึ้นไป ไม่ว่าแอปจะกำหนดเป้าหมายเป็นระดับ API ใดก็ตาม

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

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

กู้คืนระดับการเข้าถึง IME เริ่มต้นหลังจากการหมุน

ตั้งแต่ Android 17 เป็นต้นไป เมื่อการกำหนดค่าของอุปกรณ์เปลี่ยนแปลง (เช่น ผ่านการหมุน) และแอปไม่ได้จัดการการเปลี่ยนแปลงนี้ ระบบจะไม่คืนค่าระดับการมองเห็น IME ก่อนหน้า

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

  • ตั้งค่าแอตทริบิวต์ android:windowSoftInputMode เป็น stateAlwaysVisible
  • ขอแป้นพิมพ์เสมือนในกิจกรรมของคุณโดยใช้โปรแกรมในเมธอด onCreate() หรือเพิ่มเมธอด onConfigurationChanged()

อินพุตจากมนุษย์

Android 17 มีการเปลี่ยนแปลงต่อไปนี้ซึ่งส่งผลต่อวิธีที่ แอปโต้ตอบกับอุปกรณ์อินพุตของมนุษย์ เช่น แป้นพิมพ์และทัชแพด

ทัชแพดจะส่งเหตุการณ์ที่เกี่ยวข้องโดยค่าเริ่มต้นระหว่างการจับเคอร์เซอร์

ตั้งแต่ Android 17 เป็นต้นไป หากแอปขอการจับภาพตัวชี้โดยใช้ View.requestPointerCapture() และผู้ใช้ใช้ทัชแพด ระบบจะ จดจำการเคลื่อนไหวของตัวชี้และท่าทางสัมผัสสำหรับการเลื่อนของผู้ใช้ และ รายงานไปยังแอปในลักษณะเดียวกับการเคลื่อนไหวของตัวชี้และปุ่มลูกกลิ้ง จากเมาส์ที่จับภาพ ในกรณีส่วนใหญ่ การดำเนินการนี้จะช่วยลดความจำเป็นที่แอปซึ่งรองรับเมาส์ที่จับภาพจะต้องเพิ่มตรรกะการจัดการพิเศษสำหรับทัชแพด ดูรายละเอียดเพิ่มเติมได้ที่เอกสารประกอบสำหรับ View.POINTER_CAPTURE_MODE_RELATIVE

ก่อนหน้านี้ ระบบไม่ได้พยายามจดจำท่าทางสัมผัสจากทัชแพด แต่จะส่งตำแหน่งสัมผัสที่แน่นอนและดิบของผู้ใช้ไปยังแอปในรูปแบบที่คล้ายกับการสัมผัสหน้าจอ หากแอปยังคงต้องการข้อมูลที่แน่นอนนี้ แอป ควรเรียกใช้เมธอด View.requestPointerCapture(int) ใหม่ด้วย View.POINTER_CAPTURE_MODE_ABSOLUTE แทน

สื่อ

Android 17 มีการเปลี่ยนแปลงลักษณะการทำงานของสื่อต่อไปนี้

การปิดช่องโหว่ของเสียงเบื้องหลัง

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

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

ดูข้อมูลเพิ่มเติม รวมถึงกลยุทธ์การลดความเสี่ยงได้ที่การปิดช่องโหว่เสียงในเบื้องหลัง

การเชื่อมต่อ

Android 17 มีการเปลี่ยนแปลงต่อไปนี้เพื่อเพิ่มประสิทธิภาพการเชื่อมต่ออุปกรณ์

การจับคู่ใหม่โดยอัตโนมัติเมื่อการเชื่อมต่อบลูทูธขาดหายไป

Android 17 引入了自主重新配对功能,这是一项系统级增强功能,旨在自动解决蓝牙配对信息丢失问题。

以前,如果配对信息丢失,用户必须手动前往“设置”取消配对,然后重新配对外围设备。此功能以 Android 16 的安全改进为基础,允许系统在后台重新建立配对信息,而无需用户手动前往“设置”取消配对并重新配对外围设备。

虽然大多数应用不需要更改代码,但开发者应注意蓝牙堆栈中的以下行为变更:

  • 新的配对上下文ACTION_PAIRING_REQUEST 现在包含 EXTRA_PAIRING_CONTEXT extra,允许应用区分 标准配对请求和自主系统发起的重新配对尝试。
  • 有条件的密钥更新:只有在重新配对成功且新连接达到或超过之前配对信息的安全级别时,才会替换现有安全密钥。
  • 修改后的 intent 时间:现在,只有在自主重新配对尝试失败时,才会广播 ACTION_KEY_MISSING intent。如果系统在后台成功恢复配对信息,则可以减少应用中不必要的错误处理。
  • 用户通知:系统通过新的界面通知和对话框管理重新配对。系统会提示用户确认重新配对尝试,以确保用户了解重新连接。

外围设备制造商和配套应用开发者应验证硬件和应用是否能妥善处理配对信息转换。如需测试此行为,请使用以下任一方法模拟远程配对信息丢失:

  • 从外围设备中手动移除配对信息
  • 在“设置”>“已连接的设备”中手动取消配对设备