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 tạo một ứng dụng tương tự hoặc thay thế màn hình chính, bạn cũng có thể cho phép người dùng nhúng các tiện ích bằng cách triển khai AppWidgetHost. Đây không phải là điều mà hầu hết các ứng dụng cần làm, nhưng nếu đang tạo máy chủ lưu trữ của riêng mình, thì bạn cần hiểu 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 một AppWidgetHost tuỳ chỉnh. Để biết 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.

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

  • Máy chủ lưu trữ 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 trong giao diện người dùng. AppWidgetHost phải có mã nhận dạng là duy nhất trong gói riêng của máy chủ lưu trữ. Mã này vẫn tồn tại trong mọi trường hợp sử dụng máy chủ. Mã nhận dạng thường là một giá trị được cố định giá trị trong mã mà bạn chỉ định trong ứng dụng của mình.

  • Mã tiện ích ứng dụng: mỗi thực thể tiện ích được gán 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 chi tiết, hãy xem phần Tiện ích liên kết như sau. 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ã nhận dạng này vẫn 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ủ. 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 gói lưu trữ duy trì và liên kết với mã tiện ích ứng dụng.

  • Khung hiển thị máy chủ của tiện ích ứng dụng: hãy coi AppWidgetHostView là một khung mà tiện ích được bao bọc bất cứ khi nào cần 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ủ tăng cường.

    • Theo mặc định, hệ thống tạo một AppWidgetHostView, nhưng máy chủ lưu trữ có thể tạo lớp con AppWidgetHostView riêng bằng cách mở rộng lớp con đó.
    • Kể từ Android 12 (API cấp 31), AppWidgetHostView sẽ giới thiệu các phương thức setColorResources()resetColorResources() để xử lý màu quá tải linh độ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 với AppWidgetProvider về cách hiển thị tiện ích (ví dụ: danh sách phạm vi kích thước) và việc tiện ích đang ở trên màn hình khoá hay màn hình chính. 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()updateAppWidgetSize() để sửa đổi gói của một tiện ích. Cả hai phương thức này đều kích hoạt lệnh gọi lại onAppWidgetOptionsChanged() đến 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ữ, quy trình có tên là liên kết sẽ xảy 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 giúp máy chủ lưu trữ 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 chỉ là bước đầu tiên. Trong thời gian chạy, người dùng phải cấp quyền rõ ràng cho ứng dụng để ứng dụng có thể thêm tiện ích vào máy chủ. Để 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, ứng dụng của bạn phải hiển thị hộp thoại nhắc người dùng cấp quyền: "allow" cho lần thêm tiện ích hiện tại hoặc "always cho phép" để bao gồm mọi tiện ích được thêm vào trong tương lai.

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

Kotlin

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

Java

Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
// This is the options bundle described in the preceding section.
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET);

Máy chủ phải kiểm tra xem tiện ích mà người dùng thêm có cần cấu hình hay không. Để biết thêm thông tin, hãy xem phần 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 đề cập chi tiết hơn trong các phần sau, từ đối tượng AppWidgetProviderInfo liên kết với một trình cung cấp tiện ích.

Bất kể bạn đang nhắm mục tiêu phiên bản Android nào, tất cả máy chủ lưu trữ đều có các trách nhiệm sau:

  • Khi thêm một 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ủ lưu trữ, hãy gọi deleteAppWidgetId() để 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ả hai cờ configuration_optionalreconfigurable. Xem phần Cập nhật tiện ích trong hoạt động cấu hình để biết thông tin chi tiết. Đây là một bước cần thiết đối với nhiều tiện ích trước khi chúng có thể hiển thị.

  • Các tiện ích sẽ 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 ô – kể từ Android 12, nếu targetCellWidthtargetCellHeight được chỉ định, hoặc dps nếu chỉ có minWidthminHeight được chỉ định. Hãy xem phần Thuộc tính kích thước tiện ích.

    Đảm bảo tiện ích được bố trí với ít nhất nhiều dps. Ví dụ: nhiều máy chủ lưu trữ căn chỉnh 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 sử dụng số lượng ô tối thiểu đáp ứng các giới hạn của minWidthminHeight.

Ngoài các yêu cầu nêu trong phần trước, các phiên bản nền tảng cụ thể còn giới thiệu các tính năng đặt trách nhiệm mới trên máy chủ lưu trữ.

Xác định phương pháp tiếp cận của bạn dựa trên phiên bản Android mục tiêu

Android 12

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

Có giới hạn là MAX_INIT_VIEW_COUNT (16) về số lượng RemoteViews khác nhau mà một 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 bạn không nên cung cấp nhiều hơn MAX_INIT_VIEW_COUNT kích thước.

Android 12 cũng giới thiệu các thuộc tính maxResizeWidthmaxResizeHeight trong dps. Bạn nên sử dụng ít nhất một trong các thuộc tính này để tiện ích không vượt quá kích thước do thuộc tính chỉ định.

Tài nguyên khác

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