Flutter+Android/ios 桌面组件
总结:
- Android和iOS 桌面小组件 需要原生去绘制小组件和更新数据,Flutter层 可以使用 MethodChannel 与原生 通讯 来控制 更新数据,app无法主动控制 小组件的添加 和 删除, 只能是用户手动操作 。
- 小组件支持表现的内容包括:文字,图片,列表,假造时钟,勾选框,进度条等,注意:只能表现原生的view 不可表现自定义画的view。
- 负一屏:Google原生暂时还没开放API可以直接添加小组件到负一屏,目前Google原生的负一屏 是一个简单的 消息 feed流 不可自定义编辑,国内的很多厂商整合了负一屏和桌面小组件,也就说小组件可以直接添加在负一屏,不外开辟需要适配不同的厂商体系如小米,华为,Oppo,vivo等,iOS负一屏 也可以自定义编辑,小组件直接添加在负一屏。
官方文档:
Android小组件:https://developer.android.com/develop/ui/views/appwidgets?hl=zh-cn
IOS小组件:https://developer.apple.com/cn/documentation/widgetkit/creating-a-widget-extension/
小米小部件:https://dev.mi.com/console/doc/detail?pId=2465
华为荣耀小组件:https://developer.honor.com/cn/doc/guides/100170
Oppo小组件:https://open.oppomobile.com/new/developmentDoc/info?id=12704
vivo小组件:https://developers.vivo.com/doc/d/e88425fe41c94924a052e98dd956c0fb
参考文档:
Flutter小组件开辟:https://juejin.cn/post/6933559401462628365
Android小组件开辟:https://juejin.cn/post/7296031991320870912
上手开辟:
使用Flutter插件:home_widget
插件地点:https://pub-web.flutter-io.cn/packages/home_widget
iOSAndroid 平台设置
为了正常工作,需要一些特定于平台的设置。请查看以下内容,了解怎样添加对 Android 和 iOS 的支持
iOS 在 Xcode 中将小部件添加到您的应用程序
通过添加小部件扩展 File > New > Target > Widget Extension
添加groupId
您需要向应用程序和小部件扩展添加一个groupId
注意:为了添加 groupId,您需要一个付费的 Apple 开辟者帐户
转到您的Apple 开辟者帐户并添加一个新组。将此组添加到您的 Runner 和 XCode 内的 Widget Extension: Signing & Capabilities > App Groups > +。
(要在您的应用程序和扩展程序之间交换,请更改目的)
同步 CFBundleVersion(可选)
此步调是可选的,这会将小部件扩展构建版本与您的应用程序版本同步,因此您在上传应用程序时不会收到 App Store Connect 版本不匹配的警告。

在您的 Runner(应用程序)目的中,转到 Build Phases > + > New Run Script Phase 并添加以下脚本:
- generatedPath="$SRCROOT/Flutter/Generated.xcconfig"
- # Read and trim versionNumber and buildNumber
- versionNumber=$(grep FLUTTER_BUILD_NAME "$generatedPath" | cut -d '=' -f2 | xargs)
- buildNumber=$(grep FLUTTER_BUILD_NUMBER "$generatedPath" | cut -d '=' -f2 | xargs)
- infoPlistPath="$SRCROOT/HomeExampleWidget/Info.plist"
- # Check and add CFBundleVersion if it does not exist
- /usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$infoPlistPath" 2>/dev/null
- if [ $? != 0 ]; then
- /usr/libexec/PlistBuddy -c "Add :CFBundleVersion string $buildNumber" "$infoPlistPath"
- else
- /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$infoPlistPath"
- fi
- # Check and add CFBundleShortVersionString if it does not exist
- /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" "$infoPlistPath" 2>/dev/null
- if [ $? != 0 ]; then
- /usr/libexec/PlistBuddy -c "Add :CFBundleShortVersionString string $versionNumber" "$infoPlistPath"
- else
- /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $versionNumber" "$infoPlistPath"
- fi
复制代码 将HomeExampleWidget 更换为您创建的小部件扩展文件夹的名称。
编写你的小组件
Check the Example App for an Implementation of a Widget.
A more detailed overview on how to write Widgets for iOS 14 can be found on the Apple Developer documentation.
In order to access the Data send with Flutter can be access with
查抄示例应用程序以了解小部件的实现。有关怎样为 iOS 14 编写 Widget 的更详细概述可以在Apple 开辟人员文档中找到。为了访问使用 Flutter 发送的数据,可以使用
- let data = UserDefaults.init(suiteName:"YOUR_GROUP_ID")
复制代码 Android (Jetpack Glance) 将 Jetpack Glance 添加为应用程序 Gradle 文件的依靠项
- implementation 'androidx.glance:glance-appwidget:LATEST-VERSION'
复制代码 在 android/app/src/main/res/xml中创建小部件配置
- <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:initialLayout="@layout/glance_default_loading_layout"
- android:minWidth="40dp"
- android:minHeight="40dp"
- android:resizeMode="horizontal|vertical"
- android:updatePeriodMillis="10000">
- </appwidget-provider>
复制代码 将 WidgetReceiver 添加到 AndroidManifest
- <receiver android:name=".glance.HomeWidgetReceiver"
- android:exported="true">
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- <meta-data
- android:name="android.appwidget.provider"
- android:resource="@xml/home_widget_glance_example" />
- </receiver>
复制代码 创建 WidgetReceiver
要获得主动更新,您应该从 HomeWidgetGlanceWidgetReceiver 扩展
Your Receiver should then look like this
你的Receiver 应该看起来像这样
- package es.antonborri.home_widget_example.glance
- import HomeWidgetGlanceWidgetReceiver
- class HomeWidgetReceiver : HomeWidgetGlanceWidgetReceiver<HomeWidgetGlanceAppWidget>() {
- override val glanceAppWidget = HomeWidgetGlanceAppWidget()
- }
复制代码 构建您的 AppWidget
- class HomeWidgetGlanceAppWidget : GlanceAppWidget() {
- /**
- * Needed for Updating
- */
- override val stateDefinition = HomeWidgetGlanceStateDefinition()
- override suspend fun provideGlance(context: Context, id: GlanceId) {
- provideContent {
- GlanceContent(context, currentState())
- }
- }
- @Composable
- private fun GlanceContent(context: Context, currentState: HomeWidgetGlanceState) {
- // Use data to access the data you save with
- val data = currentState.preferences
-
- // Build Your Composable Widget
- Column(
- ...
- }
复制代码 Android (XML) 在 android/app/src/main/res/layout中创建小部件布局
在 android/app/src/main/res/xml中创建小部件配置
- <?xml version="1.0" encoding="utf-8"?>
- <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
- android:minWidth="40dp"
- android:minHeight="40dp"
- android:updatePeriodMillis="86400000"
- android:initialLayout="@layout/example_layout"
- android:resizeMode="horizontal|vertical"
- android:widgetCategory="home_screen">
- </appwidget-provider>
复制代码 将 WidgetReceiver 添加到 AndroidManifest
- <receiver android:name="HomeWidgetExampleProvider" android:exported="true">
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/home_widget_example" />
- </receiver>
复制代码 编写你的 WidgetProvider
For convenience, you can extend from HomeWidgetProvider which gives you access to a SharedPreferences Object with the Data in the onUpdate method.
In case you don’t want to use the convenience Method you can access the Data using
为了方便起见,您可以从HomeWidgetProvider举行扩展,它使您可以通过onUpdate方法中的数据访问 SharedPreferences 对象。假如您不想使用方便的方法,您可以使用以下方式访问数据
- import es.antonborri.home_widget.HomeWidgetPlugin
- ...
- HomeWidgetPlugin.getData(context)
复制代码 这将使您可以访问类似的 SharedPreferences
更多信息
For more Information on how to create and configure Android Widgets, check out this guide on the Android Developers Page.
有关怎样创建和配置 Android Widget 的更多信息,请查看 Android 开辟人员页面上的本指南。
用法
设置
iOS For iOS, you need to call HomeWidget.setAppGroupId('YOUR_GROUP_ID');
Without this you won’t be able to share data between your App and the Widget and calls to saveWidgetData and getWidgetData will return an error
对于iOS,您需要调用HomeWidget.setAppGroupId(‘YOUR_GROUP_ID’);假如没有这个,您将无法在应用程序和小部件之间共享数据,并且调用saveWidgetData和getWidgetData将返回错误
保存数据
In order to save Data call HomeWidget.saveWidgetData<String>('id', data)
更新小组件
In order to force a reload of the HomeScreenWidget you need to call
为了逼迫重新加载 HomeScreenWidget,您需要调用
- HomeWidget.updateWidget(
- name: 'HomeWidgetExampleProvider',
- androidName: 'HomeWidgetExampleProvider',
- iOSName: 'HomeWidgetExample',
- qualifiedAndroidName: 'com.example.app.HomeWidgetExampleProvider',
- );
复制代码 The name for Android will be chosen by checking qualifiedAndroidName, falling back to <packageName>.androidName and if that was not provided it will fallback to <packageName>.name.
This Name needs to be equal to the Classname of the WidgetProvider
Android 的名称将通过查抄qualifiedAndroidName来选择,回退到.androidName ,假如未提供,它将回退到.name 。该名称需要等于WidgetProvider的类名
The name for iOS will be chosen by checking iOSName if that was not provided it will fallback to name.
This name needs to be equal to the Kind specified in you Widget
iOS 的名称将通过查抄iOSName来选择,假如未提供,它将回退到name 。该名称需要等于您在 Widget 中指定的 Kind
Android (Jetpack Glance)
If you followed the guide and use HomeWidgetGlanceWidgetReceiver as your Receiver, HomeWidgetGlanceStateDefinition as the AppWidgetStateDefinition, currentState() in the composable view and currentState.preferences for data access. No further work is necessary.
假如您按照指南操作并使用HomeWidgetGlanceWidgetReceiver作为吸收器、使用HomeWidgetGlanceStateDefinition作为 AppWidgetStateDefinition、可组合视图中的currentState()以及用于数据访问的currentState.preferences 。不需要进一步的工作。
Android (XML)
Calling HomeWidget.updateWidget only notifies the specified provider.
To update widgets using this provider,
update them from the provider like this:
调用HomeWidget.updateWidget仅通知指定的提供程序。要使用此提供程序更新小部件,请从提供程序更新它们,如下所示:
- class HomeWidgetExampleProvider : HomeWidgetProvider() {
- override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
- appWidgetIds.forEach { widgetId ->
- val views = RemoteViews(context.packageName, R.layout.example_layout).apply {
- // ...
- }
- // Update widget.
- appWidgetManager.updateAppWidget(widgetId, views)
- }
- }
- }
复制代码 检索数据
To retrieve the current Data saved in the Widget call HomeWidget.getWidgetData<String>('id', defaultValue: data)
要检索保存在小部件中的当前数据,请调用HomeWidget.getWidgetData(‘id’, defaultValue: data)
交互式小部件
Android 和 iOS(从 iOS 17 开始)允许小部件具有按钮等交互式元素
Dart
- Write a static function that takes a Uri as an argument. This will get called when a user clicks on the View
编写一个以 Uri 作为参数的静态函数。当用户单击视图时将调用此函数
- @pragma("vm:entry-point")
- FutureOr<void> backgroundCallback(Uri data) async {
- // do something with data
- ...
- }
复制代码 @pragma('vm:entry-point') must be placed above the callback function to avoid tree shaking in release mode.
- Register the callback function by calling
通过调用注册回调函数
- HomeWidget.registerInteractivityCallback(backgroundCallback);
复制代码 iOS
- Adjust your Podfile to add home_widget as a dependency to your WidgetExtension
调解 Podfile 以将home_widget添加为 WidgetExtension 的依靠项
- target 'YourWidgetExtension' do
- use_frameworks!
- use_modular_headers!
- pod 'home_widget', :path => '.symlinks/plugins/home_widget/ios'
- end
复制代码 - To be able to use plugins with the Background Callback add this to your AppDelegate’s application function
为了可以或许通过后台回调使用插件,请将其添加到您的 AppDelegate 的application函数中
- if #available(iOS 17, *) {
- HomeWidgetBackgroundWorker.setPluginRegistrantCallback { registry in
- GeneratedPluginRegistrant.register(with: registry)
- }
- }
复制代码 - Create a custom AppIntent in your App Target (Runner) and make sure to select both your App and your WidgetExtension in the Target Membership panel
在您的 App Target (Runner) 中创建自定义AppIntent ,并确保在 Target Membership 面板中选择您的 App 和 WidgetExtension
In this Intent you should import home_widget and call HomeWidgetBackgroundWorker.run(url: url, appGroup: appGroup!) in the perform method. url and appGroup can be either hardcoded or set as parameters from the Widget
在此 Intent 中,您应该导入home_widget并在执行方法中调用HomeWidgetBackgroundWorker.run(url: url, appGroup: appGroup!) 。 url和appGroup可以是硬编码的,也可以设置为 Widget 的参数
- import AppIntents
- import Flutter
- import Foundation
- import home_widget
- @available(iOS 16, *)
- public struct BackgroundIntent: AppIntent {
- static public var title: LocalizedStringResource = "HomeWidget Background Intent"
-
- @Parameter(title: "Widget URI")
- var url: URL?
-
- @Parameter(title: "AppGroup")
- var appGroup: String?
-
- public init() {}
-
- public init(url: URL?, appGroup: String?) {
- self.url = url
- self.appGroup = appGroup
- }
-
- public func perform() async throws -> some IntentResult {
- await HomeWidgetBackgroundWorker.run(url: url, appGroup: appGroup!)
-
- return .result()
- }
- }
复制代码 - Add a Button to your Widget. This Button might be encapsulated by a Version check. Pass in an instance of the AppIntent created in the previous step
将按钮添加到您的小部件。该按钮可能由版本查抄封装。传入上一步创建的AppIntent实例
- Button(
- intent: BackgroundIntent(
- url: URL(string: "homeWidgetExample://titleClicked"), appGroup: widgetGroupId)
- ) {
- Text(entry.title).bold().font( /*@START_MENU_TOKEN@*/.title /*@END_MENU_TOKEN@*/)
- }.buttonStyle(.plain)
复制代码 - With the current setup the Widget is now Interactive as long as the App is still in the background. If you want to have the Widget be able to wake the App up you need to add the following to your AppIntent file
在当前设置下,只要应用程序仍在后台,小部件就可以交互。假如您想让 Widget 可以或许唤醒应用程序,您需要将以下内容添加到您的AppIntent文件中
- @available(iOS 16, *)
- @available(iOSApplicationExtension, unavailable)
- extension BackgroundIntent: ForegroundContinuableIntent {}
复制代码 This code tells the system to always perform the Intent in the App and not in a process attached to the Widget. Note however that this will start your Flutter App using the normal main entrypoint meaning your full app might be run in the background. To counter this you should add checks in the very first Widget you build inside runApp to only perform necessary calls/setups while the App is launched in the background
此代码告诉体系始终在应用程序中执行 Intent,而不是在附加到 Widget 的进程中。但请注意,这将使用正常的主入口点启动您的 Flutter 应用程序,这意味着您的完整应用程序可能会在后台运行。为了解决这个问题,您应该在runApp内构建的第一个 Widget 中添加查抄,以便仅在应用程序在后台启动时执行须要的调用/设置
Android Jetpack Glance
- Add the necessary Receiver and Service to your AndroidManifest.xml file
将须要的吸收器和服务添加到您的AndroidManifest.xml文件中- <receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver" android:exported="true">
- <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"/>
复制代码 - Create a custom Action 创建自定义操作
- class InteractiveAction : ActionCallback {
- override suspend fun onAction(context: Context, glanceId: GlanceId, parameters: ActionParameters) {
- val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context, Uri.parse("homeWidgetExample://titleClicked"))
- backgroundIntent.send()
- }
- }
复制代码 - Add the Action as a modifier to a view
将操作作为修改器添加到视图中- Text(
- title,
- style = TextStyle(fontSize = 36.sp, fontWeight = FontWeight.Bold),
- modifier = GlanceModifier.clickable(onClick = actionRunCallback<InteractiveAction>()),
- )
复制代码 Android XML
- Add the necessary Receiver and Service to your AndroidManifest.xml file
将须要的吸收器和服务添加到您的AndroidManifest.xml文件中
- <receiver android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver" android:exported="true">
- <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"/>
复制代码 - Add a HomeWidgetBackgroundIntent.getBroadcast PendingIntent to the View you want to add a click listener to
将HomeWidgetBackgroundIntent.getBroadcast PendingIntent 添加到要添加点击侦听器的视图
- val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(
- context,
- Uri.parse("homeWidgetExample://titleClicked")
- )
- setOnClickPendingIntent(R.id.widget_title, backgroundIntent)
复制代码 Using images of Flutter widgets (使用 Flutter 小组件的图像)
In some cases, you may not want to rewrite UI code in the native frameworks for your widgets.
在某些情况下,您可能不想在小部件的本机框架中重写 UI 代码。
Dart For example, say you have a chart in your Flutter app configured with `CustomPaint`: 例如,假设您的 Flutter 应用程序中有一个配置了“CustomPaint”的图表:- class LineChart extends StatelessWidget {
- const LineChart({
- super.key,
- });
- @override
- Widget build(BuildContext context) {
- return CustomPaint(
- painter: LineChartPainter(),
- child: const SizedBox(
- height: 200,
- width: 200,
- ),
- );
- }
- }
复制代码
Rewriting the code to create this chart on both Android and iOS might be time consuming.
Instead, you can generate a png file of the Flutter widget and save it to a shared container
between your Flutter app and the home screen widget.
重写代码以在 Android 和 iOS 上创建此图表可能非常耗时。相反,您可以生成 Flutter 小部件的 png 文件,并将其保存到 Flutter 应用程序和主屏幕小部件之间的共享容器中。
- var path = await HomeWidget.renderFlutterWidget(
- const LineChart(),
- key: 'lineChart',
- logicalSize: const Size(400, 400),
- );
复制代码
- LineChart() is the widget that will be rendered as an image. (LineChart()是将呈现为图像的小部件。)
- key is the key in the key/value storage on the device that stores the path of the file for easy retrieval on the native side.(key是装备上键/值存储中的键,存储文件的路径,方便本机端检索)
iOS To retrieve the image and display it in a widget, you can use the following SwiftUI code: 要检索图像并将其表现在小部件中,您可以使用以下 SwiftUI 代码:
- In your TimelineEntry struct add a property to retrieve the path:
在您的TimelineEntry布局中添加一个属性来检索路径:
- struct MyEntry: TimelineEntry {
- …
- let lineChartPath: String
- }
复制代码 - Get the path from the UserDefaults in getSnapshot:
从getSnapshot中的UserDefaults获取路径:
- func getSnapshot(
- ...
- let lineChartPath = userDefaults?.string(forKey: "lineChart") ?? "No screenshot available"
复制代码 - Create a View to display the chart and resize the image based on the displaySize of the widget:
创建一个View来表现图表并根据小部件的displaySize调解图像巨细:
- struct WidgetEntryView : View {
- …
- var ChartImage: some View {
- if let uiImage = UIImage(contentsOfFile: entry.lineChartPath) {
- let image = Image(uiImage: uiImage)
- .resizable()
- .frame(width: entry.displaySize.height*0.5, height: entry.displaySize.height*0.5, alignment: .center)
- return AnyView(image)
- }
- print("The image file could not be loaded")
- return AnyView(EmptyView())
- }
- …
- }
复制代码 - Display the chart in the body of the widget’s View:
在小部件的View主体中表现图表:
- VStack {
- Text(entry.title)
- Text(entry.description)
- ChartImage
- }
复制代码 
Android (Jetpack Glance)- // Access data
- val data = currentState.preferences
- // Get Path
- val imagePath = data.getString("lineChart", null)
- // Add Image to Compose Tree
- imagePath?.let {
- val bitmap = BitmapFactory.decodeFile(it)
- Image(androidx.glance.ImageProvider(bitmap), null)
- }
复制代码 Android (XML)
- Add an image UI element to your xml file:
将图像 UI 元素添加到您的 xml 文件中:
- <ImageView
- android:id="@+id/widget_image"
- android:layout_width="200dp"
- android:layout_height="200dp"
- android:layout_below="@+id/headline_description"
- android:layout_alignBottom="@+id/headline_title"
- android:layout_alignParentStart="true"
- android:layout_alignParentLeft="true"
- android:layout_marginStart="8dp"
- android:layout_marginLeft="8dp"
- android:layout_marginTop="6dp"
- android:layout_marginBottom="-134dp"
- android:layout_weight="1"
- android:adjustViewBounds="true"
- android:background="@android:color/white"
- android:scaleType="fitCenter"
- android:src="@android:drawable/star_big_on"
- android:visibility="visible"
- tools:visibility="visible" />
复制代码 - Update your Kotlin code to get the chart image and put it into the widget, if it exists.
更新您的 Kotlin 代码以获取图表图像并将其放入小部件(假如存在)中。
- class NewsWidget : AppWidgetProvider() {
- override fun onUpdate(
- context: Context,
- appWidgetManager: AppWidgetManager,
- appWidgetIds: IntArray,
- ) {
- for (appWidgetId in appWidgetIds) {
- // Get reference to SharedPreferences
- val widgetData = HomeWidgetPlugin.getData(context)
- val views = RemoteViews(context.packageName, R.layout.news_widget).apply {
- // Get chart image and put it in the widget, if it exists
- val imagePath = widgetData.getString("lineChart", null)
- val imageFile = File(imagePath)
- val imageExists = imageFile.exists()
- if (imageExists) {
- val myBitmap: Bitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
- setImageViewBitmap(R.id.widget_image, myBitmap)
- } else {
- println("image not found!, looked @: $imagePath")
- }
- // End new code
- }
- appWidgetManager.updateAppWidget(appWidgetId, views)
- }
- }
- }
复制代码 启动应用程序并检测哪个小部件被点击
To detect if the App has been initially started by clicking the Widget you can call HomeWidget.initiallyLaunchedFromHomeWidget() if the App was already running in the Background you can receive these Events by listening to HomeWidget.widgetClicked. Both methods will provide Uris, so you can easily send back data from the Widget to the App to for example navigate to a content page.
要检测应用程序是否已通过单击小部件初始启动,您可以调用HomeWidget.initiallyLaunchedFromHomeWidget()假如应用程序已经在后台运行,您可以通过监听HomeWidget.widgetClicked来吸收这些变乱。两种方法都会提供 Uris,因此您可以轻松地将数据从 Widget 发送回应用程序,例如导航到内容页面。
In order for these methods to work you need to follow these steps:
为了使这些方法发挥作用,您需要执行以下步调:
iOS Add .widgetUrl to your WidgetComponent
将.widgetUrl添加到您的 WidgetComponent
- Text(entry.message)
- .font(.body)
- .widgetURL(URL(string: "homeWidgetExample://message?message=\(entry.message)&homeWidget"))
复制代码 In order to only detect Widget Links you need to add the queryParameterhomeWidget to the URL
为了仅检测 Widget 链接,您需要将 queryParameter homeWidget添加到 URL
Android Jetpack Glance Add an IntentFilter to the Activity Section in your AndroidManifest
将IntentFilter添加到AndroidManifest的Activity部分
- <intent-filter>
- <action android:name="es.antonborri.home_widget.action.LAUNCH" />
- </intent-filter>
复制代码 Add the following modifier to your Widget (import from HomeWidget)
将以下修改器添加到您的小部件(从 HomeWidget 导入)
- Text(
- message,
- style = TextStyle(fontSize = 18.sp),
- modifier = GlanceModifier.clickable(
- onClick = actionStartActivity<MainActivity>(
- context,
- Uri.parse("homeWidgetExample://message?message=$message")
- )
- )
- )
复制代码 Android XML Add an IntentFilter to the Activity Section in your AndroidManifest
将IntentFilter添加到AndroidManifest的Activity部分
- <intent-filter>
- <action android:name="es.antonborri.home_widget.action.LAUNCH" />
- </intent-filter>
复制代码 In your WidgetProvider add a PendingIntent to your View using HomeWidgetLaunchIntent.getActivity
在你的 WidgetProvider 中使用HomeWidgetLaunchIntent.getActivity添加一个 PendingIntent 到你的视图中
- val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity(
- context,
- MainActivity::class.java,
- Uri.parse("homeWidgetExample://message?message=$message"))
- setOnClickPendingIntent(R.id.widget_message, pendingIntentWithData)
复制代码 后台更新
As the methods of HomeWidget are static it is possible to use HomeWidget in the background to update the Widget even when the App is in the background.
由于 HomeWidget 的方法是静态的,因此即使应用程序在后台,也可以在后台使用 HomeWidget 来更新 Widget。
The example App is using the flutter_workmanager plugin to achieve this.
Please follow the Setup Instructions for flutter_workmanager (or your preferred background code execution plugin). Most notably make sure that Plugins get registered in iOS in order to be able to communicate with the HomeWidget Plugin.
In case of flutter_workmanager this achieved by adding:
示例应用程序使用flutter_workmanager插件来实现此目的。请遵照 flutter_workmanager(或您首选的后台代码执行插件)的设置说明。最值得注意的是,请确保插件在 iOS 中注册,以便可以或许与 HomeWidget 插件举行通讯。对于 flutter_workmanager,可以通过添加以下内容来实现:
- WorkmanagerPlugin.setPluginRegistrantCallback { registry in
- GeneratedPluginRegistrant.register(with: registry)
- }
复制代码 to AppDelegate.swift
###Request Pin Widget
Requests to Pin (Add) the Widget to the users HomeScreen by pinning it to the users HomeScreen.
请求通过将小部件固定到用户主屏幕来将小部件固定(添加)到用户主屏幕。
- HomeWidget.requestPinWidget(
- name: 'HomeWidgetExampleProvider',
- androidName: 'HomeWidgetExampleProvider',
- qualifiedAndroidName: 'com.example.app.HomeWidgetExampleProvider',
- );
复制代码 This method is only supported on Android, API 26+.
If you want to check whether it is supported on current device, use:
此方法仅在Android、API 26+上受支持。假如您想查抄当前装备是否支持它,请使用:
- HomeWidget.isRequestPinWidgetSupported();
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |