Tiếp tục nhiều lần (multi-resume)

Trong Android 9 (trở xuống), các ứng dụng sẽ chuyển sang trạng thái PAUSED khi:

  • Một hoạt động mới, trong mờ được khởi chạy trên đầu ứng dụng, trong khi ứng dụng vẫn hiển thị (và do đó, không bị dừng).
  • Hoạt động mất tiêu điểm, nhưng không bị che khuất và người dùng có thể tương tác với hoạt động đó. Ví dụ: ở chế độ nhiều cửa sổ, một số hoạt động có thể xuất hiện và nhận dữ liệu đầu vào bằng thao tác chạm cùng lúc.

Những trường hợp này khác nhau về thời gian tạm dừng mà ứng dụng phải thực hiện nhưng không thể phân biệt ở cấp ứng dụng.

Trong Android 10, tất cả các hoạt động có thể lấy tiêu điểm ở trên cùng trong các ngăn xếp hiển thị đều nằm ở trạng thái RESUMED. Điều này giúp cải thiện khả năng tương thích với chế độ Nhiều cửa sổ và chế độ MD cho những ứng dụng sử dụng onPause() thay vì onStop() để ngừng làm mới giao diện người dùng và tương tác với người dùng. Điều này có nghĩa là:

  • Cả hai hoạt động ở chế độ chia đôi màn hình đều được tiếp tục.
  • Tất cả các hoạt động hiển thị ở trên cùng trong chế độ cửa sổ có thể thay đổi kích thước đều được tiếp tục.
  • Các hoạt động trên nhiều màn hình có thể được tiếp tục cùng một lúc.

Hình 1. Tính năng tiếp tục nhiều lần trên thiết bị có thể gập lại

Hình 2. Tính năng tiếp tục nhiều lần ở chế độ máy tính

Các hoạt động có thể ở trạng thái PAUSED khi không thể lấy làm tâm điểm hoặc bị che khuất một phần, chẳng hạn như:

  • Ở chế độ chia đôi màn hình thu nhỏ (với trình chạy ở bên cạnh), hoạt động trên cùng sẽ không tiếp tục vì không thể lấy tiêu điểm.
  • Ở chế độ hình trong hình, hoạt động sẽ không tiếp tục vì không thể lấy hoạt động đó làm tâm điểm.
  • Khi các hoạt động bị những hoạt động trong suốt khác che phủ trong cùng một ngăn xếp.

Phương pháp này cho biết với các ứng dụng rằng một hoạt động chỉ có thể nhận dữ liệu đầu vào từ người dùng ở trạng thái RESUMED. Trước Android 10, các hoạt động cũng có thể nhận dữ liệu đầu vào ở trạng thái PAUSED (ví dụ: thử chạm đồng thời vào cả hai hoạt động ở chế độ chia đôi màn hình trên thiết bị chạy Android 9).

Để duy trì tín hiệu đã tiếp tục từ các bản phát hành Android trước đó (và để thông báo thời điểm ứng dụng nên có quyền truy cập vào các tài nguyên chỉ có quyền truy cập hoặc tài nguyên đơn nhất), Android 10 có một lệnh gọi lại mới:

Activity#onTopResumedActivityChanged(boolean onTop)

Khi được gọi, lệnh gọi lại này sẽ được gọi trong khoảng thời gian từ Activity#onResume() đến Activity#onPause(). Lệnh gọi lại này không bắt buộc và có thể bỏ qua, vì vậy, một hoạt động có thể chuyển từ trạng thái RESUMED sang trạng thái PAUSED mà không trở thành hoạt động ở trên cùng trong hệ thống. Ví dụ: ở chế độ nhiều cửa sổ. Vì lệnh gọi lại này là không bắt buộc, nên nó không thuộc Vòng đời của hoạt động và hiếm khi được dùng.

Hoạt động được tiếp tục ở trên cùng trước đó sẽ nhận và hoàn tất việc thực thi onTopResumedActivity(false) trước khi hoạt động được tiếp tục ở trên cùng tiếp theo nhận onTopResumedActivity(true), trừ phi hoạt động trước đó mất quá nhiều thời gian để xử lý lệnh gọi phương thức và đạt đến thời gian chờ là 500 mili giây.

Khả năng tương thích

Để duy trì khả năng tương thích khi triển khai tính năng tiếp tục nhiều hoạt động, hãy cân nhắc những giải pháp sau.

Nhiều hoạt động được tiếp tục trong một quy trình ứng dụng

  • Vấn đề. Trong Android 9 trở xuống, hệ thống chỉ tiếp tục một hoạt động tại một thời điểm. Tất cả các quá trình chuyển đổi giữa các hoạt động đều liên quan đến việc tạm dừng một hoạt động trước khi tiếp tục một hoạt động khác. Một số ứng dụng và khung (chẳng hạn như Flutter hoặc LocalActivityManager của Android) sử dụng thực tế này và lưu trạng thái về hoạt động được tiếp tục trong các singleton.
  • Giải pháp. Trong Android 9 trở xuống, nếu cả hai hoạt động trong cùng một quy trình đều được tiếp tục, hệ thống sẽ chỉ tiếp tục hoạt động có thứ tự Z cao hơn. Các ứng dụng nhắm đến Android 10 có thể hỗ trợ nhiều hoạt động được tiếp tục cùng một lúc.

Quyền truy cập đồng thời vào camera

  • Vấn đề. Những vấn đề này cũng xuất hiện trong Android 9 trở xuống. Ví dụ: một hoạt động toàn màn hình và được tiếp tục có thể mất tiêu điểm camera vào một hoạt động bị tạm dừng ở trên cùng trong chế độ hình trong hình nhưng sẽ hiển thị nhiều hơn khi chế độ nhiều cửa sổ và nhiều màn hình được áp dụng rộng rãi hơn.
    • Do những thay đổi đối với trạng thái RESUME, các ứng dụng có thể bị ngắt kết nối với camera ngay cả khi được tiếp tục. Để giải quyết vấn đề này, các ứng dụng phải xử lý tình huống camera bị ngắt kết nối mà không gặp sự cố. Khi bị ngắt kết nối, các ứng dụng sẽ nhận được lệnh gọi lại đã ngắt kết nối và tất cả các lệnh gọi vào API sẽ bắt đầu truyền CameraAccessException.
    • resizeableActivity=false không đảm bảo quyền truy cập độc quyền vào camera vì các ứng dụng khác sử dụng camera có thể được mở trên các màn hình khác.
  • Giải pháp. Nhà phát triển nên thêm logic cho trường hợp ứng dụng bị ngắt kết nối với camera. Nếu một ứng dụng bị ngắt kết nối với camera, ứng dụng đó sẽ theo dõi các lệnh gọi lại về trạng thái sẵn sàng của camera để cố gắng kết nối lại và tiếp tục sử dụng camera. Ngoài lệnh gọi lại CameraManager#AvailabilityCallback#onCameraAvailable() hiện có, Android 10 còn thêm CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged(), bao gồm trường hợp tiêu điểm (và mức độ ưu tiên của camera) chuyển đổi giữa một số hoạt động được tiếp tục. Nhà phát triển ứng dụng nên sử dụng cả hai lệnh gọi lại này để xác định thời điểm thích hợp để thử truy cập vào camera.

Tiếp tục nhiều lần (multi-resume)

Trong Android 10, trạng thái vòng đời hoạt động được xác định bằng khả năng hiển thị và thứ tự Z. Để đảm bảo trạng thái chính xác sau khi cập nhật chế độ hiển thị trên một hoạt động và đánh giá trạng thái vòng đời nào có thể áp dụng, hãy gọi phương thức ActivityRecord#makeActiveIfNeeded() từ nhiều vị trí. Trong Android 10, trạng thái hoạt động có nghĩa là RESUMED hoặc PAUSED và chỉ hoạt động trong 2 trường hợp này.

Trong Android 10, việc tiếp tục một hoạt động được theo dõi riêng trong từng ngăn xếp thay vì ở một vị trí duy nhất trong hệ thống. Điều này là do bạn có thể thực hiện đồng thời một số hiệu ứng chuyển đổi hoạt động ở chế độ nhiều cửa sổ. Để biết thông tin chi tiết, hãy xem ActivityStack#mInResumeTopActivity.

Lệnh gọi lại hoạt động được tiếp tục hàng đầu

Sau những hành động có thể dẫn đến thay đổi hoạt động hàng đầu (chẳng hạn như khởi chạy, tiếp tục hoạt động hoặc thay đổi thứ tự Z), ActivityStackSupervisor#updateTopResumedActivityIfNeeded() sẽ được gọi. Phương thức này kiểm tra xem hoạt động tiếp tục ở trên cùng có thay đổi hay không và thực hiện việc cập nhật nếu cần. Nếu hoạt động được tiếp tục ở trên cùng trước đó chưa giải phóng trạng thái được tiếp tục ở trên cùng, thì một thông báo mất trạng thái được tiếp tục ở trên cùng sẽ được gửi đến hoạt động đó và một thời gian chờ sẽ được lên lịch ở phía máy chủ (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). Báo cáo về trạng thái được tiếp tục ở trên cùng sẽ được gửi đến hoạt động tiếp theo sau khi hoạt động trước đó giải phóng trạng thái hoặc khi hết thời gian chờ (xem các cách sử dụng:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

Một mục giao dịch TopResumedActivityChangeItem mới đã được thêm vào để báo cáo các thay đổi về trạng thái được tiếp tục hàng đầu cho các ứng dụng và tận dụng cấu trúc ActivityLifecycler từ Android 9.

Trạng thái được tiếp tục ở trên cùng được lưu trữ ở phía máy khách và mỗi khi hoạt động chuyển sang RESUMED hoặc PAUSED, hoạt động này cũng sẽ kiểm tra xem có nên gọi lại onTopResumedActivityChanged() hay không. Điều này cho phép tách rời một số yếu tố trong quá trình giao tiếp về trạng thái vòng đời và trạng thái được tiếp tục hàng đầu giữa phía máy chủ và phía ứng dụng.