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

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

หาก targetSdkVersion ของแอปเป็น 29 ขึ้นไป คุณจะต้องรองรับการเปลี่ยนแปลงเพิ่มเติมด้วย โปรดอ่านรายละเอียดเกี่ยวกับการเปลี่ยนแปลงลักษณะการทํางานสําหรับแอปที่กําหนดเป้าหมายเป็น 29

หมายเหตุ: นอกเหนือจากการเปลี่ยนแปลงที่ระบุไว้ในหน้านี้แล้ว Android 10 ยังมีการเปลี่ยนแปลงและข้อจำกัดด้านความเป็นส่วนตัวจำนวนมาก ซึ่งรวมถึงการเปลี่ยนแปลงต่อไปนี้

  • การเข้าถึงตำแหน่งอุปกรณ์ในเบื้องหลัง
  • เริ่มกิจกรรมในเบื้องหลัง
  • ข้อมูลความเกี่ยวข้องของรายชื่อติดต่อ
  • การสุ่มที่อยู่ MAC
  • ข้อมูลเมตาของกล้อง
  • รูปแบบสิทธิ์

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

ข้อจำกัดของอินเทอร์เฟซที่ไม่ใช่ SDK

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

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

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

ดูข้อมูลเพิ่มเติมได้ที่การอัปเดตข้อจำกัดเกี่ยวกับอินเทอร์เฟซที่ไม่ใช่ SDK ใน Android 10 และข้อจำกัดเกี่ยวกับอินเทอร์เฟซที่ไม่ใช่ SDK

การนำทางด้วยท่าทางสัมผัส

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

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

NDK

Android 10 มีการเปลี่ยนแปลง NDK ดังต่อไปนี้

ออบเจ็กต์ที่แชร์ต้องไม่มีการเปลี่ยนตำแหน่งข้อความ

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

SELinux จะบังคับใช้ข้อจำกัดนี้กับแอปที่กำหนดเป้าหมายเป็น Android 10 ขึ้นไป หากแอปเหล่านี้ยังคงใช้ออบเจ็กต์ที่แชร์ซึ่งมีการเปลี่ยนตำแหน่งข้อความอยู่ แอปมีความเสี่ยงสูงที่จะใช้งานไม่ได้

การเปลี่ยนแปลงไลบรารี Bionic และเส้นทางตัวลิงก์แบบไดนามิก

ตั้งแต่ Android 10 เป็นต้นไป เส้นทางหลายเส้นทางจะเป็นลิงก์สัญลักษณ์แทนที่จะเป็นไฟล์ปกติ แอปที่อาศัยเส้นทางที่เป็นไฟล์ปกติอาจใช้งานไม่ได้

  • /system/lib/libc.so -> /apex/com.android.runtime/lib/bionic/libc.so
  • /system/lib/libm.so -> /apex/com.android.runtime/lib/bionic/libm.so
  • /system/lib/libdl.so -> /apex/com.android.runtime/lib/bionic/libdl.so
  • /system/bin/linker -> /apex/com.android.runtime/bin/linker

การเปลี่ยนแปลงเหล่านี้มีผลกับตัวแปร 64 บิตของไฟล์ด้วย โดยจะใช้ lib64/ แทน lib/

ระบบจะจัดเตรียมลิงก์สัญลักษณ์ไว้ที่เส้นทางเดิมเพื่อความเข้ากันได้ เช่น /system/lib/libc.so เป็นลิงก์สัญลักษณ์ไปยัง /apex/com.android.runtime/lib/bionic/libc.so ดังนั้น dlopen(“/system/lib/libc.so”) จะยังคงทํางานต่อไป แต่แอปจะพบความแตกต่างเมื่อพยายามตรวจสอบไลบรารีที่โหลดโดยการอ่าน /proc/self/maps หรือที่คล้ายกัน ซึ่งไม่ปกติ แต่เราพบว่าแอปบางแอปทําเช่นนั้นเป็นส่วนหนึ่งของกระบวนการป้องกันการแฮ็ก หากเป็นเช่นนั้น คุณควรเพิ่มเส้นทาง /apex/… เป็นเส้นทางที่ถูกต้องสำหรับไฟล์ Bionic

ไบนารี/ไลบรารีของระบบที่แมปกับหน่วยความจำแบบเรียกใช้ได้อย่างเดียว

ตั้งแต่ Android 10 เป็นต้นไป ระบบจะแมปส่วนของไบนารีและไลบรารีของระบบที่เรียกใช้ได้ไปยังหน่วยความจำแบบเรียกใช้ได้อย่างเดียว (อ่านไม่ได้) เป็นเทคนิคการเพิ่มความแข็งแกร่งเพื่อป้องกันการโจมตีด้วยการใช้โค้ดซ้ำ หากแอปของคุณดำเนินการอ่านในเซกเมนต์หน่วยความจำที่ทำเครื่องหมายว่า "ดำเนินการเท่านั้น" ไม่ว่าจะเป็นจากข้อบกพร่อง ช่องโหว่ หรือการตรวจสอบหน่วยความจำโดยเจตนา ระบบจะส่งสัญญาณ SIGSEGV ไปยังแอปของคุณ

คุณสามารถระบุว่าลักษณะการทำงานนี้ทำให้เกิดข้อขัดข้องหรือไม่โดยตรวจสอบไฟล์ Tombstone ที่เกี่ยวข้องใน /data/tombstones/ ข้อขัดข้องที่เกี่ยวข้องกับการดําเนินการเท่านั้นจะมีข้อความยกเลิกดังต่อไปนี้

Cause: execute-only (no-read) memory access error; likely due to data in .text.

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

ความปลอดภัย

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

เปิดใช้ TLS 1.3 โดยค่าเริ่มต้น

ใน Android 10 ขึ้นไป ระบบจะเปิดใช้ TLS 1.3 โดยค่าเริ่มต้นสำหรับการเชื่อมต่อ TLS ทั้งหมด รายละเอียดสำคัญบางประการเกี่ยวกับการใช้งาน TLS 1.3 มีดังนี้

  • คุณปรับแต่งชุดการเข้ารหัส TLS 1.3 ไม่ได้ ระบบจะเปิดใช้ชุดการเข้ารหัส TLS 1.3 ที่รองรับเสมอเมื่อเปิดใช้ TLS 1.3 ระบบจะไม่สนใจความพยายามในการปิดใช้ setEnabledCipherSuites() โดยเรียกใช้
  • เมื่อเจรจา TLS 1.3 ระบบจะเรียกใช้ออบเจ็กต์ก่อนเพิ่มเซสชันลงในแคชเซสชันHandshakeCompletedListener (ใน TLS 1.2 และเวอร์ชันอื่นๆ ก่อนหน้า ระบบจะเรียกออบเจ็กต์เหล่านี้ว่า after ซึ่งเพิ่มเซสชันลงในแคชเซสชัน)
  • ในบางกรณีที่อินสแตนซ์ SSLEngine แสดงSSLHandshakeException ใน Android เวอร์ชันก่อนหน้า อินสแตนซ์เหล่านี้จะแสดงSSLProtocolException แทนใน Android 10 ขึ้นไป
  • ไม่รองรับโหมด 0-RTT

หากต้องการ คุณขอรับ SSLContext ที่ปิดใช้ TLS 1.3 ได้โดยโทรไปที่ SSLContext.getInstance("TLSv1.2") นอกจากนี้ คุณยังเปิดหรือปิดใช้เวอร์ชันโปรโตคอลตามการเชื่อมต่อแต่ละรายการได้โดยเรียกใช้ setEnabledProtocols() ในออบเจ็กต์ที่เหมาะสม

ใบรับรองที่ลงนามด้วย SHA-1 จะไม่ได้รับการเชื่อถือใน TLS

ใน Android 10 ใบรับรองที่ใช้อัลกอริทึมแฮช SHA-1 จะไม่น่าเชื่อถือในการเชื่อมต่อ TLS CA รูทไม่ได้ออกใบรับรองดังกล่าวมาตั้งแต่ปี 2016 และ Chrome หรือเบราว์เซอร์หลักๆ อื่นๆ จะไม่เชื่อถือใบรับรองดังกล่าวอีกต่อไป

การพยายามเชื่อมต่อจะล้มเหลวหากการเชื่อมต่อไปยังเว็บไซต์ที่แสดงใบรับรองโดยใช้ SHA-1

การเปลี่ยนแปลงและการปรับปรุงลักษณะการทํางานของ KeyChain

เบราว์เซอร์บางประเภท เช่น Google Chrome อนุญาตให้ผู้ใช้เลือกใบรับรองเมื่อเซิร์ฟเวอร์ TLS ส่งข้อความคำขอใบรับรองเป็นส่วนหนึ่งของการจับมือ TLS ตั้งแต่ Android 10 เป็นต้นไป ออบเจ็กต์ KeyChain จะเป็นไปตามผู้ออกใบรับรองและพารามิเตอร์ข้อกำหนดหลักเมื่อเรียกใช้ KeyChain.choosePrivateKeyAlias() เพื่อแสดงข้อความแจ้งให้ผู้ใช้เลือกใบรับรอง โดยเฉพาะอย่างยิ่ง พรอมต์นี้ไม่มีตัวเลือกที่ไม่เป็นไปตามข้อกำหนดเฉพาะของเซิร์ฟเวอร์

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

นอกจากนี้ ใน Android 10 ขึ้นไป คุณไม่จำเป็นต้องล็อกหน้าจออุปกรณ์เพื่อนำเข้าคีย์หรือใบรับรอง CA ไปยังออบเจ็กต์ KeyChain

การเปลี่ยนแปลงอื่นๆ เกี่ยวกับ TLS และการเข้ารหัส

มีการเปลี่ยนแปลงเล็กน้อยหลายอย่างในไลบรารี TLS และวิทยาการเข้ารหัสที่จะมีผลใน Android 10 ดังนี้

  • การเข้ารหัส AES/GCM/NoPadding และ ChaCha20/Poly1305/NoPadding จะแสดงขนาดบัฟเฟอร์ที่แม่นยำยิ่งขึ้นจาก getOutputSize()
  • ระบบจะไม่รวมชุดการเข้ารหัส TLS_FALLBACK_SCSV ในการพยายามเชื่อมต่อด้วยโปรโตคอลสูงสุด TLS 1.2 ขึ้นไป เราไม่แนะนำให้ใช้ TLS ภายนอกสำรองเนื่องจากมีการปรับปรุงการติดตั้งใช้งานเซิร์ฟเวอร์ TLS เราขอแนะนำให้ใช้การเจรจาต่อรองเวอร์ชัน TLS แทน
  • ChaCha20-Poly1305 เป็นชื่อแทนของ ChaCha20/Poly1305/NoPadding
  • ระบบจะไม่ถือว่าชื่อโฮสต์ที่มีจุดต่อท้ายเป็นชื่อโฮสต์ SNI ที่ถูกต้อง
  • ระบบจะพิจารณาส่วนขยาย supported_signature_algorithms ใน CertificateRequest เมื่อเลือกคีย์การรับรองสําหรับการตอบกลับใบรับรอง
  • คีย์การลงนามแบบทึบ เช่น คีย์จาก Android Keystore สามารถใช้กับลายเซ็น RSA-PSS ใน TLS ได้

การออกอากาศ Wi-Fi Direct

ใน Android 10 การออกอากาศต่อไปนี้ที่เกี่ยวข้องกับ Wi-Fi Direct จะไม่ติดอยู่

หากแอปของคุณอาศัยการรับการออกอากาศเหล่านี้เมื่อลงทะเบียนเนื่องจากมีการติดอยู่ ให้ใช้เมธอด get() ที่เหมาะสมในการเริ่มต้นเพื่อรับข้อมูลแทน

ความสามารถของ Wi-Fi Aware

Android 10 เพิ่มการรองรับเพื่อสร้างซ็อกเก็ต TCP/UDP ได้ง่ายขึ้นโดยใช้เส้นทางข้อมูล Wi-Fi Aware หากต้องการสร้างซ็อกเก็ต TCP/UDP ที่เชื่อมต่อกับ ServerSocket อุปกรณ์ไคลเอ็นต์จะต้องทราบที่อยู่ IPv6 และพอร์ตของเซิร์ฟเวอร์ ซึ่งก่อนหน้านี้จำเป็นต้องสื่อสารนอกแบนด์ เช่น โดยใช้การรับส่งข้อความเลเยอร์ 2 ของ BT หรือ Wi-Fi Aware หรือค้นพบในแบนด์โดยใช้โปรโตคอลอื่นๆ เช่น mDNS ใน Android 10 คุณสามารถสื่อสารข้อมูลดังกล่าวได้เป็นส่วนหนึ่งของการตั้งค่าเครือข่าย

เซิร์ฟเวอร์จะทำอย่างใดอย่างหนึ่งต่อไปนี้ได้

  • เริ่มต้น ServerSocket และตั้งค่าหรือรับพอร์ตที่จะใช้
  • ระบุข้อมูลพอร์ตเป็นส่วนหนึ่งของคําขอเครือข่าย Wi-Fi Aware

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีระบุข้อมูลพอร์ตเป็นส่วนหนึ่งของคำขอเครือข่าย

Kotlin

val ss = ServerSocket()
val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle)
  .setPskPassphrase("some-password")
  .setPort(ss.localPort)
  .build()

val myNetworkRequest = NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build()

Java

ServerSocket ss = new ServerSocket();
WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier
  .Builder(discoverySession, peerHandle)
  .setPskPassphrase(some-password)
  .setPort(ss.getLocalPort())
  .build();

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
  .setNetworkSpecifier(ns)
  .build();

จากนั้นไคลเอ็นต์จะส่งคำขอเครือข่าย Wi-Fi Aware เพื่อรับ IPv6 และพอร์ตที่เซิร์ฟเวอร์ระบุ

Kotlin

val callback = object : ConnectivityManager.NetworkCallback() {
  override fun onAvailable(network: Network) {
    ...
  }
  
  override fun onLinkPropertiesChanged(network: Network,
      linkProperties: LinkProperties) {
    ...
  }

  override fun onCapabilitiesChanged(network: Network,
      networkCapabilities: NetworkCapabilities) {
    ...
    val ti = networkCapabilities.transportInfo
    if (ti is WifiAwareNetworkInfo) {
       val peerAddress = ti.peerIpv6Addr
       val peerPort = ti.port
    }
  }
  override fun onLost(network: Network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback)

Java

callback = new ConnectivityManager.NetworkCallback() {
  @Override
  public void onAvailable(Network network) {
    ...
  }
  @Override
  public void onLinkPropertiesChanged(Network network,
      LinkProperties linkProperties) {
    ...
  }
  @Override
  public void onCapabilitiesChanged(Network network,
      NetworkCapabilities networkCapabilities) {
    ...
    TransportInfo ti = networkCapabilities.getTransportInfo();
    if (ti instanceof WifiAwareNetworkInfo) {
       WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti;
       Inet6Address peerAddress = info.getPeerIpv6Addr();
       int peerPort = info.getPort();
    }
  }
  @Override
  public void onLost(Network network) {
    ...
  }
};

connMgr.requestNetwork(networkRequest, callback);

SYSTEM_ALERT_WINDOW ในอุปกรณ์ Go

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

หากแอปที่ทำงานในอุปกรณ์รุ่น Go ที่ใช้ Android 9 หรือต่ำกว่าได้รับสิทธิ์ SYSTEM_ALERT_WINDOW แอปจะยังคงมีสิทธิ์นั้นแม้ว่าอุปกรณ์จะอัปเกรดเป็น Android 10 แล้วก็ตาม อย่างไรก็ตาม แอปที่ไม่มีสิทธิ์ดังกล่าวจะไม่ได้รับสิทธิ์หลังจากอัปเกรดอุปกรณ์แล้ว

หากแอปในอุปกรณ์ Go ส่ง Intent ที่มีการดำเนินการ ACTION_MANAGE_OVERLAY_PERMISSION ระบบจะปฏิเสธคำขอโดยอัตโนมัติและนําผู้ใช้ไปยังหน้าจอการตั้งค่าที่ระบุว่าไม่อนุญาตสิทธิ์เนื่องจากทำให้อุปกรณ์ช้าลง หากแอปในอุปกรณ์ Go เรียกใช้ Settings.canDrawOverlays() เมธอดจะแสดงผลลัพธ์เป็นเท็จเสมอ โปรดทราบว่าข้อจำกัดเหล่านี้จะไม่มีผลกับแอปที่ได้รับสิทธิ์ SYSTEM_ALERT_WINDOW ก่อนที่อุปกรณ์จะอัปเกรดเป็น Android 10

คำเตือนสำหรับแอปที่กำหนดเป้าหมายเป็น Android เวอร์ชันเก่า

อุปกรณ์ที่ใช้ Android 10 ขึ้นไปจะเตือนผู้ใช้เมื่อเปิดแอปที่กําหนดเป้าหมายเป็น Android 5.1 (API ระดับ 22) หรือต่ำกว่าเป็นครั้งแรก หากแอปกำหนดให้ผู้ใช้ต้องให้สิทธิ์ ผู้ใช้ก็จะมีสิทธิ์ปรับสิทธิ์ของแอปก่อนที่จะอนุญาตให้แอปทำงานเป็นครั้งแรก

ผู้ใช้จะเห็นคำเตือนเหล่านี้ก็ต่อเมื่อเรียกใช้แอปที่ยังไม่ได้อัปเดตเมื่อเร็วๆ นี้เท่านั้น เนื่องจากข้อกำหนด API เป้าหมายของ Google Play สำหรับแอปที่เผยแพร่ผ่าน Store อื่นๆ ข้อกำหนด API เป้าหมายที่คล้ายกันจะมีผลในช่วงปี 2019 ดูข้อมูลเพิ่มเติมเกี่ยวกับข้อกำหนดเหล่านี้ได้ที่การขยายข้อกำหนดระดับ API เป้าหมายในปี 2019

นำชุดการเข้ารหัส SHA-2 CBC ออกแล้ว

ระบบได้นำชุดการเข้ารหัส SHA-2 CBC ต่อไปนี้ออกจากแพลตฟอร์มแล้ว

  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

ชุดการเข้ารหัสเหล่านี้มีความปลอดภัยน้อยกว่าชุดการเข้ารหัสที่คล้ายกันซึ่งใช้ GCM และเซิร์ฟเวอร์ส่วนใหญ่จะรองรับทั้งชุดการเข้ารหัส GCM และ CBC ของชุดการเข้ารหัสเหล่านี้ หรือจะไม่รองรับชุดการเข้ารหัสใดเลย

การใช้งานแอป

Android 10 มีการเปิดตัวการเปลี่ยนแปลงลักษณะการทำงานต่อไปนี้ที่เกี่ยวข้องกับการใช้งานแอป

  • การปรับปรุงการใช้งานแอปด้วย UsageStats - Android 10 จะติดตามการใช้งานแอปอย่างแม่นยำด้วย UsageStats เมื่อแอปใช้โหมดแยกหน้าจอหรือโหมดภาพในภาพ นอกจากนี้ Android 10 จะติดตามการใช้งาน Instant App อย่างถูกต้อง

  • โหมดสีเทาตามแอป - Android 10 สามารถตั้งค่าโหมดการแสดงผลเป็นสีเทาตามแอป

  • สถานะการรบกวนของแต่ละแอป - Android 10 สามารถตั้งค่าแอปเป็น "สถานะการรบกวน" ได้โดยที่ระบบจะระงับการแจ้งเตือนของแอปนั้นและไม่แสดงแอปเป็นแอปที่แนะนำ

การเปลี่ยนแปลงการเชื่อมต่อ HTTPS

หากแอปที่ใช้ Android 10 ส่ง null ไปยัง setSSLSocketFactory() ระบบจะแสดง IllegalArgumentException ในเวอร์ชันก่อนหน้า การส่ง null ไปยัง setSSLSocketFactory() จะมีผลเหมือนกับการส่ง default factory ปัจจุบัน

เลิกใช้งานไลบรารี android.preference แล้ว

ไลบรารี android.preference เลิกใช้งานแล้วใน Android 10 นักพัฒนาแอปควรใช้ไลบรารีค่ากําหนด AndroidX ซึ่งเป็นส่วนหนึ่งของ Android Jetpack แทน ดูแหล่งข้อมูลเพิ่มเติมที่จะช่วยในการย้ายข้อมูลและการพัฒนาได้ที่คู่มือการตั้งค่าฉบับปรับปรุง รวมถึงแอปตัวอย่างสาธารณะและเอกสารอ้างอิง

การเปลี่ยนแปลงในไลบรารียูทิลิตีของไฟล์ ZIP

Android 10 มีการเปิดตัวการเปลี่ยนแปลงต่อไปนี้ในคลาสของแพ็กเกจ java.util.zip ซึ่งจัดการไฟล์ ZIP การเปลี่ยนแปลงเหล่านี้ทำให้ลักษณะการทำงานของไลบรารีมีความสอดคล้องกันมากขึ้นระหว่าง Android กับแพลตฟอร์มอื่นๆ ที่ใช้ java.util.zip

ที่สูบลม

ในเวอร์ชันก่อนหน้า เมธอดบางรายการในคลาส Inflater จะแสดงข้อผิดพลาด IllegalStateException หากมีการเรียกใช้หลังจากการเรียกใช้ end() ใน Android 10 วิธีการเหล่านี้จะแสดงข้อผิดพลาด NullPointerException แทน

ZipFile

ใน Android 10 ขึ้นไป Constructor สำหรับ ZipFile ที่ใช้อาร์กิวเมนต์ประเภท File, int และ Charset จะไม่แสดงข้อผิดพลาด ZipException หากไฟล์ ZIP ที่ระบุไม่มีไฟล์ใดๆ

ZipOutputStream

ใน Android 10 ขึ้นไป เมธอด finish() ใน ZipOutputStream จะไม่แสดงข้อผิดพลาด ZipException หากพยายามเขียนสตรีมเอาต์พุตสำหรับไฟล์ ZIP ที่ไม่มีไฟล์ใดๆ

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

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

แอปพลิเคชันที่กําหนดเป้าหมายเป็น API ระดับ 24 ขึ้นไปควรตั้งค่า android:resizeableActivity อย่างชัดเจนและระบุฟังก์ชันการทํางานที่จําเป็นเพื่อจัดการการทํางานแบบหลายหน้าต่าง

การติดตามการใช้งานแบตเตอรี่

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

ก่อนที่จะเป็น Android 10 สถิติการใช้งานแบตเตอรี่จะรีเซ็ตทุกครั้งที่ถอดปลั๊กอุปกรณ์ออก ไม่ว่าระดับแบตเตอรี่จะมีการเปลี่ยนแปลงเพียงเล็กน้อยเพียงใดก็ตาม

การเลิกใช้งาน Android Beam

ใน Android 10 เราจะเลิกใช้งาน Android Beam อย่างเป็นทางการ ซึ่งเป็นฟีเจอร์เก่าสำหรับการเริ่มแชร์ข้อมูลระหว่างอุปกรณ์ผ่าน Near Field Communication (NFC) นอกจากนี้ เรายังเลิกใช้งาน NFC API ที่เกี่ยวข้องหลายรายการด้วย Android Beam จะยังคงมีให้บริการสำหรับพาร์ทเนอร์ผู้ผลิตอุปกรณ์ที่ต้องการใช้ แต่จะไม่มีการพัฒนาอีกต่อไป อย่างไรก็ตาม Android จะยังคงรองรับความสามารถและ API อื่นๆ ของ NFC ต่อไป และกรณีการใช้งานต่างๆ เช่น การอ่านจากแท็กและการชําระเงินจะยังคงทํางานตามที่คาดไว้

การเปลี่ยนแปลงลักษณะการทํางานของ java.math.BigDecimal.stripTrailingZeros()

BigDecimal.stripTrailingZeros() จะไม่เก็บค่า 0 ต่อท้ายไว้เป็นกรณีพิเศษอีกต่อไปหากค่าอินพุตเป็น 0

การเปลี่ยนแปลงลักษณะการทํางานของ java.util.regex.Matcher และ Pattern

ผลลัพธ์ของ split() มีการเปลี่ยนแปลงเพื่อไม่ให้ขึ้นต้นด้วย Stringเปล่า ("") อีกต่อไปเมื่อมีรายการที่ตรงกันแบบความกว้างเป็น 0 ที่จุดเริ่มต้นของอินพุต ซึ่งจะส่งผลต่อ String.split() ด้วย ตัวอย่างเช่น ตอนนี้ "x".split("") จะแสดงผลเป็น {"x"} แต่ก่อนหน้านี้จะแสดงผลเป็น {"", "x"} ใน Android เวอร์ชันเก่า ตอนนี้ "aardvark".split("(?=a)" แสดงผลเป็น {"a", "ardv", "ark"} แทน {"", "a", "ardv", "ark"}

นอกจากนี้ เรายังได้ปรับปรุงลักษณะการยกเว้นสำหรับอาร์กิวเมนต์ที่ไม่ถูกต้องด้วย

  • ตอนนี้ appendReplacement(StringBuffer, String) จะแสดงข้อผิดพลาด IllegalArgumentException แทน IndexOutOfBoundsException หากString ที่ใช้แทนลงท้ายด้วยเครื่องหมายแบ็กสแลชเดี่ยว ซึ่งเป็นที่ไม่ถูกต้อง ระบบจะแสดงข้อยกเว้นเดียวกันนี้หาก String ที่ใช้แทนลงท้ายด้วย $ ก่อนหน้านี้ไม่มีข้อยกเว้นเกิดขึ้นในสถานการณ์นี้
  • replaceFirst(null) ไม่เรียก reset() ใน Matcher อีกต่อไปหากมีการส่ง NullPointerException ตอนนี้ระบบจะแสดงข้อยกเว้น NullPointerException ด้วยเมื่อไม่พบรายการที่ตรงกัน ก่อนหน้านี้ ระบบจะแสดงข้อยกเว้นเฉพาะเมื่อมีรายการที่ตรงกันเท่านั้น
  • start(int group), end(int group) และ group(int group) จะแสดงIndexOutOfBoundsExceptionทั่วไปมากขึ้นหากดัชนีกลุ่มอยู่นอกขอบเขต ก่อนหน้านี้ เมธอดเหล่านี้จะแสดง ArrayIndexOutOfBoundsException

ตอนนี้มุมเริ่มต้นของ GradientDrawable คือ TOP_BOTTOM

ใน Android 10 หากคุณกำหนด GradientDrawable ใน XML และไม่ระบุการวัดมุม การวางแนวของไล่ระดับสีจะเป็น TOP_BOTTOM โดยค่าเริ่มต้น การเปลี่ยนแปลงนี้แตกต่างจาก Android เวอร์ชันก่อนหน้าซึ่งมีค่าเริ่มต้นเป็น LEFT_RIGHT

วิธีแก้ปัญหาคือ หากคุณอัปเดต AAPT2 เป็นเวอร์ชันล่าสุด เครื่องมือจะตั้งค่าการวัดมุมเป็น 0 สําหรับแอปเดิมหากไม่ได้ระบุการวัดมุม

การบันทึกสําหรับออบเจ็กต์ที่แปลงเป็นอนุกรมโดยใช้ SUID เริ่มต้น

ตั้งแต่ Android 7.0 (API ระดับ 24) เป็นต้นไป แพลตฟอร์มได้แก้ไขserialVersionUIDเริ่มต้นสำหรับออบเจ็กต์ที่ซีเรียลไลซ์ได้ การแก้ไขนี้ไม่ส่งผลต่อแอปที่กำหนดเป้าหมายเป็น API ระดับ 23 หรือต่ำกว่า

ตั้งแต่ Android 10 เป็นต้นไป หากแอปกำหนดเป้าหมายเป็น API ระดับ 23 หรือต่ำกว่าและใช้ serialVersionUID เริ่มต้นที่ไม่ถูกต้อง ระบบจะบันทึกคำเตือนและแนะนำการแก้ไขโค้ด

กล่าวโดยละเอียดคือ ระบบจะบันทึกคำเตือนหากเงื่อนไขต่อไปนี้ทั้งหมดเป็นจริง

  • แอปกำหนดเป้าหมายเป็น API ระดับ 23 หรือต่ำกว่า
  • คลาสได้รับการจัดรูปแบบให้เป็นอนุกรม
  • คลาสที่แปลงเป็นอนุกรมจะใช้ serialVersionUID เริ่มต้นแทนการตั้งค่า serialVersionUID อย่างชัดเจน
  • serialVersionUID เริ่มต้นจะแตกต่างจากserialVersionUID ในกรณีที่แอปกำหนดเป้าหมายเป็น API ระดับ 24 ขึ้นไป

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

การเปลี่ยนแปลง java.io.FileChannel.map()

ตั้งแต่ Android 10 เป็นต้นไป ระบบจะไม่รองรับ FileChannel.map() สำหรับไฟล์ที่ไม่ใช่มาตรฐาน เช่น /dev/zero ซึ่งไม่สามารถเปลี่ยนขนาดได้โดยใช้ truncate() Android เวอร์ชันก่อนหน้าจะละเว้น errno ที่ truncate() แสดง แต่ Android 10 จะแสดงข้อยกเว้น IOException หากต้องการลักษณะการทำงานแบบเก่า คุณต้องใช้สคริปต์เนทีฟ