Glance로 오류 처리

Glance의 오류 처리를 개선하기 위한 API 기능은 Android 15부터 포함됩니다. 이 페이지에서는 이러한 API와 관련된 권장사항을 제공합니다.

컴포저블이 아닌 구성요소 주변에 try-catch 블록 사용

Compose는 컴포저블 주위에 try-catch 블록을 허용하지 않지만 이러한 블록으로 앱의 다른 로직을 래핑할 수 있습니다. 이렇게 하면 다음 예와 같이 오류 뷰에 Compose를 사용할 수 있습니다.

provideContent {
       var isError = false;
       var data = null
       try {
           val repository = (context.applicationContext as MyApplication).myRepository
           data = repository.loadData()
       } catch (e: Exception) {
           isError = true;
           //handleError
       }

       if (isError) {
           ErrorView()
       } else {
           Content(data)
       }
   }

기본 오류 레이아웃

포착되지 않은 예외나 Compose 오류가 있는 경우 Glance에 기본 오류 레이아웃이 표시됩니다.

오류 유형과 오류를 찾을 수 있는 위치에 관한 제안사항을 보여주는 오류 메시지
그림 1. Glance 1.0 기본 오류 레이아웃
'콘텐츠를 표시할 수 없음'이라는 텍스트가 포함된 상자
그림 2. Glance 1.1.0 기본 오류 레이아웃

Glance를 사용하면 개발자가 컴포지션이 실패할 경우 XML 레이아웃을 대체로 제공할 수 있습니다. 즉, Compose 코드에 오류가 있는 것입니다. 이 오류 UI는 앱 코드에 포착되지 않은 오류가 있는 경우에도 표시됩니다.

class UpgradeWidget : GlanceAppWidget(errorUiLayout = R.layout.error_layout)

이 레이아웃은 사용자가 상호작용할 수 없는 정적 레이아웃이지만 긴급한 경우에 적합합니다.

오류 메시지를 표시하는 제목과 텍스트 필드를 포함합니다.
그림 3. 맞춤 오류 레이아웃 예시

기본 오류 UI에 작업 추가

Glance 1.1.0부터 Glance를 사용하여 기본 오류 처리 코드를 재정의할 수 있습니다. 이렇게 하면 컴포지션에서 포착되지 않은 예외나 오류가 발생할 때 작업 콜백을 추가할 수 있습니다.

이 기능을 사용하려면 onCompositionError() 함수를 재정의합니다.

GlanceAppWidget.onCompositionError(
    context: Context,
    glanceId: GlanceId,
    appWidgetId: Int,
    throwable: Throwable
)

이 함수에서 Glance는 오류 처리를 위해 RemoteViews API로 대체합니다. 이를 통해 XML을 사용하여 레이아웃과 작업 핸들러를 지정할 수 있습니다.

다음 예에서는 의견 보내기 버튼이 포함된 오류 UI를 만드는 방법을 단계별로 보여줍니다.

  1. error_layout.xml 파일을 작성합니다.

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       style="@style/Widget.MyApplication.AppWidget.Error"
       android:id="@android:id/background"
       android:layout_width="match_parent"
       android:textSize="24sp"
       android:layout_height="match_parent"
       android:orientation="vertical">
    
       <TextView
           android:id="@+id/error_title_view"
           android:layout_width="match_parent"
           android:textColor="@color/white"
           android:textFontWeight="800"
           android:layout_height="wrap_content"
           android:text="Example Widget Error" />
    
       <LinearLayout
           android:layout_width="match_parent"
           android:orientation="horizontal"
           android:paddingTop="4dp"
           android:layout_height="match_parent">
    
           <ImageButton
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_gravity="center"
            android:tint="@color/white"
            android:id="@+id/error_icon"
            android:src="@drawable/heart_broken_fill0_wght400_grad0_opsz24"
           />
           <TextView
               android:id="@+id/error_text_view"
               android:layout_width="wrap_content"
               android:textColor="@color/white"
               android:layout_height="wrap_content"
               android:layout_gravity="center"
               android:padding="8dp"
               android:textSize="16sp"
               android:layout_weight="1"
               android:text="Useful Error Message!" />
       </LinearLayout>
    
    </LinearLayout>
    
    
  2. onCompositionError 함수를 재정의합니다.

    override fun onCompositionError(
       context: Context,
       glanceId: GlanceId,
       appWidgetId: Int,
       throwable: Throwable
    ) {
       val rv = RemoteViews(context.packageName, R.layout.error_layout)
       rv.setTextViewText(
           R.id.error_text_view,
           "Error was thrown. \nThis is a custom view \nError Message: `${throwable.message}`"
       )
       rv.setOnClickPendingIntent(R.id.error_icon, getErrorIntent(context, throwable))
       AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, rv)
    }
    
  3. GlanceAppWidgetReceiver를 참조하는 대기 중인 인텐트를 만듭니다.

    private fun getErrorIntent(context: Context, throwable: Throwable): PendingIntent {
        val intent = Intent(context, UpgradeToHelloWorldPro::class.java)
        intent.setAction("widgetError")
        return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
    }
    
    
  4. GlanceAppWidgetReceiver에서 인텐트를 처리합니다.

    override fun onReceive(context: Context, intent: Intent) {
       super.onReceive(context, intent)
       Log.e("ErrorOnClick", "Button was clicked.");
    }