Cho phép người dùng định cấu hình tiện ích ứng dụng

Tiện ích ứng dụng có thể định cấu hình được. Ví dụ: tiện ích đồng hồ có thể cho phép người dùng định cấu hình múi giờ sẽ hiển thị.

Nếu bạn muốn cho phép người dùng định cấu hình các chế độ cài đặt của tiện ích, hãy tạo một cấu hình tiện ích Activity. Hoạt động này được máy chủ lưu trữ tiện ích ứng dụng tự động chạy khi tiện ích được tạo hoặc sau đó, tuỳ thuộc vào các tuỳ chọn cấu hình mà bạn chỉ định.

Khai báo hoạt động cấu hình

Khai báo hoạt động cấu hình như một hoạt động bình thường trong tệp kê khai Android. Máy chủ lưu trữ tiện ích ứng dụng sẽ chạy tiện ích đó bằng thao tác ACTION_APPWIDGET_CONFIGURE, vì vậy, hoạt động cần chấp nhận ý định này. Ví dụ:

<activity android:name=".ExampleAppWidgetConfigurationActivity">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
    </intent-filter>
</activity>

Khai báo hoạt động trong tệp AppWidgetProviderInfo.xml bằng thuộc tính android:configure. Xem thêm thông tin về cách khai báo tệp này. Dưới đây là ví dụ về cách khai báo hoạt động cấu hình:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    ... >
</appwidget-provider>

Hoạt động được khai báo bằng một không gian tên đủ điều kiện vì trình chạy tham chiếu đến hoạt động đó từ bên ngoài phạm vi gói của bạn.

Đó là tất cả những gì bạn cần để bắt đầu một hoạt động định cấu hình. Tiếp theo, bạn cần triển khai hoạt động thực tế.

Triển khai hoạt động cấu hình

Có 2 điểm quan trọng cần nhớ khi bạn triển khai hoạt động này:

  • Máy chủ lưu trữ tiện ích ứng dụng gọi hoạt động cấu hình và hoạt động cấu hình phải luôn trả về kết quả. Kết quả phải bao gồm mã tiện ích ứng dụng được truyền bởi ý định khởi chạy hoạt động (được lưu trong phần bổ sung ý định dưới dạng EXTRA_APPWIDGET_ID).
  • Hệ thống không gửi thông báo ACTION_APPWIDGET_UPDATE khi một hoạt động cấu hình được chạy, nghĩa là hệ thống sẽ không gọi phương thức onUpdate() khi tiện ích được tạo. Hoạt động định cấu hình có trách nhiệm yêu cầu cập nhật từ AppWidgetManager trong lần đầu tạo tiện ích. Tuy nhiên, onUpdate() được gọi cho các lần cập nhật tiếp theo – chỉ bị bỏ qua trong lần đầu tiên.

Hãy xem các đoạn mã trong phần sau để biết ví dụ về cách trả về kết quả từ cấu hình và cập nhật tiện ích.

Cập nhật tiện ích trong hoạt động cấu hình

Khi một tiện ích sử dụng hoạt động cấu hình, trách nhiệm của hoạt động đó là cập nhật tiện ích khi cấu hình hoàn tất. Bạn có thể thực hiện việc này bằng cách yêu cầu cập nhật trực tiếp từ AppWidgetManager.

Dưới đây là phần tóm tắt quy trình để cập nhật tiện ích đúng cách và đóng hoạt động cấu hình:

  1. Lấy mã tiện ích ứng dụng qua ý định chạy hoạt động:

    Kotlin

    val appWidgetId = intent?.extras?.getInt(
            AppWidgetManager.EXTRA_APPWIDGET_ID,
            AppWidgetManager.INVALID_APPWIDGET_ID
    ) ?: AppWidgetManager.INVALID_APPWIDGET_ID
    

    Java

    Intent intent = getIntent();
    Bundle extras = intent.getExtras();
    int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
    if (extras != null) {
        appWidgetId = extras.getInt(
                AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }
    
  2. Đặt kết quả hoạt động thành RESULT_CANCELED.

    Bằng cách này, nếu người dùng quay lại hoạt động trước khi kết thúc, hệ thống sẽ thông báo cho máy chủ lưu trữ tiện ích ứng dụng rằng cấu hình đã bị huỷ và máy chủ không thêm tiện ích:

    Kotlin

    val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    setResult(Activity.RESULT_CANCELED, resultValue)
    

    Java

    int resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(Activity.RESULT_CANCELED, resultValue);
    
  3. Định cấu hình tiện ích theo lựa chọn ưu tiên của người dùng.

  4. Khi cấu hình hoàn tất, hãy lấy một thực thể của AppWidgetManager bằng cách gọi getInstance(Context):

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    

    Java

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    
  5. Cập nhật tiện ích theo bố cục RemoteViews bằng cách gọi updateAppWidget(int,RemoteViews):

    Kotlin

    val views = RemoteViews(context.packageName, R.layout.example_appwidget)
    appWidgetManager.updateAppWidget(appWidgetId, views)
    

    Java

    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
    appWidgetManager.updateAppWidget(appWidgetId, views);
    
  6. Tạo ý định trả về, đặt ý định bằng kết quả hoạt động và kết thúc hoạt động:

    Kotlin

    val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
    setResult(Activity.RESULT_OK, resultValue)
    finish()
    

    Java

    Intent resultValue = new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
    setResult(RESULT_OK, resultValue);
    finish();
    

Hãy xem lớp mẫu ListWidgetConfigureActivity.kt trên GitHub để biết ví dụ.

Lựa chọn cấu hình tiện ích

Theo mặc định, máy chủ lưu trữ tiện ích ứng dụng chỉ khởi chạy hoạt động cấu hình một lần, ngay sau khi người dùng thêm tiện ích vào màn hình chính. Tuy nhiên, bạn có thể chỉ định các tuỳ chọn cho phép người dùng định cấu hình lại các tiện ích hiện có hoặc bỏ qua cấu hình tiện ích ban đầu bằng cách cung cấp cấu hình tiện ích mặc định.

Cho phép người dùng định cấu hình lại các tiện ích đã đặt

Để cho phép người dùng định cấu hình lại các tiện ích hiện có, hãy chỉ định cờ reconfigurable trong thuộc tính widgetFeatures của appwidget-provider. Xem hướng dẫn khai báo tệp AppWidgetProviderInfo.xml để biết thêm thông tin. Ví dụ:

<appwidget-provider
    android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
    android:widgetFeatures="reconfigurable">
</appwidget-provider>

Người dùng có thể định cấu hình lại tiện ích của họ bằng cách chạm và giữ tiện ích rồi nhấn vào nút ReConfigure (Định cấu hình lại), được gắn nhãn 1 trong hình 1.

Nút xuất hiện ở góc dưới cùng bên phải
Hình 1. Nút ReConfigure (Định cấu hình lại) của tiện ích.

Sử dụng cấu hình mặc định của tiện ích

Bạn có thể cung cấp trải nghiệm tiện ích liền mạch hơn bằng cách cho phép người dùng bỏ qua bước định cấu hình ban đầu. Để làm việc này, hãy chỉ định cả cờ configuration_optionalreconfigurable trong trường widgetFeatures. Thao tác này sẽ bỏ qua việc khởi chạy hoạt động cấu hình sau khi người dùng thêm tiện ích. Như đã đề cập trước đó, người dùng vẫn có thể định cấu hình lại tiện ích sau đó. Ví dụ: một tiện ích đồng hồ có thể bỏ qua cấu hình ban đầu và hiển thị múi giờ của thiết bị theo mặc định.

Dưới đây là ví dụ về cách đánh dấu hoạt động cấu hình là có thể định cấu hình lại và không bắt buộc:

<appwidget-provider
    android:configure="com.myapp.ExampleAppWidgetConfigurationActivity"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

Cho phép người dùng ghim tiện ích

Trên các thiết bị chạy Android 8.0 (API cấp 26) trở lên, các trình chạy cho phép người dùng tạo lối tắt được ghim cũng cho phép ghim tiện ích vào màn hình chính. Tương tự như các lối tắt được ghim, các tiện ích được ghim này cho phép người dùng truy cập vào các thao tác cụ thể trong ứng dụng của bạn và có thể thêm vào màn hình chính ngay từ ứng dụng, như minh hoạ trong video sau.

Ví dụ về bố cục thích ứng
Hình 2. Ví dụ về cách ghim một tiện ích.

Trong ứng dụng của mình, bạn có thể tạo một yêu cầu để hệ thống ghim một tiện ích vào trình chạy được hỗ trợ bằng cách hoàn tất các bước sau:

  1. Đảm bảo bạn khai báo tiện ích trong tệp kê khai của ứng dụng.

  2. Gọi phương thức requestPinAppWidget(), như minh hoạ trong đoạn mã sau:

Kotlin

val appWidgetManager = AppWidgetManager.getInstance(context)
val myProvider = ComponentName(context, ExampleAppWidgetProvider::class.java)

if (appWidgetManager.isRequestPinAppWidgetSupported()) {
    // Create the PendingIntent object only if your app needs to be notified
    // when the user chooses to pin the widget. Note that if the pinning
    // operation fails, your app isn't notified. This callback receives the ID
    // of the newly pinned widget (EXTRA_APPWIDGET_ID).
    val successCallback = PendingIntent.getBroadcast(
            /* context = */ context,
            /* requestCode = */ 0,
            /* intent = */ Intent(...),
            /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT)

    appWidgetManager.requestPinAppWidget(myProvider, null, successCallback)
}

Java

AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName myProvider = new ComponentName(context, ExampleAppWidgetProvider.class);

if (appWidgetManager.isRequestPinAppWidgetSupported()) {
    // Create the PendingIntent object only if your app needs to be notified
    // when the user chooses to pin the widget. Note that if the pinning
    // operation fails, your app isn't notified. This callback receives the ID
    // of the newly pinned widget (EXTRA_APPWIDGET_ID).
    PendingIntent successCallback = PendingIntent.getBroadcast(
            /* context = */ context,
            /* requestCode = */ 0,
            /* intent = */ new Intent(...),
            /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT);

    appWidgetManager.requestPinAppWidget(myProvider, null, successCallback);
}