본 포스트에서는 Flutter 앱에서 홈 위젯을 만들어 앱을 더욱 멋지고 화려하게 만드는 방법을 알고자 합니다.
위젯의 버튼을 클릭하면 환율이 변경됩니다.
현재 환율은 랜덤으로 변경된다. -> url 페이지에 받아와서 출력해야함
1. pubspec.yaml home_widget 패키지를 추가
dependencies:
home_widget: ^0.3.0
pubspec.yaml
name: webview_flutter_onlyweb_kt
description: A new Flutter project.
# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0+1
environment:
sdk: '>=3.1.1 <4.0.0'
#sdk: '>=2.19.1 <3.0.0'
# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
webview_flutter: ^4.2.2
flutter_inappwebview: ^5.3.2
hex: ^0.2.0
flutter_launcher_icons: ^0.13.1
http: ^0.13.6
dynatrace_flutter_plugin: ^3.275.1
home_widget: ^0.3.0
dev_dependencies:
flutter_test:
sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^2.0.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
# For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages
2. layout / xml 디렉토리 및 파일 생성
- android/app/src/main/res/layout/widget_layout.xml
- android/app/src/main/res/xml/widget_info.xml
widget_layout.xml
<LinearLayout
android:id="@+id/widget_root"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="280dp"
android:layout_height="210dp"
android:background="#1f303d"
android:orientation="vertical">
<TextView
android:id="@+id/tv_counter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="12dp"
android:text="--"
android:textColor="@android:color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_prdcd_sell"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="12dp"
android:text="--"
android:textColor="@android:color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/tv_prdcd_buy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="12dp"
android:text="--"
android:textColor="@android:color/white"
android:textSize="16sp" />
<Button
android:id="@+id/bt_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="환율 업데이트"
android:textColor="@android:color/holo_blue_dark"
android:textSize="12sp" />
</LinearLayout>
widget_info.xml
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_layout"
android:minWidth="280dp"
android:minHeight="210dp"
android:minResizeWidth="280dp"
android:minResizeHeight="210dp"
android:widgetCategory="home_screen" />
3. MainActivity 클래스가 포함된 디렉터리에 WidgetProvider.kt 추가
WidgetProvider.kt
package com.coforward.webview_flutter_onlyweb_kt
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.widget.RemoteViews
import es.antonborri.home_widget.HomeWidgetBackgroundIntent
import es.antonborri.home_widget.HomeWidgetLaunchIntent
import es.antonborri.home_widget.HomeWidgetProvider
class AppWidgetProvider : HomeWidgetProvider() {
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
appWidgetIds.forEach { widgetId ->
val views = RemoteViews(context.packageName, R.layout.widget_layout).apply {
// Open App on Widget Click
val pendingIntent = HomeWidgetLaunchIntent.getActivity(context,
MainActivity::class.java)
setOnClickPendingIntent(R.id.widget_root, pendingIntent)
val counter = widgetData.getInt("_counter", 0)
val prdcdSellString = widgetData.getString("_prdcdSell", "0")
val prdcdBuyString = widgetData.getString("_prdcdBuy", "0")
var counterText = "현재 카운터 : $counter"
val counterTextSell = "USD/KRW 팔때 $prdcdSellString"
val counterTextBuy = "USD/KRW 살때 $prdcdBuyString"
setTextViewText(R.id.tv_counter, counterText)
setTextViewText(R.id.tv_prdcd_sell, counterTextSell)
setTextViewText(R.id.tv_prdcd_buy, counterTextBuy)
// Pending intent to update counter on button click
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context,
Uri.parse("myAppWidget://updatecounter"))
setOnClickPendingIntent(R.id.bt_update, backgroundIntent)
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
}
4. home_widget 패키지를 사용하여 flutter에서 백그라운드로 위젯 데이터를 검색하고 업데이트 위해 main.dart 수정
main.dart
Future<void> main() async {
// 앱 초기화 로직 및 설정
await initialization(null);
// Dynatrace 초기화
Dynatrace().startWithoutWidget();
WidgetsFlutterBinding.ensureInitialized();
await HomeWidget.registerBackgroundCallback(backgroundCallback);
runApp(
const MaterialApp(
home: WebViewApp(),
),
);
}
...
...
Future<void> backgroundCallback(Uri? uri) async {
if (uri?.host == 'updatecounter') {
double randomNumberSell = generateRandomNumber(1200.0, 1299.99);
String prdcdSell = randomNumberSell.toStringAsFixed(2);
double randomNumberBuy = generateRandomNumber(1300.0, 1399.99);
String prdcdBuy = randomNumberBuy.toStringAsFixed(2);
print("랜덤 숫자 Sell: $prdcdSell");
print("랜덤 숫자 Buy : $prdcdBuy");
int _counter = 0;
await HomeWidget.getWidgetData<int>('_counter', defaultValue: 0)
.then((int? value) {
_counter = value ?? 0;
_counter++;
});
await HomeWidget.saveWidgetData<String>('_prdcdSell', prdcdSell);
await HomeWidget.saveWidgetData<String>('_prdcdBuy', prdcdBuy);
await HomeWidget.saveWidgetData<int>('_counter', _counter);
await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider');
}
}
double generateRandomNumber(double min, double max) {
Random random = Random();
return min + random.nextDouble() * (max - min);
}
5. AndroidManifest.xml에 앱 위젯에 대한 수신기와 백그라운드 서비스를 추가
AndroidManifest.xml
...
</activity>
<!-- Your Background receiver and service goes here -->
<receiver android:name="AppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/widget_info" />
</receiver>
<receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver">
<intent-filter>
<action android:name="es.antonborri.home_widget.action.BACKGROUND" />
</intent-filter>
</receiver>
<service android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true"/>
...
혹시
안드로이드 스튜디오 프로젝트를 코틀린으로 설정했는데도
WidgetProvider.kt 파일의 import 시 빨간색으로 나타나면
flutter 버전을 확인해보고 flutter upgrade 하면 해결된다.
참고
https://pub.dev/packages/home_widget
https://medium.com/@ashishgarg1998/how-to-create-home-screen-app-widgets-in-flutter-ce3458f3638e
https://developer.android.com/guide/topics/appwidgets?hl=ko#CreatingLayout
'프로그래밍 > flutter' 카테고리의 다른 글
[flutter] Flutter에서 홈 화면 앱 위젯 2개 만드는 방법 (안드로이드) (0) | 2023.10.25 |
---|---|
[flutter] 인터넷에서 데이터 가져오기 GET/POST (fetch) (0) | 2023.10.25 |
[flutter] 안드로이드 apk 만들기 (0) | 2023.10.19 |
[flutter] 화면 방향을 세로/가로 고정 방법 (0) | 2023.09.26 |
[flutter] 화면의 가로 및 세로 크기를 가져오기(휴대폰/패드 등) (0) | 2023.09.26 |