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),
      ),
    );
  }
}
6
likes
150
points
59
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)

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