如何在 android:updatePeriodMillis="0" 时从 Flutter 更新 Android 小部件?

Posted

技术标签:

【中文标题】如何在 android:updatePeriodMillis="0" 时从 Flutter 更新 Android 小部件?【英文标题】:How can I update an Android widget from Flutter while android:updatePeriodMillis="0"? 【发布时间】:2021-04-28 15:09:48 【问题描述】:

我是新来的。我正在慢慢掌握 Flutter,但在 Kotlin/Java 集成方面完全是新手。我正在尝试制作一个 Flutter 应用程序,其中一些数据在 Flutter istelf 内不定期更新,然后显示在主屏幕小部件上。

我不想定期更新 android 小部件,因为每天可能不会有任何更改,只是偶尔更改。在寻找实际制作小部件的方法时,我发现了这个really helpful answer from bnxm 和一个很好的implementation on Github from timobaehr。

以这个为例,如果我想在应用程序中的按钮被按下(或后台服务运行)时更新主屏幕小部件上显示的“结果”,而不是在一组间隔? Timobaehr 在他的演示中使用了默认的 Flutter 计数应用程序,那么我可以如何处理按下按钮时运行的这段代码?

这里是main.dart中的更新函数:

void onWidgetUpdate() 
  WidgetsFlutterBinding.ensureInitialized();

  const MethodChannel channel = MethodChannel('com.example.app/widget');

  channel.setMethodCallHandler(
    (call) async 
      final id = call.arguments;

      print('on Dart $call.method!');

      return 
        'id': id,
        // Some data of type int - this is what I want to update
        'value': counter,
      ;
    ,
  );

下面是代码中值被更新的地方,基于默认的 Flutter 启动应用程序。我还把 int counter = 0; 移到了 dart 文件的顶部,这样它就可以在任何地方使用。

void _incrementCounter() 
    setState(() 
      
      counter++;
      
    );

// How can I update the home screen widget from here?
// For example, send the new value of 'counter' to 'value' in the update function
// so that the new value is displayed on the home screen widget

  

是否像在此处添加内容一样简单,还是需要在其他地方更改 Kotlin 代码?感谢您的帮助。

编辑:我应该说,从增量函数调用 onWidgetUpdate() 根本不会改变小部件,所以我认为肯定有其他事情需要发生,可能在后台 Kotlin 代码或使用 MethodChannels,我不熟悉。

如果你想自己运行它来测试,我从timobaehr's Github project 克隆,只是将“值”更改为来自“计数器”并且是一个 int 而不是 double。

【问题讨论】:

【参考方案1】:

好吧,我想我明白了。把它贴在这里以防它帮助其他人。

正如我所怀疑的那样,在 Kotlin 中必须进行更改。所以对我来说有点额外的学习!如果您关注timobaehr's project on Github,您可以尝试进行如下更改:

我写了一个名为“updateFromFlutter”的新方法并将其添加到 MainActivity.kt:

when (call.method) 
            "initialize" -> 
                if (call.arguments == null) return
                WidgetHelper.setHandle(this, call.arguments as Long)
            
            "updateFromFlutter" -> 
                val views = RemoteViews(context.packageName, R.layout.widget_layout).apply 
                    setTextViewText(R.id.text, call.argument("text"))
                

                val id: Int = call.argument("id")!!

                val manager = AppWidgetManager.getInstance(this)
                manager.updateAppWidget(id, views)
            
        

记得在 MainActivity.kt 的顶部导入这些:

import android.widget.RemoteViews
import com.example.flutter_app_android_widget.R
import android.appwidget.AppWidgetManager

并在更新计数器值后从 main.dart 调用它:

const MethodChannel platform = MethodChannel('com.example.flutter_app_android_widget/widget');
platform.invokeMethod("updateFromFlutter", 
    "text": counter.toString(),
    "id": //get the integer from Shared Preferences - up to you how you do this
          //or feel free to suggest a better way of keeping track of the widget id
  );

然后,您应该能够通过按下 Flutter 应用中的按钮按需更新主屏幕小部件。

【讨论】:

以上是关于如何在 android:updatePeriodMillis="0" 时从 Flutter 更新 Android 小部件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在表单提交后保留文本(如何在提交后不删除自身?)

如何在异步任务中调用意图?或者如何在 onPostExecute 中开始新的活动?

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何在 JDBC 中启动事务?

如何在 Fragment 中调用 OnActivityResult 以及它是如何工作的?

如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?