사용자가 앱 위젯을 구성하도록 사용 설정

앱 위젯을 구성할 수 있습니다. 예를 들어 시계 위젯을 사용하면 사용자가 표시할 시간대를 구성할 수 있습니다.

사용자가 위젯 설정을 구성할 수 있게 하려면 위젯 구성 Activity를 만듭니다. 이 활동은 개발자가 지정한 구성 옵션에 따라 위젯이 생성될 때 또는 나중에 앱 위젯 호스트에 의해 자동으로 실행됩니다.

구성 활동 선언

Android 매니페스트 파일에서 구성 활동을 일반 활동으로 선언합니다. 앱 위젯 호스트는 ACTION_APPWIDGET_CONFIGURE 작업으로 위젯을 실행하므로 활동은 이 인텐트를 수락해야 합니다. 예:

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

android:configure 속성을 사용하여 AppWidgetProviderInfo.xml 파일에서 활동을 선언합니다. 자세한 내용은 이 파일 선언을 참고하세요. 다음은 구성 활동을 선언하는 방법의 예입니다.

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

런처가 패키지 범위 외부에서 활동을 참조하므로 활동은 정규화된 네임스페이스로 선언됩니다.

이것으로 구성 활동을 시작하면 됩니다. 다음으로 실제 활동을 구현해야 합니다.

구성 활동 구현

활동을 구현할 때 기억해야 할 두 가지 중요한 사항이 있습니다.

  • 앱 위젯 호스트가 구성 활동을 호출하고 구성 활동은 항상 결과를 반환해야 합니다. 결과에는 활동을 실행한 인텐트에서 전달한 앱 위젯 ID가 포함되어야 하며 이는 인텐트 추가 항목에 EXTRA_APPWIDGET_ID로 저장됩니다.
  • 시스템은 구성 활동이 시작될 때 ACTION_APPWIDGET_UPDATE 브로드캐스트를 전송하지 않습니다. 즉, 위젯이 생성될 때 onUpdate() 메서드를 호출하지 않습니다. 위젯을 처음으로 만들 때 AppWidgetManager에서 업데이트를 요청하는 것은 구성 활동의 책임입니다. 그러나 후속 업데이트에서는 onUpdate()가 호출되며 처음 업데이트할 때만 건너뜁니다.

구성의 결과를 반환하고 위젯을 업데이트하는 방법의 예는 다음 섹션의 코드 스니펫을 참고하세요.

구성 활동에서 위젯 업데이트

위젯이 구성 활동을 사용하는 경우 구성 완료 시 위젯을 업데이트하는 것은 활동의 책임입니다. AppWidgetManager에서 직접 업데이트를 요청하면 됩니다.

다음은 위젯을 올바르게 업데이트하고 구성 활동을 닫는 절차를 요약한 것입니다.

  1. 활동을 실행한 인텐트에서 앱 위젯 ID를 가져옵니다.

    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. 활동 결과를 RESULT_CANCELED로 설정합니다.

    이렇게 하면 사용자가 끝에 도달하기 전에 활동을 중단하면 시스템은 앱 위젯 호스트에 구성이 취소되고 호스트가 위젯을 추가하지 않는다고 알립니다.

    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. 사용자의 환경설정에 따라 위젯을 구성합니다.

  4. 구성이 완료되면 getInstance(Context)를 호출하여 AppWidgetManager의 인스턴스를 가져옵니다.

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    

    Java

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    
  5. updateAppWidget(int,RemoteViews)를 호출하여 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. 반환 인텐트를 만들고 활동 결과로 설정하고 활동을 완료합니다.

    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();
    

예는 GitHub의 ListWidgetConfigureActivity.kt 샘플 클래스를 참고하세요.

위젯 구성 옵션

기본적으로 앱 위젯 호스트는 사용자가 홈 화면에 위젯을 추가한 직후에 구성 활동을 한 번만 실행합니다. 그러나 기본 위젯 구성을 제공하여 사용자가 기존 위젯을 재구성하거나 초기 위젯 구성을 건너뛸 수 있는 옵션을 지정할 수 있습니다.

사용자가 배치된 위젯을 재구성할 수 있도록 함

사용자가 기존 위젯을 재구성할 수 있도록 하려면 appwidget-providerwidgetFeatures 속성에 reconfigurable 플래그를 지정합니다. 자세한 내용은 AppWidgetProviderInfo.xml 파일 선언 가이드를 참고하세요. 예:

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

사용자는 위젯을 길게 터치하고 그림 1에서 1로 표시된 Reconfigure(재구성) 버튼을 탭하여 위젯을 재구성할 수 있습니다.

버튼은 오른쪽 하단에 표시됩니다.
그림 1. 위젯 재구성 버튼.

위젯의 기본 구성 사용

사용자가 초기 구성 단계를 건너뛰도록 허용하여 더 원활한 위젯 환경을 제공할 수 있습니다. 이렇게 하려면 widgetFeatures 필드에 configuration_optional 플래그와 reconfigurable 플래그를 모두 지정합니다. 이를 통해 사용자가 위젯을 추가한 후 구성 활동 실행을 우회할 수 있습니다. 앞서 언급했듯이 사용자는 나중에 위젯을 재구성할 수 있습니다. 예를 들어 시계 위젯은 초기 구성을 우회하고 기본적으로 기기 시간대를 표시할 수 있습니다.

다음은 구성 활동을 재구성 및 선택사항으로 표시하는 방법을 보여주는 예입니다.

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

사용자가 위젯을 고정하도록 허용하기

Android 8.0 (API 수준 26) 이상을 실행하는 기기에서는 사용자가 고정된 바로가기를 만들 수 있는 런처를 사용하면 위젯을 홈 화면에 고정할 수도 있습니다. 고정된 바로가기와 마찬가지로 이러한 고정된 위젯을 통해 사용자는 앱의 특정 작업에 액세스할 수 있으며 다음 동영상과 같이 앱에서 직접 홈 화면에 추가할 수 있습니다.

반응형 레이아웃의 예
그림 2. 위젯 고정 예

앱에서 다음 단계를 완료하여 지원되는 런처에 위젯을 고정하도록 시스템에 요청하는 요청을 생성할 수 있습니다.

  1. 앱의 매니페스트 파일에서 위젯을 선언해야 합니다.

  2. 다음 코드 스니펫과 같이 requestPinAppWidget() 메서드를 호출합니다.

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);
}