flutter pub add home_widget
두 타겟 모두 설정해야 한다.
Runner 타겟:
1. Signing & Capabilities 탭 이동
2. + Capability → App Groups 선택
3. group.com.example.app 입력 (Bundle ID에 맞춰 수정)
NewsWidgets 타겟:
1. 동일하게 App Groups 추가
2. 동일한 그룹명 입력
// 데이터 구조 정의
struct NewsArticleEntry: TimelineEntry {
let date: Date
let title: String
let description: String
}
// 위젯 UI 표시
struct NewsWidgetsEntryView : View {
var entry: NewsArticleEntry
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text(entry.title)
.font(.headline)
.lineLimit(2)
Text(entry.description)
.font(.body)
.lineLimit(3)
}
.padding()
}
}
struct Provider: TimelineProvider {
// 위젯 처음 표시할 때 임시 데이터
func placeholder(in context: Context) -> NewsArticleEntry {
NewsArticleEntry(
date: Date(),
title: "제목",
description: "설명"
)
}
// 현재 데이터 가져오기
func getSnapshot(in context: Context, completion: @escaping (NewsArticleEntry) -> ()) {
let userDefaults = UserDefaults(suiteName: "group.com.example.app")
let title = userDefaults?.string(forKey: "headline_title") ?? "제목 없음"
let description = userDefaults?.string(forKey: "headline_description") ?? "설명 없음"
let entry = NewsArticleEntry(
date: Date(),
title: title,
description: description
)
completion(entry)
}
// 위젯 업데이트 일정 설정
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
getSnapshot(in: context) { entry in
let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
android:background="@android:color/white">
<TextView
android:id="@+id/headline_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="제목"
android:textSize="18sp"
android:textStyle="bold"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/headline_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/headline_title"
android:layout_marginTop="8dp"
android:text="설명"
android:textSize="14sp"
android:textColor="@android:color/darker_gray" />
</RelativeLayout>
package com.example.homescreen_widgets
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetPlugin
class NewsWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
) {
// 저장된 데이터 가져오기
val widgetData = HomeWidgetPlugin.getData(context)
for (appWidgetId in appWidgetIds) {
// 위젯 레이아웃 설정
val views = RemoteViews(context.packageName, R.layout.news_widget)
// 제목 설정
val title = widgetData.getString("headline_title", "제목 없음")
views.setTextViewText(R.id.headline_title, title)
// 설명 설정
val description = widgetData.getString("headline_description", "설명 없음")
views.setTextViewText(R.id.headline_description, description)
// 위젯 업데이트
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
flutter pub add home_widget
import 'package:home_widget/home_widget.dart';
Future<void> updateHomeWidget({
required String title,
required String description,
}) async {
try {
// 1. 데이터 저장
await HomeWidget.saveWidgetData<String>('headline_title', title);
await HomeWidget.saveWidgetData<String>('headline_description', description);
// 2. 위젯 업데이트 신호
await HomeWidget.updateWidget(
iOSName: 'NewsWidgets',
androidName: 'NewsWidget',
);
print('위젯 업데이트 완료');
} catch (e) {
print('위젯 업데이트 실패: $e');
}
}
ElevatedButton(
onPressed: () {
updateHomeWidget(
title: '새로운 기사 제목',
description: '기사 요약 내용',
);
},
child: const Text('홈 위젯 업데이트'),
),
Flutter 앱
↓
updateHomeWidget() 호출
↓
HomeWidget.saveWidgetData() → 데이터 저장
├─ iOS: UserDefaults에 저장
└─ Android: SharedPreferences에 저장
↓
HomeWidget.updateWidget() → 위젯 업데이트 신호
↓
iOS 위젯 Android 위젯
Provider.getSnapshot() NewsWidget.onUpdate()
UserDefaults에서 데이터 읽기 SharedPreferences에서 데이터 읽기
UI 업데이트 UI 업데이트
| 항목 | iOS | Android |
|---|---|---|
| 저장소 | UserDefaults | SharedPreferences |
| 앱 그룹 | group.com.example.app | 불필요 |
| 언어 | Swift | Kotlin |
| 레이아웃 | SwiftUI | XML |
| 주요 파일 | NewsWidgets.swift | NewsWidget.kt, news_widget.xml |
홈 위젯은 Flutter 앱이 켜지지 않아도 데이터를 표시한다
home_widget 패키지로 Flutter와 네이티브 코드를 연결하여 앱과 위젯이 데이터를 공유할 수 있다.