Dani
Dani

Reputation: 4187

Spinner for home screen widget

I have a home screen widget for my app. It does the job fine, updating a counter (the default Flutter example), but sometimes, it takes a few seconds to refresh.

I'm trying to display a spinner, blocking the Update Counter button, and remove it when I get the callback, but it doesn't work.

For this, I'm trying this package: https://pub.dev/packages/home_widget

This is what I have so far:

main.dart:

import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart';
import 'package:porftolio_investments/theme/theme.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  HomeWidget.registerInteractivityCallback(backgroundCallback);
  runApp(const MyApp());
}

Future<void> backgroundCallback(Uri? uri) async {
  if (uri?.host == 'updatecounter') {
    int counter = 0;
    await HomeWidget.getWidgetData('_counter', defaultValue: 0).then((value) {
      counter = value!;
      counter++;
    });

    await HomeWidget.saveWidgetData('_counter', counter);

    await HomeWidget.updateWidget(
      name: 'HomeScreenWidgetProvider',
      iOSName: 'HomeScreenWidgetProvider',
    );
  }
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Porfolio Investments',
      theme: darkMode,
      // home: const LandingPage(),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  @override
  void initState() {
    super.initState();
    HomeWidget.widgetClicked.listen((Uri? uri) => loadData());
    loadData();
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
    updateAppWidget();
  }

  void loadData() async {
    await HomeWidget.getWidgetData('_counter', defaultValue: 0).then((value) {
      setState(() {
        _counter = value!;
      });
    });
  }

  Future<void> updateAppWidget() async {
    await HomeWidget.saveWidgetData('_counter', _counter);
    await HomeWidget.updateWidget(
      name: 'HomeScreenWidgetProvider',
      iOSName: 'HomeScreenWidgetProvider',
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            )
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

widget_layout.xml:

<FrameLayout
    android:id="@+id/widget_root"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="180dp"
    android:layout_height="110dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#1f303d">

        <TextView
            android:id="@+id/tv_counter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            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:layout_alignParentBottom="true"
            android:text="Update Counter"
            android:textColor="@android:color/holo_blue_dark"
            android:textSize="12sp" />
    </RelativeLayout>
</FrameLayout>

widget_info.xml:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/widget_layout"
    android:minWidth="150dp"
    android:minHeight="200dp"
    android:minResizeWidth="200dp"
    android:minResizeHeight="150dp"
    android:widgetCategory="home_screen" />

WidgetProvider.kt:

class HomeScreenWidgetProvider : 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)

                var counterText = "Your counter value is: $counter"

                if (counter == 0) {
                    counterText = "You have not pressed the counter button"
                }

                setTextViewText(R.id.tv_counter, counterText)

                // 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)
        }
    }
}

AndroidManifest.xml:

<receiver 
            android:name="HomeScreenWidgetProvider" 
            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/widget_info" />
        </receiver>

        <!-- home screen widget -->
        <!-- HomeWidget background receiver -->
        <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>

        <!-- HomeWidget background service -->
        <service
            android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="true" />

Upvotes: 0

Views: 34

Answers (0)

Related Questions