นอกจากฟีเจอร์และความสามารถใหม่ๆ แล้ว Android 7.0 มีการเปลี่ยนแปลงการทำงานของระบบและ API อย่างหลากหลาย เอกสารนี้ ไฮไลต์การเปลี่ยนแปลงสำคัญที่คุณควรทำความเข้าใจและนำมาใช้ ในแอปของคุณ
หากคุณเผยแพร่แอปสำหรับ Android ไว้ก่อนหน้านี้ โปรดทราบว่าแอปของคุณ อาจได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านี้ในแพลตฟอร์ม
แบตเตอรี่และหน่วยความจำ
Android 7.0 มีการเปลี่ยนแปลงลักษณะการทำงานของระบบซึ่งมีจุดประสงค์เพื่อปรับปรุงอายุการใช้งานแบตเตอรี่ ของอุปกรณ์และลดการใช้ RAM การเปลี่ยนแปลงเหล่านี้อาจส่งผลต่อการเข้าถึง ทรัพยากรระบบ ตลอดจนวิธีที่แอปของคุณโต้ตอบกับแอปอื่นๆ Intent แบบไม่เจาะจงปลายทางบางอย่าง
Doze
Doze เปิดตัวใน Android 6.0 (API ระดับ 23) เพื่อช่วยยืดอายุการใช้งานแบตเตอรี่ การเลื่อนเวลาของกิจกรรมเครือข่ายและ CPU เมื่อผู้ใช้ไม่ได้เสียบปลั๊กอุปกรณ์ไว้ อยู่กับที่ และหน้าจอปิดอยู่ Android 7.0 เหนือกว่า การเพิ่มประสิทธิภาพ Doze โดยใช้กลุ่มย่อยของการจำกัด CPU และเครือข่าย แม้จะถอดปลั๊กอุปกรณ์โดยปิดหน้าจออยู่ แต่ อยู่กับที่ เช่น เมื่อโทรศัพท์มือถืออยู่ในกระเป๋าของผู้ใช้
เมื่ออุปกรณ์ใช้พลังงานแบตเตอรี่และหน้าจอปิดอยู่เป็นระยะเวลาหนึ่ง
อุปกรณ์จะเข้าสู่ Doze และใช้ข้อจำกัดชุดแรก นั่นก็คือ
ปิดการเข้าถึงเครือข่ายแอป รวมทั้งเลื่อนงานและการซิงค์ออกไป หากอุปกรณ์คือ
อยู่กับที่เป็นระยะเวลาหนึ่งหลังจากเข้าสู่ Doze ระบบจะใช้
การจำกัดส่วนที่เหลือของ Doze สำหรับ PowerManager.WakeLock
การปลุก AlarmManager
, GPS และ Wi-Fi สแกนหา ไม่ว่าจะ
ว่ามีการใช้ข้อจำกัดการจับ Doze บางส่วนหรือทั้งหมด ระบบจะปลุก
อุปกรณ์สำหรับช่วงเวลาบำรุงรักษาสั้นๆ โดยในระหว่างนี้ แอปพลิเคชันได้รับอนุญาต
เข้าถึงเครือข่ายและเรียกใช้งาน/การซิงค์ที่มีการเลื่อนเวลาได้
โปรดทราบว่าการเปิดใช้งานหน้าจอหรือเสียบปลั๊กอุปกรณ์จะเป็นการออกจาก Doze และ จะนำข้อจำกัดในการประมวลผลเหล่านี้ออก ลักษณะการทำงานเพิ่มเติม มีผลต่อคำแนะนำและแนวทางปฏิบัติที่ดีที่สุดในการปรับแอปให้เข้ากับ Doze เปิดตัวไปใน Android 6.0 (API ระดับ 23) ตามที่ได้กล่าวไปใน การเพิ่มประสิทธิภาพสำหรับ Doze และสแตนด์บายแอป คุณยังควร ทำตามคำแนะนำเหล่านั้น เช่น การใช้ Firebase Cloud Messaging (FCM) เพื่อ รับส่งข้อความ และเริ่มต้นวางแผนการอัปเดตเพื่อรองรับ พฤติกรรม Doze เพิ่มเติม
โปรเจ็กต์ Svelte: การเพิ่มประสิทธิภาพพื้นหลัง
Android 7.0 จะนำการกระจายข้อมูลโดยนัยออก 3 อย่างเพื่อช่วยเพิ่มประสิทธิภาพของทั้ง 2 อย่าง การใช้หน่วยความจำและการใช้พลังงาน การเปลี่ยนแปลงนี้จำเป็นโดยปริยาย การเผยแพร่มักเริ่มต้นแอปที่ลงทะเบียนไว้เพื่อฟังการเผยแพร่ใน พื้นหลัง การนำการออกอากาศเหล่านี้ออกสามารถให้ประโยชน์แก่อุปกรณ์ได้อย่างมาก ประสิทธิภาพและประสบการณ์ของผู้ใช้
อุปกรณ์เคลื่อนที่มีการเปลี่ยนแปลงการเชื่อมต่อบ่อยครั้ง เช่น เมื่อต้องเคลื่อนย้าย
ระหว่าง Wi-Fi และอินเทอร์เน็ตมือถือ ขณะนี้ แอปสามารถตรวจสอบการเปลี่ยนแปลงใน
การเชื่อมต่อด้วยการลงทะเบียนตัวรับสำหรับการออกอากาศ CONNECTIVITY_ACTION
โดยนัยใน
ไฟล์ Manifest เนื่องจากมีแอปจำนวนมากลงทะเบียนเพื่อรับการออกอากาศนี้
สวิตช์เครือข่ายอาจทำให้พวกเขาทุกคนตื่นขึ้นมาและประมวลผลการออกอากาศ
ครั้งเดียว
ในทำนองเดียวกัน Android เวอร์ชันก่อนหน้า แอปสามารถลงทะเบียนเพื่อรับการออกอากาศ ACTION_NEW_PICTURE
และ ACTION_NEW_VIDEO
โดยนัยจากแอปอื่นๆ ได้ เช่น
กล้อง เมื่อผู้ใช้ถ่ายรูปด้วยแอปกล้องถ่ายรูป ระบบจะปลุกแอปเหล่านี้
เพื่อประมวลผลการออกอากาศ
Android 7.0 ใช้รายการต่อไปนี้เพื่อลดปัญหาเหล่านี้ การเพิ่มประสิทธิภาพ:
- แอปที่กำหนดเป้าหมายเป็น Android 7.0 (API ระดับ 24) ขึ้นไปจะไม่ได้รับ
CONNECTIVITY_ACTION
ประกาศหากผู้ลงโฆษณา ระบุ Broadcast Receiver ในไฟล์ Manifest แอปจะยังคง ได้รับการออกอากาศCONNECTIVITY_ACTION
รายการหากลงทะเบียนBroadcastReceiver
ของพวกเขากับContext.registerReceiver()
และบริบทนั้นก็ยังคงใช้ได้ - ระบบจะไม่ส่งประกาศ
ACTION_NEW_PICTURE
หรือACTION_NEW_VIDEO
อีกต่อไป การเพิ่มประสิทธิภาพนี้ ส่งผลต่อแอปทั้งหมด ไม่เพียงแต่แอปที่กำหนดเป้าหมายเป็น Android 7.0 เท่านั้น
หากแอปใช้ Intent ดังกล่าว คุณควรนำทรัพยากร Dependency ออก
โดยเร็วที่สุดเพื่อให้คุณสามารถกำหนดเป้าหมายอุปกรณ์ Android 7.0 ได้อย่างเหมาะสม
เฟรมเวิร์ก Android มีโซลูชันมากมายที่ช่วยลดความจำเป็นใน
การออกอากาศโดยนัยเหล่านี้ ตัวอย่างเช่น JobScheduler
API มีกลไกที่มีประสิทธิภาพในการตั้งเวลา
การดำเนินการของเครือข่ายเมื่อมีเงื่อนไขที่ระบุ เช่น การเชื่อมต่อกับ
ตรงตามเครือข่ายที่ไม่จำกัดปริมาณอินเทอร์เน็ต คุณยังใช้ JobScheduler
เพื่อตอบสนองต่อการเปลี่ยนแปลงต่อผู้ให้บริการเนื้อหาได้อีกด้วย
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพในเบื้องหลังใน Android 7.0 (ระดับ API 24) และวิธีปรับเปลี่ยนแอป โปรดดูข้อมูลเบื้องต้น การเพิ่มประสิทธิภาพ
การเปลี่ยนแปลงสิทธิ์
Android 7.0 มีการเปลี่ยนแปลงสิทธิ์ที่อาจส่งผลต่อแอปของคุณ
การเปลี่ยนแปลงสิทธิ์ในระบบไฟล์
เพื่อปรับปรุงความปลอดภัยของไฟล์ส่วนตัว ไดเรกทอรีส่วนตัวของ
แอปที่กำหนดเป้าหมายเป็น Android 7.0 ขึ้นไปมีการจํากัดการเข้าถึง (0700
)
การตั้งค่านี้จะป้องกันการรั่วไหลของข้อมูลเมตาของไฟล์ส่วนตัว เช่น ขนาดของไฟล์
หรือการมีอยู่ การเปลี่ยนแปลงสิทธิ์นี้มีผลข้างเคียงหลายอย่าง ดังนี้
-
เจ้าของไม่ควรผ่อนปรนสิทธิ์สำหรับไฟล์ส่วนตัวอีกต่อไป
และความพยายามที่จะทำเช่นนั้นโดยใช้
MODE_WORLD_READABLE
และ/หรือMODE_WORLD_WRITEABLE
จะทริกเกอร์SecurityException
หมายเหตุ: ขณะนี้ข้อจำกัดนี้ยังไม่มีผลโดยสมบูรณ์ แอปอาจยังแก้ไขสิทธิ์ในไดเรกทอรีส่วนตัวได้โดยใช้ API แบบเนทีฟหรือ
File
API อย่างไรก็ตาม เราขอแนะนำอย่างยิ่ง ไม่สนับสนุนให้ผ่อนปรนสิทธิ์ในไดเรกทอรีส่วนตัว -
การส่ง URI
file://
นอกโดเมนแพ็กเกจอาจทำให้ ที่มีเส้นทางที่ไม่สามารถเข้าถึงได้ ดังนั้น ความพยายามที่จะผ่าน URIfile://
จะทริกเกอร์FileUriExposedException
วิธีที่แนะนำในการแชร์ เนื้อหาของไฟล์ส่วนตัวกำลังใช้FileProvider
-
DownloadManager
ไม่สามารถแชร์แบบส่วนตัวได้อีกต่อไป ไฟล์ที่จัดเก็บไว้ตามชื่อไฟล์ แอปพลิเคชันเดิมอาจลงท้ายด้วย เส้นทางที่ไม่สามารถเข้าถึงได้เมื่อเข้าถึงCOLUMN_LOCAL_FILENAME
การกำหนดเป้าหมายแอป Android 7.0 ขึ้นไปจะทริกเกอร์SecurityException
เมื่อ กำลังพยายามเข้าถึงCOLUMN_LOCAL_FILENAME
แอปพลิเคชันเดิมที่ตั้งค่าตำแหน่งการดาวน์โหลดเป็นตำแหน่งสาธารณะโดย โดยใช้DownloadManager.Request.setDestinationInExternalFilesDir()
หรือ วันที่DownloadManager.Request.setDestinationInExternalPublicDir()
ยังคงสามารถเข้าถึงเส้นทางใน อย่างไรก็ตามCOLUMN_LOCAL_FILENAME
ไม่แนะนำอย่างยิ่ง วิธีที่เหมาะสมในการเข้าถึงไฟล์ เปิดเผยโดยDownloadManager
กำลังใช้ContentResolver.openFileDescriptor()
การแชร์ไฟล์ระหว่างแอป
สำหรับแอปที่กำหนดเป้าหมายเป็น Android 7.0 เฟรมเวิร์ก Android จะบังคับใช้
นโยบาย API ของ StrictMode
ที่ไม่อนุญาตให้เปิดเผย URI file://
นอกแอปของคุณ หาก Intent ที่มี URI ของไฟล์ออกจากแอป แอปจะล้มเหลว
โดยมีข้อยกเว้น FileUriExposedException
รายการ
หากต้องการแชร์ไฟล์ระหว่างแอปพลิเคชัน คุณควรส่ง URI content://
และให้สิทธิ์เข้าถึงชั่วคราวใน URI วิธีที่ง่ายที่สุดในการให้สิทธิ์นี้คือ
โดยใช้ชั้นเรียน FileProvider
หากต้องการดูข้อมูลเพิ่มเติม
เกี่ยวกับสิทธิ์และการแชร์ไฟล์
ดูการแชร์ไฟล์
การปรับปรุงการเข้าถึง
Android 7.0 มีการเปลี่ยนแปลงที่มีจุดประสงค์เพื่อปรับปรุงความสามารถในการใช้งาน สำหรับผู้ใช้ที่มีสายตาเลือนรางหรือมีความบกพร่อง การเปลี่ยนแปลงเหล่านี้ควร มักไม่จำเป็นต้องเปลี่ยนแปลงโค้ดในแอป แต่คุณควรตรวจสอบ ฟีเจอร์เหล่านี้และทดสอบกับแอปเพื่อประเมินผลกระทบที่อาจเกิดขึ้นกับผู้ใช้ ประสบการณ์การใช้งาน
การซูมหน้าจอ
Android 7.0 ช่วยให้ผู้ใช้ตั้งค่าขนาดการแสดงผลเพื่อขยายได้ หรือย่อองค์ประกอบทั้งหมดบนหน้าจอ ซึ่งจะช่วยเพิ่มการเข้าถึงอุปกรณ์ สำหรับผู้ใช้ที่มีสายตาเลือนราง ผู้ใช้ไม่สามารถซูมหน้าจอผ่านหน้าจอขั้นต่ำ ความกว้างของ sw320dp ซึ่งเป็นความกว้างของ Nexus 4 ซึ่งเป็นโทรศัพท์ขนาดกลางทั่วไป
เมื่อความหนาแน่นของอุปกรณ์เปลี่ยนแปลง ระบบจะแจ้งแอปที่กำลังทำงานใน วิธีต่อไปนี้
- หากแอปกำหนดเป้าหมายเป็น API ระดับ 23 หรือต่ำกว่า ระบบจะปิดใช้งานโดยอัตโนมัติ กระบวนการเบื้องหลังทั้งหมด หมายความว่าหากผู้ใช้เปลี่ยนจาก เพื่อเปิดหน้าจอการตั้งค่า และเปลี่ยน การตั้งค่าขนาดการแสดงผล ระบบจะหยุดการทำงานของแอป ในลักษณะที่ใช้ในสถานการณ์ที่มีหน่วยความจำน้อย หากแอปมีพื้นหน้า ระบบจะแจ้งกระบวนการดังกล่าวว่าด้วยการเปลี่ยนแปลงการกำหนดค่า ที่อธิบายไว้ในการจัดการ การเปลี่ยนแปลงรันไทม์ เช่นเดียวกับเมื่อการวางแนวของอุปกรณ์เปลี่ยนไป
- หากแอปกำหนดเป้าหมายเป็น Android 7.0 กระบวนการทั้งหมดของแอป (ที่ทำงานอยู่เบื้องหน้าและพื้นหลัง) จะได้รับการแจ้งเตือนเกี่ยวกับการเปลี่ยนแปลงการกำหนดค่าเป็น ที่อธิบายไว้ในการจัดการ การเปลี่ยนแปลงรันไทม์
แอปส่วนใหญ่ไม่จำเป็นต้องทำการเปลี่ยนแปลงใดๆ เพื่อรองรับฟีเจอร์นี้ แอปเหล่านี้เป็นไปตามแนวทางปฏิบัติแนะนำของ Android สิ่งที่ควรตรวจสอบมีดังนี้
- ทดสอบแอปของคุณในอุปกรณ์ที่มีความกว้างของหน้าจอ
sw320dp
และดูให้แน่ใจว่าประสิทธิภาพเพียงพอ - เมื่อการกำหนดค่าอุปกรณ์เปลี่ยนไป ให้อัปเดตความหนาแน่นที่ขึ้นอยู่กับความหนาแน่น
ข้อมูลที่แคชไว้ เช่น บิตแมปที่แคชหรือทรัพยากรที่โหลดจาก
เครือข่าย ตรวจสอบการเปลี่ยนแปลงการกำหนดค่าเมื่อแอปกลับมาทำงานอีกครั้งจากช่วงหยุดชั่วคราว
หมายเหตุ: ถ้าคุณแคชข้อมูลที่ขึ้นอยู่กับการกำหนดค่า ระบบจะดำเนินการ ควรใส่ข้อมูลเมตาที่เกี่ยวข้อง เช่น หน้าจอที่เหมาะสม หรือความหนาแน่นของพิกเซลสำหรับข้อมูลนั้น การบันทึกข้อมูลเมตานี้จะช่วยให้คุณ ตัดสินใจว่าคุณจำเป็นต้องรีเฟรชข้อมูลที่แคชไว้หลังจากการกำหนดค่าหรือไม่ เปลี่ยน
- หลีกเลี่ยงการระบุขนาดด้วยหน่วยพิกเซล เนื่องจากไม่ได้ปรับขนาดด้วย
ความหนาแน่นของหน้าจอ แต่ให้ระบุมิติข้อมูลด้วย ความหนาแน่นไม่ขึ้นกับความหนาแน่น" แทน
pixel (
dp
)
การตั้งค่าการมองเห็นในวิซาร์ดการตั้งค่า
Android 7.0 มีการตั้งค่าการมองเห็นในหน้าจอต้อนรับ ซึ่งผู้ใช้สามารถ กำหนดการตั้งค่าการช่วยเหลือพิเศษต่อไปนี้ในอุปกรณ์เครื่องใหม่ ท่าทางสัมผัสการขยาย, ขนาดแบบอักษร, ขนาดการแสดงผลและ TalkBack การเปลี่ยนแปลงนี้ เพิ่มระดับการมองเห็นข้อบกพร่องที่เกี่ยวข้องกับการตั้งค่าหน้าจอแบบต่างๆ ถึง คุณควรทดสอบแอปกับสิ่งเหล่านี้ เปิดการตั้งค่าแล้ว การตั้งค่าจะอยู่ในส่วนการตั้งค่า > การช่วยเหลือพิเศษ
การลิงก์แอป NDK กับไลบรารีของแพลตฟอร์ม
ตั้งแต่ Android 7.0 เป็นต้นไป ระบบจะป้องกันไม่ให้แอปลิงก์แบบไดนามิก กับไลบรารีที่ไม่ใช่ NDK ซึ่งอาจทำให้แอปขัดข้อง การเปลี่ยนแปลงใน มีจุดประสงค์เพื่อสร้างประสบการณ์การใช้งานแอปที่สอดคล้องกันในการอัปเดตแพลตฟอร์ม และอุปกรณ์อื่นๆ แม้ว่าโค้ดของคุณอาจไม่ได้ลิงก์กับ ไลบรารีส่วนตัว อาจเป็นไปได้ว่าไลบรารีแบบคงที่ของบุคคลที่สามในไฟล์ ที่สามารถทำได้ ดังนั้น นักพัฒนาแอปทุกรายจึงควรตรวจสอบว่า เพื่อให้แอปไม่ขัดข้องในอุปกรณ์ที่ใช้ Android 7.0 หากแอปของคุณใช้ คุณควรใช้ NDK API สาธารณะเท่านั้น
แอปของคุณอาจพยายามเข้าถึงแพลตฟอร์มส่วนตัวอยู่ 3 วิธีด้วยกัน API:
- แอปของคุณเข้าถึงไลบรารีแพลตฟอร์มส่วนตัวโดยตรง คุณควรอัปเดต แอปของคุณให้รวมสำเนาของไลบรารีเหล่านั้นเอง หรือใช้ NDK API สาธารณะ
- แอปของคุณใช้ไลบรารีของบุคคลที่สามที่เข้าถึงแพลตฟอร์มส่วนตัว ห้องสมุด แม้คุณจะมั่นใจว่าแอปไม่ได้เข้าถึงคลังส่วนตัว โดยตรง คุณควรทดสอบแอปในสถานการณ์นี้ต่อไป
- แอปของคุณอ้างอิงไลบรารีที่ไม่ได้รวมอยู่ใน APK สำหรับ
เหตุการณ์นี้อาจเกิดขึ้นได้หากคุณพยายามใช้สำเนา OpenSSL ของคุณเองแต่
ลืมรวมไปกับ APK ของแอป แอปอาจทำงานได้ตามปกติในเวอร์ชันต่างๆ
ของแพลตฟอร์ม Android ที่มี
libcrypto.so
อย่างไรก็ตาม แอป อาจขัดข้องใน Android เวอร์ชันหลังๆ ที่ไม่มีไลบรารีนี้ (เช่น Android 6.0 ขึ้นไป) หากต้องการแก้ไขปัญหานี้ ให้ตรวจสอบว่าคุณจัดกลุ่มทั้งหมด ด้วยไลบรารีที่ไม่ใช่ NDK ด้วย APK
แอปไม่ควรใช้ไลบรารีแบบเนทีฟที่ไม่รวมอยู่ใน NDK เนื่องจาก อาจมีการเปลี่ยนแปลงหรือนำออกใน Android เวอร์ชันต่างๆ การเปลี่ยนจาก OpenSSL เป็น BoringSSL คือตัวอย่างของการเปลี่ยนแปลงดังกล่าว และ เนื่องจากไม่มีข้อกำหนดความเข้ากันได้สำหรับไลบรารีแพลตฟอร์ม ใน NDK อุปกรณ์ต่างๆ อาจมีระดับ ความสามารถในการใช้งานร่วมกัน
เพื่อลดผลกระทบที่ข้อจำกัดนี้อาจมีต่อในปัจจุบัน
แอปที่เผยแพร่แล้ว ชุดของไลบรารีที่มีการใช้งานที่สำคัญ เช่น
libandroid_runtime.so
libcutils.so
libcrypto.so
และ libssl.so
ใช้งานได้ชั่วคราว
เข้าถึงได้ใน Android 7.0 (API ระดับ 24) สำหรับแอปที่กำหนดเป้าหมายเป็น API ระดับ 23 หรือ
ด้านล่าง หากแอปโหลดไลบรารีเหล่านี้ Logcat จะสร้างคำเตือน
และข้อความโทสต์จะปรากฏในอุปกรณ์เป้าหมายเพื่อแจ้งให้คุณทราบ หากคุณเห็นข้อมูลเหล่านี้
คุณควรอัปเดตแอปให้มีสำเนาของ
หรือใช้เฉพาะ NDK API สาธารณะเท่านั้น Android รุ่นต่อๆ ไป
อาจจำกัดการใช้ไลบรารีส่วนตัวทั้งหมด และทำให้
แอปขัดข้อง
แอปทั้งหมดสร้างข้อผิดพลาดรันไทม์เมื่อเรียกใช้ API ที่ไม่ใช่ทั้ง
สาธารณะหรือเข้าถึงได้ชั่วคราว ผลลัพธ์ที่ได้คือ
ทั้ง System.loadLibrary
และ dlopen(3)
กลับมา
NULL
และอาจทำให้แอปขัดข้อง คุณควรตรวจสอบ
โค้ดของแอปเพื่อนำการใช้ API ของแพลตฟอร์มส่วนตัวออก และทดสอบแอปของคุณอย่างละเอียด
ใช้อุปกรณ์หรือโปรแกรมจำลองที่ใช้ Android 7.0 (API ระดับ 24) หากคุณ
หากไม่แน่ใจว่าแอปใช้ไลบรารีส่วนตัวหรือไม่ คุณตรวจสอบ Logcat เพื่อระบุข้อผิดพลาดรันไทม์ได้
ตารางต่อไปนี้อธิบายลักษณะการทำงานที่คุณคาดว่าจะเห็นจาก
แอปขึ้นอยู่กับการใช้ไลบรารีเนทีฟส่วนตัวและ API เป้าหมาย
ระดับ (android:targetSdkVersion
)
ห้องสมุด | ระดับ API เป้าหมาย | การเข้าถึงรันไทม์ผ่าน Linker แบบไดนามิก | ลักษณะการทำงานของ Android 7.0 (API ระดับ 24) | ลักษณะการทำงานในอนาคตของแพลตฟอร์ม Android |
---|---|---|---|---|
NDK สาธารณะ | ช่วง | รองรับผู้พิการ | ทำงานได้ตามที่คาดไว้ | ทำงานได้ตามที่คาดไว้ |
ส่วนตัว (คลังส่วนตัวที่เข้าถึงได้ชั่วคราว) | 23 หรือต่ำกว่า | เข้าถึงได้ชั่วคราว | ทำงานได้ตามที่คาดไว้ แต่คุณจะได้รับคำเตือน Logcat | ข้อผิดพลาดเกี่ยวกับรันไทม์ |
ส่วนตัว (คลังส่วนตัวที่เข้าถึงได้ชั่วคราว) | 24 ปีขึ้นไป | จำกัด | ข้อผิดพลาดเกี่ยวกับรันไทม์ | ข้อผิดพลาดเกี่ยวกับรันไทม์ |
ส่วนตัว (อื่นๆ) | ช่วง | จำกัด | ข้อผิดพลาดเกี่ยวกับรันไทม์ | ข้อผิดพลาดเกี่ยวกับรันไทม์ |
ตรวจสอบว่าแอปใช้คลังส่วนตัวหรือไม่
Logcat อาจสร้าง หรือข้อผิดพลาดเกี่ยวกับรันไทม์ ตัวอย่างเช่น หากแอปกำหนดเป้าหมายเป็น API ระดับ 23 หรือ ที่ต่ำกว่า และพยายามเข้าถึงไลบรารีส่วนตัวในอุปกรณ์ที่ใช้ Android 7.0 คุณอาจเห็นคำเตือนที่มีลักษณะดังนี้
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so" ("/system/lib/libandroid_runtime.so") needed or dlopened by "/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
คำเตือน Logcat เหล่านี้จะบอกคุณว่าไลบรารีใดพยายามเข้าถึง API ของแพลตฟอร์มส่วนตัว แต่จะไม่ทำให้แอปของคุณขัดข้อง หากแอป กำหนดเป้าหมายเป็น API ระดับ 24 ขึ้นไป อย่างไรก็ตาม Logcat จะสร้างข้อมูลต่อไปนี้ ข้อผิดพลาดรันไทม์และแอปอาจขัดข้อง
java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so" ("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so" is not accessible for the namespace "classloader-namespace" at java.lang.Runtime.loadLibrary0(Runtime.java:977) at java.lang.System.loadLibrary(System.java:1602)
นอกจากนี้ คุณยังอาจเห็นเอาต์พุต Logcat เหล่านี้หากแอปใช้ไลบรารีของบุคคลที่สาม
ซึ่งลิงก์กับ API ของแพลตฟอร์มส่วนตัวแบบไดนามิก เครื่องมือ Readelf ใน
Android 7.0DK ให้คุณสร้างรายการที่แชร์แบบไดนามิกทั้งหมด
ไลบรารีของไฟล์ .so
ที่ระบุโดยการเรียกใช้คำสั่งต่อไปนี้
aarch64-linux-android-readelf -dW libMyLibrary.so
อัปเดตแอป
คุณสามารถทำตามขั้นตอนต่อไปนี้เพื่อแก้ไขข้อผิดพลาด ตรวจสอบว่าแอปของคุณไม่ขัดข้องในการอัปเดตแพลตฟอร์มในอนาคต
- หากแอปใช้ไลบรารีแพลตฟอร์มส่วนตัว คุณควรอัปเดตแอปเพื่อรวม สำเนาไลบรารีเหล่านี้เอง หรือใช้ NDK API สาธารณะ
- หากแอปของคุณใช้ไลบรารีของบุคคลที่สามที่เข้าถึงสัญลักษณ์ส่วนตัว โปรดติดต่อ ผู้เขียนห้องสมุดเพื่ออัปเดตไลบรารี
- ตรวจสอบว่าได้ทำแพ็กเกจคลังทั้งหมดที่ไม่ใช่ NDK ด้วย APK แล้ว
- ใช้ฟังก์ชัน JNI มาตรฐานแทน
getJavaVM
และgetJNIEnv
จากlibandroid_runtime.so
:AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h> AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or JavaVM::AttachCurrentThread from <jni.h>.
- ใช้
__system_property_get
แทนproperty_get
ส่วนตัว จากlibcutils.so
ซึ่งทำได้โดยใช้__system_property_get
ซึ่งได้แก่#include <sys/system_properties.h>
หมายเหตุ: ความพร้อมใช้งานและเนื้อหาของพร็อพเพอร์ตี้ระบบคือ ไม่ได้รับการทดสอบผ่าน CTS วิธีแก้ไขที่ดีกว่าคือหลีกเลี่ยงการใช้ ทั้งหมด
- ใช้สัญลักษณ์
SSL_ctrl
ในเวอร์ชันที่อยู่ในเครื่องจากlibcrypto.so
ตัวอย่างเช่น คุณควรลิงก์libcyrpto.a
แบบคงที่ใน ไฟล์.so
หรือรวมlibcrypto.so
เวอร์ชันลิงก์แบบไดนามิกจาก BoringSSL/OpenSSL และรวมไฟล์ไว้ใน APK ของคุณ
Android for Work
Android 7.0 มีการเปลี่ยนแปลงสำหรับแอปที่กำหนดเป้าหมายเป็น Android for Work ซึ่งได้แก่ การเปลี่ยนแปลงการติดตั้งใบรับรอง การรีเซ็ตรหัสผ่าน ผู้ใช้รอง การจัดการ และการเข้าถึงตัวระบุอุปกรณ์ หากคุณกำลังสร้างแอปสำหรับ สภาพแวดล้อมของ Android for Work คุณควรตรวจสอบการเปลี่ยนแปลงเหล่านี้และแก้ไข แอปของคุณให้เหมาะสม
- คุณต้องติดตั้งโปรแกรมติดตั้งใบรับรองที่ได้รับมอบสิทธิ์ก่อน DPC จึงจะตั้งค่าได้
ได้ สำหรับทั้งแอปโปรไฟล์และแอปที่เป็นเจ้าของอุปกรณ์ซึ่งกำหนดเป้าหมายเป็น Android 7.0 (API ระดับ 24)
คุณควรติดตั้งโปรแกรมติดตั้งใบรับรองที่ได้รับมอบสิทธิ์ก่อนนโยบายด้านอุปกรณ์
การเรียกใช้ตัวควบคุม (DPC)
DevicePolicyManager.setCertInstallerPackage()
หากโปรแกรมติดตั้ง ยังไม่ได้ติดตั้ง ระบบจะแสดงข้อผิดพลาดIllegalArgumentException
- รีเซ็ตการจำกัดรหัสผ่านสำหรับผู้ดูแลระบบอุปกรณ์กับโปรไฟล์แล้ว
ผู้ดูแลระบบอุปกรณ์จะใช้ไม่ได้อีกต่อไป
DevicePolicyManager.resetPassword()
เพื่อล้างหรือเปลี่ยนรหัสผ่าน ที่ตั้งไว้แล้ว ผู้ดูแลระบบอุปกรณ์จะยังคงตั้งค่ารหัสผ่านได้ แต่จะทำได้เพียง เมื่ออุปกรณ์ไม่มีรหัสผ่าน, PIN หรือรูปแบบ - เจ้าของอุปกรณ์และโปรไฟล์จะจัดการบัญชีได้แม้ว่าจะมีข้อจำกัด
ตั้งค่า เจ้าของอุปกรณ์และเจ้าของโปรไฟล์สามารถเรียกใช้ API การจัดการบัญชีได้
แม้ว่าจะมีข้อจำกัดผู้ใช้
DISALLOW_MODIFY_ACCOUNTS
รายการก็ตาม - เจ้าของอุปกรณ์สามารถจัดการผู้ใช้รองได้ง่ายขึ้น เมื่ออุปกรณ์กำลัง
ทำงานในโหมดเจ้าของอุปกรณ์ ข้อจำกัดของ
DISALLOW_ADD_USER
จะได้รับการตั้งค่าโดยอัตโนมัติ วิธีนี้จะป้องกันไม่ให้ผู้ใช้สร้างรองที่ไม่มีการจัดการ ผู้ใช้ นอกจากนี้CreateUser()
และ เลิกใช้งานcreateAndInitializeUser()
เมธอดแล้ว ใหม่DevicePolicyManager.createAndManageUser()
จะแทนที่ - เจ้าของอุปกรณ์เข้าถึงตัวระบุอุปกรณ์ได้ เจ้าของอุปกรณ์สามารถเข้าถึง
ที่อยู่ MAC ของ Wi-Fi ของอุปกรณ์ โดยใช้
DevicePolicyManager.getWifiMacAddress()
หากไม่เคยมี Wi-Fi เปิดใช้ในอุปกรณ์แล้ว เมธอดนี้จะแสดงค่าnull
- การตั้งค่าโหมดการทำงานจะควบคุมการเข้าถึงแอปงาน เมื่อปิดโหมดงาน Launcher ของระบบแสดงว่าแอปงานไม่พร้อมใช้งานโดยการทำให้แอปเป็นสีเทา กำลังเปิดใช้ โหมดการทำงานจะกลับสู่การทำงานปกติ
- เมื่อติดตั้งไฟล์ PKCS #12 ที่มีห่วงโซ่ใบรับรองไคลเอ็นต์และ
คีย์ส่วนตัวที่ตรงกันจาก UI การตั้งค่า ใบรับรอง CA ใน
ไม่ได้ติดตั้งเชนไปยังที่เก็บข้อมูลเข้าสู่ระบบที่เชื่อถือได้อีกต่อไป การดำเนินการนี้จะ
ไม่ส่งผลกระทบต่อผลลัพธ์ของ
KeyChain.getCertificateChain()
เมื่อแอปพยายามเรียกข้อมูลไคลเอ็นต์ ชุดใบรับรองในภายหลัง หากจำเป็น ควรติดตั้งใบรับรอง CA ไปยังที่จัดเก็บข้อมูลรับรองที่เชื่อถือได้ผ่าน UI การตั้งค่าแยกต่างหาก โดยมี รูปแบบที่เข้ารหัส DER ภายใต้นามสกุลไฟล์ .crt หรือ .cer - ตั้งแต่ Android 7.0 เป็นต้นไป การลงทะเบียนลายนิ้วมือและพื้นที่เก็บข้อมูลจะได้รับการจัดการ ต่อผู้ใช้ หาก Device Policy Client (DPC) ของเจ้าของโปรไฟล์กำหนดเป้าหมายระดับ API 23 (หรือต่ำกว่า) ในอุปกรณ์ที่ใช้ Android 7.0 (API ระดับ 24) ผู้ใช้ ยังสามารถตั้งค่าลายนิ้วมือในอุปกรณ์ แต่แอปพลิเคชันงานทำไม่ได้ เข้าถึงลายนิ้วมือของอุปกรณ์ เมื่อ DPC กำหนดเป้าหมายเป็น API ระดับ 24 ขึ้นไป ผู้ใช้ ลายนิ้วมือสำหรับโปรไฟล์งานโดยเฉพาะโดยไปที่การตั้งค่า > ความปลอดภัย > ความปลอดภัยของโปรไฟล์งาน
- สถานะการเข้ารหัสใหม่
ENCRYPTION_STATUS_ACTIVE_PER_USER
คือ ส่งคืนโดยDevicePolicyManager.getStorageEncryptionStatus()
ไปยัง เพื่อระบุว่าการเข้ารหัสทำงานอยู่ และคีย์การเข้ารหัสเชื่อมโยงกับ ผู้ใช้ สถานะใหม่จะแสดงก็ต่อเมื่อ DPC กำหนดเป้าหมายเป็น API ระดับ 24 ขึ้นไปเท่านั้น สำหรับแอปที่กำหนดเป้าหมาย API ระดับก่อนหน้าENCRYPTION_STATUS_ACTIVE
แม้ว่าคีย์การเข้ารหัสจะมีผลเฉพาะกับผู้ใช้หรือโปรไฟล์นั้นก็ตาม - ใน Android 7.0 มีหลายวิธีที่โดยปกติแล้วจะส่งผลกระทบกับ
อุปกรณ์จะทำงานแตกต่างออกไปหากอุปกรณ์มีโปรไฟล์งานติดตั้ง
แยกกันต่างหาก แทนที่จะส่งผลกระทบต่อทั้งอุปกรณ์
ใช้ได้กับโปรไฟล์งานเท่านั้น (วิธีการทั้งหมดมีดังนี้
ในเอกสารประกอบของ
DevicePolicyManager.getParentProfileInstance()
) ตัวอย่างเช่นDevicePolicyManager.lockNow()
ล็อกเฉพาะโปรไฟล์งาน ไม่ใช่ กำลังล็อกอุปกรณ์ทั้งเครื่อง สำหรับแต่ละวิธีเหล่านี้ คุณสามารถใช้ข้อมูลเดิม โดยเรียกใช้เมธอดในอินสแตนซ์ระดับบนสุดของDevicePolicyManager
; คุณจะได้รับผู้ปกครองรายนี้โดย กำลังโทรหาDevicePolicyManager.getParentProfileInstance()
ตัวอย่างเช่น หากคุณเรียกlockNow()
ของอินสแตนซ์หลัก อุปกรณ์จะล็อกอุปกรณ์ทั้งเครื่อง
การเก็บรักษาคำอธิบายประกอบ
Android 7.0 แก้ไขข้อบกพร่องที่ไม่สนใจระดับการเข้าถึงคำอธิบายประกอบ ปัญหานี้ทำให้รันไทม์เข้าถึงคำอธิบายประกอบที่ไม่ควรได้มา สามารถทำได้ คำอธิบายประกอบเหล่านี้ได้แก่
VISIBILITY_BUILD
: ต้องการแสดงในเวลาบิลด์เท่านั้นVISIBILITY_SYSTEM
: มีเจตนาที่จะแสดงขณะรันไทม์ แต่จะปรากฏต่อ ระบบพื้นฐาน
หากแอปของคุณต้องใช้ลักษณะการทำงานนี้ โปรดเพิ่มนโยบายการเก็บรักษาลงในคำอธิบายประกอบที่ต้อง
พร้อมใช้งานขณะรันไทม์ โดยใช้ @Retention(RetentionPolicy.RUNTIME)
การเปลี่ยนแปลงการกำหนดค่าเริ่มต้นของ TLS/SSL
Android 7.0 ทำการเปลี่ยนแปลงต่อไปนี้สำหรับการกำหนดค่า TLS/SSL เริ่มต้น ที่แอปใช้สำหรับ HTTPS และการรับส่งข้อมูล TLS/SSL อื่นๆ
- ปิดใช้ชุดการเข้ารหัส RC4 แล้ว
- เปิดใช้ชุดการเข้ารหัส CHACHA20-POLY1305 แล้ว
การปิดใช้ RC4 โดยค่าเริ่มต้นอาจทำให้เกิดความเสียหายใน HTTPS หรือ TLS/SSL การเชื่อมต่อเมื่อเซิร์ฟเวอร์ไม่มีการเจรจาชุดการเข้ารหัสที่ทันสมัย วิธีแก้ไขที่แนะนำคือปรับปรุงการกำหนดค่าของเซิร์ฟเวอร์เพื่อให้มีประสิทธิภาพยิ่งขึ้น รวมถึงชุดการเข้ารหัสและโปรโตคอลที่ทันสมัยยิ่งขึ้น โดยหลักการแล้ว TLSv1.2 และ AES-GCM ควรเปิดใช้งานไว้ และชุดการเข้ารหัส Forward Secrecy (ECDHE) ควร เปิดใช้งานและเลือกไว้ได้ง่าย
อีกวิธีหนึ่งคือแก้ไขแอปให้ใช้ SSLSocketFactory
ที่กำหนดเองเพื่อสื่อสารกับเซิร์ฟเวอร์
โรงงานควรออกแบบมาเพื่อสร้าง SSLSocket
อินสแตนซ์ที่มีชุดการเข้ารหัสบางรายการที่เซิร์ฟเวอร์จำเป็นต้องใช้
เปิดใช้นอกเหนือจากชุดการเข้ารหัสเริ่มต้น
หมายเหตุ: การเปลี่ยนแปลงเหล่านี้ไม่เกี่ยวข้องกับ WebView
แอปที่กำหนดเป้าหมายเป็น Android 7.0
การเปลี่ยนแปลงลักษณะการทำงานเหล่านี้มีผลเฉพาะกับแอปที่กำหนดเป้าหมาย
Android 7.0 (API ระดับ 24) ขึ้นไป แอปที่คอมไพล์กับ Android 7.0
หรือตั้งค่า targetSdkVersion
เป็น Android 7.0 ขึ้นไปต้องแก้ไข
เพื่อรองรับลักษณะการทำงานเหล่านี้อย่างถูกต้อง หากเกี่ยวข้องกับแอป
การเปลี่ยนแปลงการทำให้เป็นอนุกรม
Android 7.0 (API ระดับ 24) แก้ไขข้อบกพร่องในการคำนวณค่าเริ่มต้น SerialVersionUID ที่ไม่ตรงกับข้อกำหนด
ชั้นเรียนที่ใช้ Serializable
และไม่ระบุฟิลด์ serialVersionUID
ที่ชัดเจนสามารถ
เห็นการเปลี่ยนแปลงในerialVersionUID เริ่มต้นซึ่งจะทำให้เกิดข้อยกเว้น
เมื่อมีการพยายามดีซีเรียลไลซ์อินสแตนซ์ของคลาสที่
เป็นอนุกรมจากเวอร์ชันก่อนหน้าหรือเรียงลำดับโดยแอปที่กำหนดเป้าหมายเป็นเวอร์ชันก่อนหน้า
เวอร์ชัน ข้อความแสดงข้อผิดพลาดจะมีลักษณะดังนี้
local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567
การแก้ไขปัญหาเหล่านี้จำเป็นต้องเพิ่มฟิลด์ serialVersionUID
ลงใน
คลาสที่ได้รับผลกระทบซึ่งมีค่า stream classdesc
serialVersionUID
จากข้อความแสดงข้อผิดพลาด เช่น 1234
นิ้ว
สำหรับกรณีนี้ การเปลี่ยนแปลงดังกล่าว
เป็นไปตามแนวทางปฏิบัติแนะนำทั้งหมดที่ดีสำหรับ
จะเขียนโค้ดต่อเนื่องได้ และจะใช้ได้กับ Android ทุกเวอร์ชัน
ข้อบกพร่องเฉพาะที่ได้รับการแก้ไขจะเกี่ยวข้องกับการมี
เมธอดเริ่มต้น เช่น <clinit>
ตาม
ระบุการมีหรือไม่มีเมธอดเริ่มต้นแบบคงที่ใน
จะมีผลกับหมายเลขซีเรียล ซึ่งเป็นค่าเริ่มต้นที่คำนวณสำหรับคลาสนั้น
ก่อนที่จะแก้ไขข้อบกพร่อง การคำนวณจะตรวจสอบ Super class เพื่อหาค่า
ตัวเริ่มต้นแบบคงที่หากคลาสไม่มี
เราขอชี้แจงว่าการเปลี่ยนแปลงนี้ไม่มีผลต่อแอปที่กำหนดเป้าหมายเป็น API ระดับ 23 หรือ
ต่ำกว่า ชั้นเรียนที่มีฟิลด์หรือชั้นเรียน serialVersionUID
ที่มีเมธอดเริ่มต้นแบบคงที่
ประเด็นสำคัญอื่นๆ
- เมื่อแอปทำงานบน Android 7.0 แต่กำหนดเป้าหมายเป็น API ระดับต่ำกว่า
และผู้ใช้เปลี่ยนขนาดการแสดงผล กระบวนการของแอปก็จะหายไป แอป
ต้องรับมือกับสถานการณ์นี้ได้อย่างดี มิเช่นนั้น อาจขัดข้อง
เมื่อผู้ใช้กู้คืนจาก "ล่าสุด"
คุณควรทดสอบแอปเพื่อให้มั่นใจว่า ลักษณะนี้จะไม่เกิดขึ้น ซึ่งคุณสามารถทำได้โดยสร้างการขัดข้องที่เหมือนกัน เมื่อปิดใช้งานแอปด้วยตนเองผ่าน DDMS
แอปที่กำหนดเป้าหมายเป็น Android 7.0 (API ระดับ 24) ขึ้นไปจะไม่ได้รับการดำเนินการโดยอัตโนมัติ เสียชีวิตเมื่อมีการเปลี่ยนแปลงความหนาแน่น แต่อาจยังคงตอบสนองได้ไม่ดีกับ การเปลี่ยนแปลงการกำหนดค่า
- แอปใน Android 7.0 ควรจัดการกับการเปลี่ยนแปลงการกำหนดค่าได้อย่างราบรื่น และไม่ควรเกิดข้อขัดข้องเมื่อเริ่มต้นใช้งานในครั้งต่อๆ ไป คุณสามารถยืนยันลักษณะการทำงานของแอป โดยเปลี่ยนขนาดตัวอักษร (การตั้งค่า > ดิสเพลย์ > ขนาดแบบอักษร) แล้วคืนค่า แอปจากรายการล่าสุด
-
เนื่องจากข้อบกพร่องใน Android เวอร์ชันก่อนหน้า ระบบไม่ได้แจ้งว่าการเขียนไม่เหมาะสม
ไปยังซ็อกเก็ต TCP ในเทรดหลักเป็นการละเมิดโหมดที่เข้มงวด Android 7.0 แก้ไขข้อบกพร่องนี้
แอปที่แสดงลักษณะการทำงานนี้ในขณะนี้จะแสดง
android.os.NetworkOnMainThreadException
โดยทั่วไปแล้ว การดำเนินการของเครือข่ายในเทรดหลักเป็นความคิดที่ไม่ดี เนื่องจากการดำเนินการเหล่านี้ ปกติแล้วจะมีเวลาในการตอบสนองสูงที่ทำให้เกิด ANR และการกระตุก -
ค่าเริ่มต้นของกลุ่มเมธอด
Debug.startMethodTracing()
คือ จัดเก็บเอาต์พุตในไดเรกทอรีเฉพาะแพ็กเกจบนพื้นที่เก็บข้อมูลที่ใช้ร่วมกัน แทนที่จะเป็นที่ระดับบนสุด ของการ์ด SD ซึ่งหมายความว่าแอปไม่จําเป็นต้องขอสิทธิ์WRITE_EXTERNAL_STORAGE
เพื่อใช้ API เหล่านี้อีกต่อไป -
API ของแพลตฟอร์มจำนวนมากได้เริ่มตรวจสอบเพย์โหลดขนาดใหญ่ที่ส่งไปแล้ว
ในธุรกรรม
Binder
และ ตอนนี้ระบบคัดลอกTransactionTooLargeExceptions
เป็นRuntimeExceptions
แทนที่จะบันทึกหรือระงับไว้เงียบๆ หนึ่ง ตัวอย่างที่พบบ่อยคือการจัดเก็บข้อมูลมากเกินไปในActivity.onSaveInstanceState()
, ซึ่งทำให้ActivityThread.StopInfo
แสดงผลRuntimeException
เมื่อแอปของคุณกำหนดเป้าหมายเป็น Android 7.0 -
หากแอปโพสต์
Runnable
งานไปยังView
และView
ไม่ได้แนบอยู่กับหน้าต่าง จัดคิวงานRunnable
ด้วยView
Runnable
จะไม่ดำเนินการจนกว่าจะ แนบView
แล้ว กับหน้าต่าง การทำงานนี้จะแก้ไขข้อบกพร่องต่อไปนี้ -
หากแอปบน Android 7.0 ที่มี
DELETE_PACKAGES
พยายามลบแพ็กเกจ แต่แอปอื่นได้ติดตั้งแพ็กเกจนั้นแล้ว ระบบต้องมีการยืนยันจากผู้ใช้ ในกรณีนี้ แอปควรคาดหวังว่าSTATUS_PENDING_USER_ACTION
เป็นสถานะการส่งคืนสินค้าPackageInstaller.uninstall()
- เราเลิกใช้งานผู้ให้บริการ JCA ที่ชื่อ Crypto แล้วเนื่องจากผู้ให้บริการ ซึ่งเป็นอัลกอริทึม SHA1PRNG ที่มีการเข้ารหัสไม่รัดกุม แอปไม่สามารถใช้ได้อีก SHA1PRNG เพื่อดึงคีย์ (ไม่ปลอดภัย) เนื่องจากผู้ให้บริการรายนี้ไม่ได้ดำเนินการแล้ว พร้อมใช้งาน สำหรับข้อมูลเพิ่มเติม โปรดดูที่บล็อก โพสต์ความปลอดภัย "คริปโต" เลิกใช้งานผู้ให้บริการใน Android แล้ว N