dynamic_icon_changer 0.0.1 copy "dynamic_icon_changer: ^0.0.1" to clipboard
dynamic_icon_changer: ^0.0.1 copied to clipboard

A Flutter plugin for dynamically changing app icons on Android and iOS based on schedules or events. Includes automatic festival handling and Android relaunch support.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:dynamic_icon_changer/dynamic_icon_changer.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dynamic Icon Changer Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Dynamic Icon Changer'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  final _iconChanger = DynamicIconChanger();
  String? _currentIcon = 'Default';
  bool _supportsAlternateIcons = false;
  final bool _relaunchAndroid = false;

  final List<String> _androidAliases = [
    '.MainActivityDefault',
    '.MainActivityChristmas',
    '.MainActivitySales',
  ];

  @override
  void initState() {
    super.initState();
    _checkStatus();
  }

  Future<void> _checkStatus() async {
    final supports = await _iconChanger.supportsAlternateIcons();
    final current = await _iconChanger.getIcon();
    setState(() {
      _supportsAlternateIcons = supports;
      _currentIcon = current ?? 'Default';
    });
  }

  Future<void> _changeIcon(String? iconName) async {
    try {
      await _iconChanger.setIcon(
        iconName,
        androidActiveAliases: _androidAliases,
        relaunch: _relaunchAndroid,
      );
      await _checkStatus();
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Icon change request sent for ${iconName ?? "Default"}')),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('Error: $e')),
        );
      }
    }
  }

  void _handleAutomaticChange() {
    final now = DateTime.now();
    _iconChanger.handleAutomaticIconChange(
      festivals: {
        'christmas': [ // Match the case used in setIcon/manifest
          DateTimeRange(
            start: DateTime(now.year, 12, 1),
            end: DateTime(now.year, 12, 31),
          ),
        ],
        'sales': [
          DateTimeRange(
            start: DateTime(now.year, 1, 1),
            end: DateTime(now.year, 1, 31),
          ),
        ],
      },
      defaultIcon: 'Default',
      androidActiveAliases: _androidAliases,
      relaunch: _relaunchAndroid,
    );
    _checkStatus();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const SizedBox(height: 20),
              Text(
                'Supports Alternate Icons: $_supportsAlternateIcons',
                style: Theme.of(context).textTheme.titleMedium,
              ),
              const SizedBox(height: 12),
              Text(
                'Current Icon: $_currentIcon',
                style: Theme.of(context).textTheme.titleMedium,
              ),
              const SizedBox(height: 24),
              
              const Divider(),

              const SizedBox(height: 8),
              Wrap(
                spacing: 8,
                children: [
                  ElevatedButton(
                    onPressed: () => _changeIcon(null),
                    child: const Text('Default'),
                  ),
                  ElevatedButton(
                    onPressed: () => _changeIcon('christmas'),
                    child: const Text('Christmas'),
                  ),
                  ElevatedButton(
                    onPressed: () => _changeIcon('sales'),
                    child: const Text('Sales'),
                  ),
                ],
              ),
              const SizedBox(height: 32),
              ElevatedButton.icon(
                onPressed: _handleAutomaticChange,
                icon: const Icon(Icons.auto_awesome),
                label: const Text('Run Automatic Check'),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.amber.shade100,
                ),
              ),
              const Padding(
                padding: EdgeInsets.all(24.0),
                child: Text(
                  'Note: On Android, changing icons often closes the app to refresh the launcher. '
                  'Enable "Android Relaunch" to automatically reopen it.\n\n'
                  'On iOS, the system allows icon changes but may throttle them if called too frequently.',
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 12, color: Colors.grey),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _checkStatus,
        tooltip: 'Refresh Status',
        child: const Icon(Icons.refresh),
      ),
    );
  }
}
11
likes
160
points
64
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for dynamically changing app icons on Android and iOS based on schedules or events. Includes automatic festival handling and Android relaunch support.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on dynamic_icon_changer

Packages that implement dynamic_icon_changer