Các thay đổi về hành vi của Android 7.0

Cùng với các tính năng và chức năng mới, Android 7.0 bao gồm nhiều thay đổi về hành vi của hệ thống và API. Tài liệu này nêu bật một số thay đổi quan trọng mà bạn nên hiểu rõ và lưu tâm đến trong ứng dụng của bạn.

Nếu bạn từng xuất bản một ứng dụng dành cho Android, hãy lưu ý rằng ứng dụng đó có thể chịu ảnh hưởng của những thay đổi này trong nền tảng.

Pin và bộ nhớ

Android 7.0 cung cấp các thay đổi về hành vi của hệ thống nhằm cải thiện thời lượng pin thiết bị và giảm mức sử dụng RAM. Những thay đổi này có thể ảnh hưởng đến quyền truy cập của ứng dụng vào tài nguyên hệ thống, cùng với cách ứng dụng của bạn tương tác với các ứng dụng khác thông qua ý định ngầm ẩn nhất định.

Nghỉ

Ra mắt trong Android 6.0 (API cấp 23), chế độ Doze cải thiện thời lượng pin bằng trì hoãn các hoạt động của CPU và mạng khi người dùng không cắm thiết bị, đứng yên và tắt màn hình. Android 7.0 mang đến nhiều tính năng hơn các tính năng nâng cao cho chế độ Nghỉ bằng cách áp dụng một tập hợp con các hạn chế về CPU và mạng trong khi thiết bị không cắm sạc và màn hình tắt, nhưng không nhất thiết đứng yên, ví dụ: khi một chiếc điện thoại di động đang di chuyển trong túi của người dùng.

Hình minh hoạ cách chế độ Nghỉ áp dụng cấp độ đầu tiên của
  các hạn chế về hoạt động của hệ thống để cải thiện thời lượng pin

Hình 1. Hình minh hoạ cách chế độ Nghỉ áp dụng cấp độ đầu tiên của các hạn chế về hoạt động của hệ thống để cải thiện thời lượng pin.

Khi một thiết bị đang chạy bằng pin và màn hình đã tắt trong một khoảng thời gian thì thiết bị sẽ chuyển sang chế độ Nghỉ và áp dụng tập hợp con đầu tiên của các hạn chế: tắt quyền truy cập mạng ứng dụng, đồng thời trì hoãn công việc và đồng bộ hoá. Nếu thiết bị là đứng yên trong một thời gian nhất định sau khi chuyển sang chế độ Nghỉ, hệ thống sẽ áp dụng các giới hạn còn lại của chế độ Nghỉ đối với PowerManager.WakeLock, AlarmManager chuông báo, quét tìm GPS và Wi-Fi. Bất kể cho dù có áp dụng một số hay tất cả các hạn chế Nghỉ, hệ thống sẽ đánh thức thiết bị của bạn trong thời gian bảo trì ngắn, trong thời gian này các ứng dụng được cho phép quyền truy cập mạng và có thể thực thi bất kỳ công việc/đồng bộ hoá nào bị trì hoãn.

Hình minh hoạ cách chế độ Nghỉ áp dụng cấp độ thứ hai của
  các hạn chế hoạt động của hệ thống sau khi thiết bị đứng yên trong một thời gian nhất định

Hình 2. Hình minh hoạ cách chế độ Nghỉ áp dụng cấp độ thứ hai của các hạn chế hoạt động của hệ thống sau khi thiết bị đứng yên trong một thời gian nhất định.

Lưu ý rằng việc kích hoạt màn hình trên hoặc cắm vào thiết bị sẽ thoát khỏi chế độ Nghỉ và loại bỏ các hạn chế xử lý này. Hành vi bổ sung không ảnh hưởng đến các đề xuất và phương pháp hay nhất trong việc điều chỉnh ứng dụng của bạn cho phù hợp với phiên bản Doze (Nghỉ) được giới thiệu trong Android 6.0 (API cấp 23), như được thảo luận trong Tối ưu hoá cho chế độ Nghỉ và Chế độ chờ ứng dụng. Bạn vẫn nên hãy làm theo các đề xuất đó, chẳng hạn như sử dụng Giải pháp gửi thông báo qua đám mây của Firebase (FCM) để gửi và nhận tin nhắn, cũng như bắt đầu lập kế hoạch cập nhật để phù hợp với hành vi Nghỉ.

Project Svelte: Tối ưu hoá ở chế độ nền

Android 7.0 xoá 3 thông báo truyền phát ngầm để giúp tối ưu hoá cả mức sử dụng bộ nhớ và mức tiêu thụ điện năng. Thay đổi này là cần thiết vì ẩn Các thông báo truyền tin thường khởi động các ứng dụng đã đăng ký nghe chúng bằng nền. Việc xoá những thông báo truyền tin này có thể mang lại lợi ích đáng kể cho thiết bị hiệu suất và trải nghiệm người dùng.

Khả năng kết nối của thiết bị di động thường xuyên thay đổi, chẳng hạn như khi di chuyển giữa Wi-Fi và dữ liệu di động. Hiện tại, ứng dụng có thể theo dõi các thay đổi trong kết nối bằng cách đăng ký bộ nhận cho thông báo CONNECTIVITY_ACTION ngầm ẩn trong tệp kê khai. Vì có nhiều ứng dụng đăng ký nhận nội dung truyền tin này, nên chỉ một việc chuyển đổi mạng có thể khiến chúng bật và xử lý thông báo truyền tin một lần.

Tương tự, trong các phiên bản Android trước đây, ứng dụng có thể đăng ký nhận thông báo ACTION_NEW_PICTUREACTION_NEW_VIDEO ngầm ẩn từ các ứng dụng khác, chẳng hạn như Máy ảnh. Khi người dùng chụp ảnh bằng ứng dụng Máy ảnh, những ứng dụng này sẽ đánh thức để xử lý truyền phát.

Để khắc phục những vấn đề này, Android 7.0 áp dụng các biện pháp sau tối ưu hoá:

  • Các ứng dụng nhắm mục tiêu Android 7.0 (API cấp 24) trở lên sẽ không nhận được thông báo CONNECTIVITY_ACTION nếu những ứng dụng đó khai báo trình nhận truyền phát trong tệp kê khai. Các ứng dụng vẫn sẽ nhận được thông báo CONNECTIVITY_ACTION nếu đăng ký BroadcastReceiver thông qua Context.registerReceiver() và ngữ cảnh đó vẫn hợp lệ.
  • Hệ thống không gửi thông báo ACTION_NEW_PICTURE hoặc ACTION_NEW_VIDEO nữa. Tối ưu hoá này ảnh hưởng đến tất cả ứng dụng chứ không chỉ những ứng dụng nhắm đến Android 7.0.

Nếu ứng dụng của bạn dùng ý định nào trong số này, thì bạn nên xoá các phần phụ thuộc vào các thiết bị đó sớm nhất có thể để bạn có thể nhắm mục tiêu đến các thiết bị Android 7.0 đúng cách. Khung Android cung cấp một số giải pháp để giảm thiểu nhu cầu những thông báo truyền phát ngầm này. Ví dụ: API JobScheduler cung cấp một cơ chế mạnh mẽ để lên lịch các hoạt động mạng khi các điều kiện được chỉ định, chẳng hạn như kết nối với mạng không đo lượng dữ liệu đều được đáp ứng. Bạn thậm chí có thể sử dụng JobScheduler để phản ứng với các thay đổi đối với trình cung cấp nội dung.

Để biết thêm thông tin về tính năng tối ưu hoá ở chế độ nền trong Android 7.0 (cấp độ API) 24) và cách điều chỉnh ứng dụng, hãy xem bài viết Nền Tối ưu hoá.

Các thay đổi về quyền

Android 7.0 có các thay đổi về quyền có thể ảnh hưởng đến ứng dụng của bạn.

Thay đổi quyền của hệ thống tệp

Để cải thiện tính bảo mật của các tệp riêng tư, thư mục riêng tư của ứng dụng nhắm đến Android 7.0 trở lên bị hạn chế quyền truy cập (0700). Chế độ cài đặt này giúp ngăn chặn việc rò rỉ siêu dữ liệu của các tệp riêng tư, chẳng hạn như kích thước của các tệp đó hoặc sự tồn tại của tài khoản đó. Thay đổi về quyền này có nhiều tác dụng phụ:

  • Chủ sở hữu sẽ không cần nới lỏng quyền đối với tệp của các tệp riêng tư nữa, và cố gắng làm như vậy bằng cách sử dụng MODE_WORLD_READABLE và/hoặc MODE_WORLD_WRITEABLE, sẽ kích hoạt một SecurityException.

    Lưu ý: Cho đến nay, quy định hạn chế này chưa được thực thi đầy đủ. Các ứng dụng vẫn có thể sửa đổi quyền đối với thư mục riêng tư của mình bằng cách sử dụng API gốc hoặc API File. Tuy nhiên, chúng tôi thực sự không khuyến khích nới lỏng quyền đối với thư mục riêng tư.

  • Việc chuyển URI file:// bên ngoài miền của gói có thể khiến có đường dẫn không thể truy cập. Do đó, cố gắng vượt qua URI file:// kích hoạt một FileUriExposedException Bạn nên chia sẻ nội dung của một tệp riêng tư đang sử dụng FileProvider.
  • DownloadManager không thể chia sẻ riêng tư nữa được lưu trữ theo tên tệp. Các ứng dụng cũ có thể có đường dẫn không thể truy cập khi truy cập COLUMN_LOCAL_FILENAME. Nhắm mục tiêu theo ứng dụng Android 7.0 trở lên kích hoạt SecurityException khi đang cố truy cập COLUMN_LOCAL_FILENAME Các ứng dụng cũ đặt vị trí tải xuống thành vị trí công cộng bằng cách đang sử dụng DownloadManager.Request.setDestinationInExternalFilesDir() hoặc DownloadManager.Request.setDestinationInExternalPublicDir() vẫn có thể truy cập vào đường dẫn trong Tuy nhiên, COLUMN_LOCAL_FILENAME bạn tuyệt đối không nên sử dụng phương pháp này. Cách ưu tiên để truy cập vào tệp mà DownloadManager hiển thị đang sử dụng ContentResolver.openFileDescriptor()

Chia sẻ tệp giữa các ứng dụng

Đối với ứng dụng nhắm đến Android 7.0, khung Android sẽ thực thi chính sách API StrictMode nghiêm cấm hiển thị URI file:// ra bên ngoài ứng dụng. Nếu ý định chứa URI tệp rời khỏi ứng dụng của bạn, thì ứng dụng sẽ gặp lỗi với ngoại lệ FileUriExposedException.

Để chia sẻ tệp giữa các ứng dụng, bạn nên gửi URI content:// và cấp quyền truy cập tạm thời trên URI. Cách dễ nhất để cấp quyền này là bằng cách bằng cách sử dụng lớp FileProvider. Thông tin khác về quyền và việc chia sẻ tệp, hãy xem phần Chia sẻ tệp.

Cải tiến khả năng hỗ trợ tiếp cận

Android 7.0 có các thay đổi nhằm cải thiện khả năng hữu dụng của nền tảng dành cho người dùng có thị lực kém hoặc khiếm thị. Những thay đổi này sẽ thường không yêu cầu thay đổi mã trong ứng dụng, tuy nhiên bạn nên xem xét tính năng này và thử nghiệm chúng với ứng dụng của bạn để đánh giá tác động tiềm ẩn đối với người dùng của bạn.

Thu phóng màn hình

Android 7.0 cho phép người dùng đặt Kích thước hiển thị để phóng to hoặc thu nhỏ tất cả các thành phần trên màn hình, nhờ đó cải thiện khả năng hỗ trợ tiếp cận của thiết bị cho người dùng có thị lực kém. Người dùng không thể thu phóng màn hình qua một màn hình tối thiểu chiều rộng của sw320dp, là chiều rộng của Nexus 4, một loại điện thoại cỡ trung bình phổ biến.

Màn hình cho thấy kích thước màn hình không thu phóng của thiết bị chạy ảnh hệ thống Android 7.0
Màn hình cho thấy tác động của việc tăng kích thước hiển thị của thiết bị chạy ảnh hệ thống Android 7.0

Hình 3. Màn hình ở bên phải cho thấy hiệu ứng của tăng kích thước Màn hình của thiết bị chạy ảnh hệ thống Android 7.0.

Khi mật độ thiết bị thay đổi, hệ thống sẽ thông báo cho các ứng dụng đang chạy trong các cách sau:

  • Nếu một ứng dụng nhắm đến API cấp 23 trở xuống, hệ thống sẽ tự động tắt tất cả các quá trình nền của nó. Điều này có nghĩa là nếu người dùng rời khỏi một ứng dụng như vậy để mở màn hình Cài đặt và thay đổi Trong chế độ cài đặt kích thước hiển thị, hệ thống sẽ tắt ứng dụng theo cùng một cách trong tình huống dung lượng bộ nhớ thấp. Nếu ứng dụng có bất kỳ nền trước nào thì hệ thống sẽ thông báo cho các quy trình đó về thay đổi cấu hình được mô tả trong phần Xử lý Thay đổi về thời gian chạy, giống như khi hướng của thiết bị đã thay đổi.
  • Nếu một ứng dụng nhắm đến Android 7.0, thì tất cả các quy trình của ứng dụng đó (nền trước và nền sau) sẽ nhận được thông báo về thay đổi cấu hình theo được mô tả trong phần Xử lý Thay đổi về thời gian chạy.

Hầu hết ứng dụng không cần thay đổi gì để hỗ trợ tính năng này, miễn là ứng dụng tuân theo các phương pháp hay nhất về Android. Những vấn đề cụ thể cần kiểm tra:

  • Kiểm thử ứng dụng trên thiết bị có chiều rộng màn hình là sw320dp và đảm bảo chiến dịch đó hoạt động đầy đủ.
  • Khi cấu hình thiết bị thay đổi, hãy cập nhật mọi tuỳ chọn phụ thuộc vào mật độ thông tin được lưu vào bộ nhớ đệm, chẳng hạn như bitmap được lưu vào bộ nhớ đệm hoặc tài nguyên được tải từ mạng. Kiểm tra các thay đổi về cấu hình khi ứng dụng tiếp tục hoạt động từ trạng thái tạm dừng trạng thái.

    Lưu ý: Nếu bạn lưu dữ liệu phụ thuộc vào cấu hình vào bộ nhớ đệm, thì đó là nên bao gồm siêu dữ liệu có liên quan như màn hình thích hợp kích thước hoặc mật độ pixel cho dữ liệu đó. Việc lưu siêu dữ liệu này cho phép bạn quyết định xem bạn có cần làm mới dữ liệu được lưu vào bộ nhớ đệm sau khi định cấu hình hay không thay đổi.

  • Tránh chỉ định kích thước bằng đơn vị px vì chúng không điều chỉnh theo tỷ lệ mật độ màn hình. Thay vào đó, hãy chỉ định phương diện bằng phương diện không phụ thuộc vào mật độ đơn vị pixel (dp).

Cài đặt thị giác trong Trình hướng dẫn thiết lập

Android 7.0 bao gồm phần Cài đặt thị giác trên màn hình Chào mừng, nơi người dùng có thể thiết lập các chế độ cài đặt hỗ trợ tiếp cận sau đây trên thiết bị mới: Cử chỉ thu phóng, Kích thước phông chữ, Kích thước hiển thịTalkBack. Sự thay đổi này tăng khả năng hiển thị lỗi liên quan đến nhiều chế độ cài đặt màn hình. Người nhận đánh giá tác động của tính năng này, bạn nên thử nghiệm ứng dụng của mình bằng bật chế độ cài đặt. Bạn có thể tìm thấy phần cài đặt trong phần Cài đặt > Hỗ trợ tiếp cận.

Liên kết ứng dụng NDK với thư viện nền tảng

Kể từ Android 7.0, hệ thống sẽ ngăn các ứng dụng liên kết động với các thư viện không phải NDK có thể khiến ứng dụng của bạn gặp sự cố. Thay đổi này về nhằm mục đích tạo ra trải nghiệm ứng dụng nhất quán qua các bản cập nhật nền tảng và các thiết bị khác nhau. Mặc dù mã của bạn có thể không liên kết được thư viện riêng tư, có thể là thư viện tĩnh của bên thứ ba trong có thể làm được như vậy. Do đó, tất cả các nhà phát triển đều nên kiểm tra để đảm bảo để ứng dụng của họ không gặp sự cố trên thiết bị chạy Android 7.0. Nếu ứng dụng của bạn sử dụng mã gốc, bạn chỉ nên sử dụng API NDK công khai.

Ứng dụng của bạn có thể đang cố gắng truy cập vào nền tảng riêng tư theo 3 cách sau đây API:

  • Ứng dụng của bạn truy cập trực tiếp vào các thư viện nền tảng riêng tư. Bạn nên cập nhật ứng dụng của bạn để thêm bản sao riêng của các thư viện đó hoặc sử dụng các API NDK công khai.
  • Ứng dụng của bạn sử dụng một thư viện bên thứ ba có quyền truy cập vào nền tảng riêng tư thư viện. Ngay cả khi bạn chắc chắn rằng ứng dụng của mình không truy cập vào thư viện riêng tư trực tiếp, bạn vẫn nên kiểm thử ứng dụng của mình trong trường hợp này.
  • Ứng dụng của bạn tham chiếu đến một thư viện không có trong APK. Cho Ví dụ: điều này có thể xảy ra nếu bạn cố sử dụng bản sao của OpenSSL nhưng đã quên nhóm ứng dụng với APK của ứng dụng. Ứng dụng có thể chạy bình thường trên các phiên bản của nền tảng Android bao gồm libcrypto.so. Tuy nhiên, ứng dụng có thể gặp sự cố trên các phiên bản Android sau này không bao gồm thư viện này (chẳng hạn như Android 6.0 trở lên). Để khắc phục vấn đề này, hãy đảm bảo rằng bạn nhóm tất cả các thư viện không phải NDK bằng APK của bạn.

Ứng dụng không được dùng các thư viện gốc không có trong NDK vì chúng có thể thay đổi hoặc bị xoá giữa các phiên bản Android. Chiến lược phát hành đĩa đơn việc chuyển đổi từ OpenSSL sang BoringSSL là một ví dụ về thay đổi như vậy. Ngoài ra, vì không có yêu cầu về khả năng tương thích đối với các thư viện nền tảng có trong NDK, các thiết bị khác nhau có thể cung cấp các cấp độ khả năng tương thích.

Nhằm giảm tác động mà quy định hạn chế này hiện có thể gây ra các ứng dụng đã phát hành, một nhóm thư viện có ý nghĩa đáng kể được sử dụng — chẳng hạn như libandroid_runtime.so, libcutils.so libcrypto.solibssl.so — tạm thời truy cập được trên Android 7.0 (API cấp 24) đối với ứng dụng nhắm đến API cấp 23 hoặc thấp hơn. Nếu ứng dụng của bạn tải một trong những thư viện này, logcat sẽ tạo cảnh báo và một thông báo ngắn sẽ xuất hiện trên thiết bị mục tiêu để thông báo cho bạn. Nếu bạn thấy những thông tin này cảnh báo, bạn nên cập nhật ứng dụng của mình để bao gồm cả bản sao riêng của những hoặc chỉ sử dụng API NDK công khai. Các bản phát hành Android trong tương lai có thể hạn chế hoàn toàn việc sử dụng thư viện riêng tư và khiến ứng dụng gặp sự cố.

Tất cả ứng dụng đều gặp lỗi thời gian chạy khi gọi một API không phải là công khai hoặc có thể truy cập tạm thời. Kết quả là System.loadLibrarydlopen(3) đều trả về NULL và có thể khiến ứng dụng của bạn gặp sự cố. Bạn nên xem lại mã ứng dụng để ngừng sử dụng API nền tảng riêng tư và kiểm thử kỹ lưỡng ứng dụng của bạn dùng một thiết bị hoặc trình mô phỏng chạy Android 7.0 (API cấp 24). Nếu bạn không chắc ứng dụng của mình có sử dụng thư viện riêng tư hay không, bạn có thể kiểm tra logcat để xác định lỗi thời gian chạy.

Bảng sau đây mô tả hành vi mà bạn sẽ thấy từ một ứng dụng phụ thuộc vào việc sử dụng thư viện gốc riêng tư và API mục tiêu của ứng dụng đó cấp độ (android:targetSdkVersion).

Thư viện Cấp API mục tiêu Quyền truy cập vào thời gian chạy thông qua trình liên kết động Hành vi của Android 7.0 (API cấp 24) Hành vi trong tương lai của nền tảng Android
NDK công khai Khán giả có Dễ tiếp cận Hoạt động như mong đợi Hoạt động như mong đợi
Riêng tư (thư viện riêng tư có thể truy cập tạm thời) 23 trở xuống Tạm thời có thể sử dụng Hoạt động như mong đợi, nhưng bạn sẽ nhận được cảnh báo logcat. Lỗi thời gian chạy
Riêng tư (thư viện riêng tư có thể truy cập tạm thời) 24 trở lên Bị hạn chế Lỗi thời gian chạy Lỗi thời gian chạy
Riêng tư (khác) Khán giả có Bị hạn chế Lỗi thời gian chạy Lỗi thời gian chạy

Kiểm tra xem ứng dụng của bạn có sử dụng thư viện riêng tư hay không

Để giúp bạn xác định các sự cố khi tải thư viện riêng tư, logcat có thể tạo một cảnh báo hoặc lỗi thời gian chạy. Ví dụ: nếu ứng dụng của bạn nhắm đến API cấp 23 hoặc thấp hơn và cố gắng truy cập thư viện riêng tư trên một thiết bị chạy Android 7.0, bạn có thể thấy một cảnh báo tương tự như sau:

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

Những cảnh báo logcat này cho bạn biết thư viện nào đang cố truy cập vào riêng tư trên nền tảng API, nhưng sẽ không khiến ứng dụng của bạn gặp sự cố. Nếu ứng dụng nhắm mục tiêu đến API cấp 24 trở lên, tuy nhiên, logcat tạo ra các kết quả sau thời gian chạy và ứng dụng của bạn có thể gặp sự cố:

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)

Bạn cũng có thể thấy những đầu ra logcat này nếu ứng dụng của bạn sử dụng thư viện bên thứ ba tự động liên kết đến các API nền tảng riêng tư. Công cụ readelf trong Android 7.0DK cho phép bạn tạo danh sách tất cả những đường liên kết được chia sẻ động các thư viện của một tệp .so nhất định bằng cách chạy lệnh sau:

aarch64-linux-android-readelf -dW libMyLibrary.so

Cập nhật ứng dụng

Dưới đây là một số bước bạn có thể thực hiện để khắc phục những loại lỗi này và đảm bảo ứng dụng của bạn không gặp sự cố khi cập nhật nền tảng trong tương lai:

  • Nếu ứng dụng của bạn dùng thư viện nền tảng riêng tư, bạn nên cập nhật ứng dụng đó để thêm bản sao riêng của các thư viện đó hoặc sử dụng các API NDK công khai.
  • Nếu ứng dụng của bạn sử dụng thư viện bên thứ ba có quyền truy cập vào các biểu tượng cá nhân, hãy liên hệ với tác giả thư viện để cập nhật thư viện.
  • Hãy nhớ đóng gói tất cả thư viện không phải NDK bằng APK của bạn.
  • Sử dụng các hàm JNI chuẩn thay vì getJavaVMgetJNIEnv từ libandroid_runtime.so:
    AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>
    AndroidRuntime::getJNIEnv -> JavaVM::GetEnv or
    JavaVM::AttachCurrentThread from <jni.h>.
    
  • Sử dụng __system_property_get thay vì property_get riêng tư biểu tượng từ libcutils.so. Để thực hiện việc này, hãy sử dụng __system_property_get bằng các tính năng sau:
    #include <sys/system_properties.h>
    

    Lưu ý: Khả năng sử dụng và nội dung của các thuộc tính hệ thống chưa được kiểm tra thông qua CTS. Cách khắc phục tốt hơn là tránh sử dụng những tài sản.

  • Sử dụng phiên bản cục bộ của biểu tượng SSL_ctrl trên libcrypto.so. Ví dụ: bạn nên liên kết tĩnh libcyrpto.a trong tệp .so của bạn hoặc bao gồm một phiên bản libcrypto.so được liên kết động từ BoringSSL/OpenSSL và đóng gói phiên bản này trong APK của bạn.

Android for Work

Android 7.0 chứa các thay đổi đối với ứng dụng nhắm mục tiêu Android for Work, bao gồm thay đổi đối với quá trình cài đặt chứng chỉ, đặt lại mật khẩu, người dùng phụ quản lý thiết bị và truy cập vào mã nhận dạng thiết bị. Nếu bạn đang xây dựng ứng dụng cho môi trường Android for Work, bạn nên xem xét những thay đổi này và sửa đổi ứng dụng của bạn cho phù hợp.

  • Bạn phải cài đặt trình cài đặt chứng chỉ được uỷ quyền trước khi DPC có thể đặt nó. Đối với cả ứng dụng hồ sơ và ứng dụng chủ sở hữu thiết bị nhắm đến Android 7.0 (API cấp 24), bạn nên cài đặt trình cài đặt chứng chỉ được uỷ quyền trước khi chính sách thiết bị lệnh gọi bộ điều khiển (DPC) DevicePolicyManager.setCertInstallerPackage(). Nếu trình cài đặt chưa được cài đặt, hệ thống sẽ gửi ra một IllegalArgumentException.
  • Giờ đây, bạn có thể đặt lại các hạn chế về mật khẩu đối với quản trị viên thiết bị cho hồ sơ chủ sở hữu. Quản trị viên thiết bị không thể sử dụng nữa DevicePolicyManager.resetPassword() để xoá mật khẩu hoặc thay đổi mà đã được thiết lập. Quản trị viên thiết bị vẫn có thể đặt mật khẩu, nhưng chỉ khi thiết bị không có mật khẩu, mã PIN hoặc hình mở khoá.
  • Chủ sở hữu thiết bị và hồ sơ có thể quản lý tài khoản ngay cả khi các quy định hạn chế được áp dụng thiết lập. Chủ sở hữu thiết bị và chủ sở hữu hồ sơ có thể gọi Account Management API ngay cả khi áp dụng các hạn chế đối với người dùng DISALLOW_MODIFY_ACCOUNTS.
  • Chủ sở hữu thiết bị có thể quản lý người dùng phụ dễ dàng hơn. Khi một thiết bị là chạy ở chế độ chủ sở hữu thiết bị, quy định hạn chế về DISALLOW_ADD_USER được đặt tự động. Thao tác này ngăn người dùng tạo tài khoản phụ không được quản lý người dùng. Ngoài ra, CreateUser() và Các phương thức createAndInitializeUser() không còn được dùng nữa; cái mới Phương thức DevicePolicyManager.createAndManageUser() sẽ thay thế các biến này.
  • Chủ sở hữu thiết bị có thể truy cập vào mã nhận dạng thiết bị. Chủ sở hữu thiết bị có thể truy cập vào Địa chỉ MAC Wi-Fi của một thiết bị, sử dụng DevicePolicyManager.getWifiMacAddress(). Nếu Wi-Fi chưa bao giờ đã được bật trên thiết bị, thì phương thức này sẽ trả về giá trị null.
  • Cài đặt Chế độ công việc kiểm soát quyền truy cập vào các ứng dụng công việc. Khi chế độ làm việc tắt trình chạy hệ thống cho biết các ứng dụng công việc hiện không hoạt động bằng cách chuyển chúng sang màu xám. Đang bật chế độ làm việc sẽ khôi phục lại hành vi bình thường.
  • Khi cài đặt tệp PKCS #12 chứa chuỗi chứng chỉ máy khách và khoá riêng tư tương ứng từ Giao diện người dùng Cài đặt, chứng chỉ CA trong không còn được cài đặt vào bộ nhớ thông tin xác thực đáng tin cậy. Điều này không ảnh hưởng đến kết quả của KeyChain.getCertificateChain() khi các ứng dụng cố gắng truy xuất ứng dụng chuỗi chứng chỉ sau. Nếu được yêu cầu, bạn phải cài đặt chứng chỉ CA vào bộ nhớ thông tin xác thực đáng tin cậy qua Giao diện người dùng Cài đặt một cách riêng biệt, với Định dạng được mã hoá DER dưới đuôi tệp là .crt hoặc .cer.
  • Kể từ Android 7.0, việc đăng ký và lưu trữ vân tay sẽ được quản lý trên mỗi người dùng. Nếu Ứng dụng chính sách thiết bị (DPC) của chủ sở hữu hồ sơ nhắm đến cấp độ API 23 (trở xuống) trên thiết bị chạy Android 7.0 (API cấp 24), người dùng vẫn có thể thiết lập vân tay trên thiết bị, nhưng các ứng dụng công việc thì không thể truy cập vân tay số của thiết bị. Khi DPC nhắm đến API cấp 24 trở lên, người dùng có thể đặt vân tay số dành riêng cho hồ sơ công việc bằng cách chuyển đến Cài đặt > Bảo mật > Bảo mật hồ sơ công việc.
  • Trạng thái mã hoá mới ENCRYPTION_STATUS_ACTIVE_PER_USER là được trả về bởi DevicePolicyManager.getStorageEncryptionStatus(), đến cho biết rằng quá trình mã hoá đang hoạt động và khoá mã hoá được liên kết với người dùng. Trạng thái mới chỉ được trả về nếu DPC nhắm đến API cấp 24 trở lên. Đối với ứng dụng nhắm đến các cấp độ API trước đó, hãy ENCRYPTION_STATUS_ACTIVE sẽ được trả về, ngay cả khi khoá mã hoá là dành riêng cho người dùng hoặc hồ sơ.
  • Trong Android 7.0, một số phương pháp thường ảnh hưởng đến toàn bộ hoạt động khác nhau nếu thiết bị đã cài đặt hồ sơ công việc bằng thử thách công việc riêng biệt. Thay vì ảnh hưởng đến toàn bộ thiết bị, các phương thức chỉ áp dụng cho hồ sơ công việc. (Danh sách đầy đủ các phương pháp này bao gồm trong tài liệu DevicePolicyManager.getParentProfileInstance().) Ví dụ: DevicePolicyManager.lockNow() chỉ khoá hồ sơ công việc, thay vì khoá toàn bộ thiết bị. Đối với mỗi phương pháp này, bạn có thể lấy phương pháp cũ bằng cách gọi phương thức trên thực thể mẹ của DevicePolicyManager; bạn có thể yêu cầu cha mẹ này bằng cách đang gọi DevicePolicyManager.getParentProfileInstance(). Ví dụ: nếu bạn gọi lockNow() của thực thể mẹ thì toàn bộ thiết bị sẽ bị khoá.

Giữ lại chú thích

Android 7.0 sửa lỗi khả năng hiển thị của các chú thích bị bỏ qua. Sự cố này đã khiến môi trường thời gian chạy truy cập vào các chú thích lẽ ra không nên được có thể. Các chú thích này bao gồm:

  • VISIBILITY_BUILD: Chỉ hiển thị tại thời điểm xây dựng.
  • VISIBILITY_SYSTEM: Nhằm hiển thị trong thời gian chạy, nhưng chỉ hiển thị với hệ thống cơ bản.

Nếu ứng dụng của bạn dựa vào hành vi này, vui lòng thêm chính sách giữ lại dữ liệu vào chú thích phải có thể sử dụng trong thời gian chạy. Bạn có thể thực hiện việc này bằng cách sử dụng @Retention(RetentionPolicy.RUNTIME).

Thay đổi cấu hình mặc định TLS/SSL

Android 7.0 thực hiện các thay đổi sau đối với cấu hình TLS/SSL mặc định được các ứng dụng sử dụng cho HTTPS và lưu lượng truy cập TLS/SSL khác:

  • Bộ thuật toán mật mã RC4 hiện đã bị vô hiệu hoá.
  • Bộ thuật toán mật mã CHACHA20-POLY1305 hiện đã được bật.

Việc tắt RC4 theo mặc định có thể dẫn đến lỗi trong HTTPS hoặc TLS/SSL khi máy chủ không thương lượng bộ thuật toán mật mã hiện đại. Cách khắc phục ưu tiên là cải thiện cấu hình của máy chủ để cho phép cùng các giao thức và bộ thuật toán mật mã hiện đại hơn. Lý tưởng nhất là TLSv1.2 và AES-GCM và bộ thuật toán mật mã chuyển tiếp bí mật (ECDHE) sẽ cần được bật và ưu tiên.

Một cách khác là sửa đổi ứng dụng để dùng SSLSocketFactory tuỳ chỉnh nhằm giao tiếp với máy chủ. Chiến lược phát hành đĩa đơn nhà máy sản xuất sẽ được thiết kế để tạo SSLSocket có một số bộ thuật toán mật mã mà máy chủ yêu cầu được bật cùng với bộ thuật toán mật mã mặc định.

Lưu ý: Những thay đổi này không liên quan đến WebView.

Ứng dụng nhắm đến Android 7.0

Những thay đổi về hành vi này chỉ áp dụng cho các ứng dụng đang nhắm mục tiêu Android 7.0 (API cấp 24) trở lên. Ứng dụng biên dịch trên Android 7.0, hoặc thiết lập targetSdkVersion thành Android 7.0 trở lên phải sửa đổi ứng dụng của họ để hỗ trợ những hành vi này đúng cách, nếu phù hợp.

Thay đổi về tuần tự

Android 7.0 (API cấp 24) sửa một lỗi trong quá trình tính toán giá trị mặc định sê-riVersionUID không khớp với thông số kỹ thuật.

Các lớp triển khai Serializable và không chỉ định trường serialVersionUID rõ ràng thì có thể thấy sự thay đổi trong serialVersionUID mặc định của họ, điều này sẽ gây ra ngoại lệ sẽ được gửi khi cố gắng giải tuần tự các thực thể của lớp được chuyển đổi tuần tự trên một phiên bản cũ hơn hoặc được chuyển đổi tuần tự bởi một ứng dụng nhắm mục tiêu . Thông báo lỗi sẽ có dạng như sau:

local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 4567

Để khắc phục những vấn đề này, bạn cần thêm trường serialVersionUID vào mọi lớp bị ảnh hưởng có giá trị stream classdesc serialVersionUID trong thông báo lỗi, ví dụ: 1234 inch trường hợp này. Thay đổi đó tuân thủ tất cả đề xuất phương pháp hay nhất cho viết mã chuyển đổi tuần tự và sẽ hoạt động trên mọi phiên bản Android.

Lỗi cụ thể đã được khắc phục có liên quan đến sự hiện diện của phương thức khởi tạo, ví dụ: <clinit>. Theo đặc tả sự có mặt hay không có phương thức khởi tạo tĩnh trong sẽ ảnh hưởng đếnserialVersionUID mặc định được tính cho lớp đó. Trước khi sửa lỗi, phép tính này cũng sẽ kiểm tra lớp cao cấp để trình khởi tạo tĩnh nếu một lớp không có trình khởi tạo.

Để làm rõ, thay đổi này không ảnh hưởng đến những ứng dụng nhắm đến API cấp 23 hoặc thấp hơn, các lớp có trường serialVersionUID hoặc các lớp có phương thức khởi tạo tĩnh.

Các điểm quan trọng khác

  • Khi một ứng dụng đang chạy trên Android 7.0 nhưng nhắm đến một cấp độ API thấp hơn, và người dùng thay đổi kích thước hiển thị, quá trình ứng dụng sẽ bị dừng. Ứng dụng phải có khả năng xử lý trường hợp này một cách linh hoạt. Nếu không, sự cố sẽ xảy ra khi người dùng khôi phục thư mục đó từ mục Gần đây.

    Bạn nên kiểm thử ứng dụng để đảm bảo rằng hành vi này không xảy ra. Bạn có thể làm như vậy bằng cách gây ra một sự cố tương tự khi tắt ứng dụng theo cách thủ công thông qua DDMS.

    Ứng dụng nhắm đến Android 7.0 (API cấp 24) trở lên không tự động bị thiệt mạng do thay đổi mật độ; tuy nhiên, chúng vẫn có thể phản hồi kém với các thay đổi về cấu hình.

  • Các ứng dụng trên Android 7.0 sẽ có khả năng xử lý linh hoạt các thay đổi về cấu hình, và không gặp sự cố vào những lần bắt đầu tiếp theo. Bạn có thể xác minh hành vi của ứng dụng bằng cách thay đổi cỡ chữ (Cài đặt > Hiển thị > Kích thước phông chữ), sau đó khôi phục ứng dụng từ mục Gần đây.
  • Do một lỗi trong các phiên bản Android trước, nên hệ thống đã không gắn cờ nội dung vào cổng TCP trên luồng chính là lỗi vi phạm chế độ nghiêm ngặt. Android 7.0 đã khắc phục lỗi này. Các ứng dụng biểu hiện hành vi này hiện sẽ gửi một android.os.NetworkOnMainThreadException. Nhìn chung, việc thực hiện các thao tác mạng trên luồng chính là không nên vì những thao tác này thường có độ trễ cao, gây ra hiện tượng ANR và hiện tượng giật.
  • Nhóm phương thức Debug.startMethodTracing() hiện đặt mặc định thành lưu trữ đầu ra trong thư mục dành riêng cho gói trên bộ nhớ dùng chung, thay vì xuất hiện ở cấp cao nhất của thẻ SD. Điều này có nghĩa là các ứng dụng không cần yêu cầu quyền WRITE_EXTERNAL_STORAGE để sử dụng các API này nữa.
  • Nhiều API nền tảng hiện đã bắt đầu kiểm tra các tải trọng lớn được gửi trên Binder giao dịch và hệ thống hiện sẽ gửi lại TransactionTooLargeExceptions dưới dạng RuntimeExceptions, thay vì tự động ghi nhật ký hoặc chặn chúng. Một Một ví dụ phổ biến là lưu trữ quá nhiều dữ liệu trong Activity.onSaveInstanceState(), khiến ActivityThread.StopInfo gửi một RuntimeException khi ứng dụng của bạn nhắm đến Android 7.0.
  • Nếu một ứng dụng đăng Runnable công việc lên View, và View không được gắn với cửa sổ, thì hệ thống đưa tác vụ Runnable vào hàng đợi với View; tác vụ Runnable không thực thi cho đến khi Đã đính kèm View thành một cửa sổ. Hành vi này khắc phục các lỗi sau:
    • Nếu một ứng dụng đã đăng lên View từ một chuỗi không phải chuỗi dự kiến luồng giao diện người dùng của cửa sổ, do đó Runnable có thể chạy trên không đúng luồng.
    • Nếu việc cần làm Runnable được đăng từ một chuỗi không phải là luồng lặp lại, ứng dụng có thể hiển thị tác vụ Runnable.
  • Nếu một ứng dụng trên Android 7.0 có DELETE_PACKAGES quyền cố gắng xoá một gói, nhưng một ứng dụng khác đã cài đặt gói đó, hệ thống yêu cầu người dùng xác nhận. Trong trường hợp này, ứng dụng sẽ có thể STATUS_PENDING_USER_ACTION là trạng thái trả về khi chúng gọi PackageInstaller.uninstall()
  • Nhà cung cấp JCA có tên là Crypto không được dùng nữa vì chỉ thuật toán SHA1PRNG yếu về mặt mật mã. Ứng dụng không thể sử dụng nữa SHA1PRNG lấy khoá (không an toàn) vì nhà cung cấp này không còn sẵn có. Để biết thêm thông tin, hãy xem blog bài đăng Bảo mật "Mã hoá" không dùng nhà cung cấp trong Android K.