Xây dựng máy chủ tiện ích

Màn hình chính của Android (có trên hầu hết các thiết bị chạy Android) cho phép người dùng nhúng tiện ích ứng dụng (hoặc tiện ích) để truy cập nhanh vào nội dung. Nếu đang xây dựng một ứng dụng thay thế màn hình chính hoặc một ứng dụng tương tự, bạn cũng có thể cho phép người dùng nhúng tiện ích bằng cách triển khai AppWidgetHost. Hầu hết các ứng dụng không cần làm việc này, nhưng nếu bạn đang tạo máy chủ lưu trữ của riêng mình, thì điều quan trọng là bạn phải hiểu rõ các nghĩa vụ theo hợp đồng mà máy chủ lưu trữ ngầm đồng ý.

Trang này tập trung vào các trách nhiệm liên quan đến việc triển khai AppWidgetHost tuỳ chỉnh. Để xem ví dụ cụ thể về cách triển khai AppWidgetHost, hãy xem mã nguồn cho màn hình chính của Android LauncherAppWidgetHost.

Sau đây là thông tin tổng quan về các lớp và khái niệm chính liên quan đến việc triển khai AppWidgetHost tuỳ chỉnh:

  • Máy chủ tiện ích ứng dụng: AppWidgetHost cung cấp hoạt động tương tác với dịch vụ AppWidget cho các ứng dụng nhúng tiện ích vào giao diện người dùng. AppWidgetHost phải có mã nhận dạng duy nhất trong gói của máy chủ lưu trữ. Mã nhận dạng này vẫn tồn tại trong tất cả các lần sử dụng máy chủ lưu trữ. Mã nhận dạng thường là một giá trị được mã hoá cứng mà bạn chỉ định trong ứng dụng.

  • Mã tiện ích ứng dụng: mỗi thực thể tiện ích được chỉ định một mã nhận dạng duy nhất tại thời điểm liên kết. Hãy xem bindAppWidgetIdIfAllowed() và để biết thêm thông tin, hãy xem phần Liên kết tiện ích sau đây. Máy chủ lưu trữ lấy mã nhận dạng duy nhất bằng cách sử dụng allocateAppWidgetId(). Mã này tồn tại trong suốt thời gian hoạt động của tiện ích cho đến khi bị xoá khỏi máy chủ lưu trữ. Mọi trạng thái dành riêng cho máy chủ lưu trữ (chẳng hạn như kích thước và vị trí của tiện ích) phải được duy trì bằng gói lưu trữ và liên kết với mã tiện ích ứng dụng.

  • Chế độ xem máy chủ tiện ích ứng dụng: hãy coi AppWidgetHostView như một khung chứa tiện ích bất cứ khi nào tiện ích cần được hiển thị. Một tiện ích được liên kết với một AppWidgetHostView mỗi khi tiện ích đó được máy chủ lưu trữ tăng cường.

    • Theo mặc định, hệ thống sẽ tạo một AppWidgetHostView, nhưng máy chủ lưu trữ có thể tạo lớp con của riêng mình cho AppWidgetHostView bằng cách mở rộng lớp con đó.
    • Kể từ Android 12 (API cấp 31), AppWidgetHostView sẽ ra mắt các phương thức setColorResources() và resetColorResources() để xử lý màu sắc được nạp chồng động. Máy chủ lưu trữ chịu trách nhiệm cung cấp màu sắc cho các phương thức này.
  • Gói tuỳ chọn: AppWidgetHost sử dụng gói tuỳ chọn để truyền đạt thông tin đến AppWidgetProvider về cách hiển thị tiện ích (ví dụ: danh sách phạm vi kích thước) và liệu tiện ích có nằm trên màn hình khoá hay màn hình chính hay không. Thông tin này cho phép AppWidgetProvider điều chỉnh nội dung và giao diện của tiện ích dựa trên cách thức và vị trí hiển thị tiện ích. Bạn có thể sử dụng updateAppWidgetOptions() và updateAppWidgetSize() để sửa đổi gói của tiện ích. Cả hai phương thức này đều kích hoạt lệnh gọi lại onAppWidgetOptionsChanged() cho AppWidgetProvider.

Liên kết tiện ích

Khi người dùng thêm một tiện ích vào máy chủ lưu trữ, một quy trình có tên là liên kết sẽ diễn ra. Liên kết đề cập đến việc liên kết một mã tiện ích ứng dụng cụ thể với một máy chủ lưu trữ cụ thể và một AppWidgetProvider cụ thể.

API liên kết cũng cho phép máy chủ cung cấp giao diện người dùng tuỳ chỉnh để liên kết. Để sử dụng quy trình này, ứng dụng của bạn phải khai báo quyền BIND_APPWIDGET trong tệp kê khai của máy chủ lưu trữ:

<uses-permission android:name="android.permission.BIND_APPWIDGET" />

Nhưng đây mới chỉ là bước đầu tiên. Trong thời gian chạy, người dùng phải cấp quyền một cách rõ ràng cho ứng dụng của bạn để cho phép ứng dụng thêm tiện ích vào máy chủ lưu trữ. Để kiểm tra xem ứng dụng của bạn có quyền thêm tiện ích hay không, hãy sử dụng phương thức bindAppWidgetIdIfAllowed(). Nếu bindAppWidgetIdIfAllowed() trả về false, thì ứng dụng của bạn phải hiển thị một hộp thoại nhắc người dùng cấp quyền: "cho phép" đối với việc thêm tiện ích hiện tại hoặc "luôn cho phép" đối với tất cả các lần thêm tiện ích trong tương lai.

Đoạn mã này đưa ra ví dụ về cách hiển thị hộp thoại:

val intent = Intent(AppWidgetManager.ACTION_APPWIDGET_BIND).apply {
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider)
    // This is the options bundle described in the preceding section.
    putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options)
}
startActivityForResult(intent, REQUEST_BIND_APPWIDGET)

Máy chủ lưu trữ phải kiểm tra xem tiện ích mà người dùng thêm có cần định cấu hình hay không. Để biết thêm thông tin, hãy xem bài viết Cho phép người dùng định cấu hình tiện ích ứng dụng.

Trách nhiệm của người tổ chức

Bạn có thể chỉ định một số chế độ cài đặt cấu hình cho tiện ích bằng cách sử dụng siêu dữ liệu AppWidgetProviderInfo. Bạn có thể truy xuất các tuỳ chọn cấu hình này (được trình bày chi tiết hơn trong các phần sau) từ đối tượng AppWidgetProviderInfo liên kết với một nhà cung cấp tiện ích.

Tất cả người tổ chức đều có những trách nhiệm sau:

  • Khi thêm tiện ích, hãy phân bổ mã tiện ích như mô tả ở trên. Khi một tiện ích bị xoá khỏi máy chủ, hãy gọi deleteAppWidgetId() để huỷ phân bổ mã tiện ích.

  • Khi thêm một tiện ích, hãy kiểm tra xem có cần chạy hoạt động cấu hình hay không. Thông thường, máy chủ lưu trữ cần khởi chạy hoạt động cấu hình của tiện ích nếu hoạt động đó tồn tại và không được đánh dấu là không bắt buộc bằng cách chỉ định cả cờ configuration_optional và reconfigurable. Xem phần Cập nhật tiện ích từ hoạt động cấu hình để biết thông tin chi tiết. Đây là bước cần thiết để nhiều tiện ích có thể hiển thị.

  • Tiện ích chỉ định chiều rộng và chiều cao mặc định trong siêu dữ liệu AppWidgetProviderInfo. Các giá trị này được xác định trong các ô (bắt đầu từ Android 12, nếu targetCellWidth và targetCellHeight được chỉ định) hoặc dp (nếu chỉ có minWidth và minHeight được chỉ định). Xem phần Thuộc tính định cỡ tiện ích.

    Đảm bảo rằng tiện ích được bố trí với ít nhất số dp này. Ví dụ: nhiều máy chủ sắp xếp các biểu tượng và tiện ích trong một lưới. Trong trường hợp này, theo mặc định, máy chủ lưu trữ sẽ thêm một tiện ích bằng cách sử dụng số lượng ô tối thiểu đáp ứng các quy tắc ràng buộc minWidth và minHeight.

Mẹo về cách tiếp cận

Ngoài các yêu cầu nêu trong phần trước, hãy lưu ý những mẹo sau:

Gói tuỳ chọn có thể chứa một List<SizeF> chứa danh sách các kích thước có thể có (tính bằng dp) mà một thực thể tiện ích có thể lấy. Số lượng kích thước được cung cấp phụ thuộc vào cách triển khai của máy chủ lưu trữ. Máy chủ thường cung cấp hai kích thước cho điện thoại (dọc và ngang) và bốn kích thước cho thiết bị có thể gập lại.

Có giới hạn MAX_INIT_VIEW_COUNT (16) về số lượng RemoteViews khác nhau mà AppWidgetProvider có thể cung cấp cho RemoteViews. Vì các đối tượng AppWidgetProvider liên kết một đối tượng RemoteViews với từng kích thước trong List<SizeF>, nên đừng cung cấp nhiều hơn MAX_INIT_VIEW_COUNT kích thước.

Khi các tiện ích chỉ định thuộc tính maxResizeWidth và maxResizeHeight theo dp, bạn nên sử dụng tiện ích dùng ít nhất một trong các thuộc tính này không vượt quá kích thước mà các thuộc tính chỉ định.

Tài nguyên khác

  • Hãy xem tài liệu tham khảo về Glance.