launcher_helper 0.4.6+hotfix.1 copy "launcher_helper: ^0.4.6+hotfix.1" to clipboard
launcher_helper: ^0.4.6+hotfix.1 copied to clipboard

To help create an android launcher this plugin provides wallpaper, installed package details, etc in an easy way.

example/lib/main.dart

import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:launcher_helper/launcher_helper.dart';
import 'package:provider/provider.dart';

import 'utils/permission_handling.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Requesting runtime permissions
    HandlerOfPermissions().askOnce();
    // Providers to handle data across the app
    return MultiProvider(
      providers: [
        // This handles data for a wallpaper
        ChangeNotifierProvider<WallpaperPageModel>(
          create: (context) => WallpaperPageModel(),
        ),
        // This handles data regarding installed applications
        ChangeNotifierProvider<ApplicationPageModel>(
          create: (context) => ApplicationPageModel(),
        ),
      ],
      child: MaterialApp(
        title: 'Red',
        themeMode: ThemeMode.system,
        theme: ThemeData(primaryColor: Colors.blue),
        home: Showcase(),
      ),
    );
  }
}

/// The showcase to present example usage of some methods in the library
class Showcase extends StatefulWidget {
  @override
  _ShowcaseState createState() => _ShowcaseState();
}

class _ShowcaseState extends State<Showcase> {
  @override
  Widget build(BuildContext context) {
    Widget wallpaperPageButton = ShowcaseButton(
      title: "Wallpaper",
      onPressed: () {
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) => WallpaperPage(),
          ),
        );
      },
    );
    Widget applicationsPageButton = ShowcaseButton(
      title: "Applications",
      onPressed: () {
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) => ApplicationsPage(),
          ),
        );
      },
    );
    return Scaffold(
      body: ListView(
        children: [
          wallpaperPageButton,
          applicationsPageButton,
        ],
      ),
    );
  }
}

class WallpaperPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        actions: <Widget>[
          FlatButton(
            onPressed: () {
              // Refreshes to check if wallpaper has been changed
              Provider.of<WallpaperPageModel>(context, listen: false).refresh();
            },
            child: Text('Refresh wallpaper'),
          ),
        ],
      ),
      body: Consumer<WallpaperPageModel>(
        builder: (context, model, _) {
          return Center(
            child: ListView(
              shrinkWrap: true,
              children: <Widget>[
                // Shows wallpaper if available. Else shows a progress indicator
                model.hasWallpaper
                    ? model.wallpaper
                    : CircularProgressIndicator(),
              ],
            ),
          );
        },
      ),
    );
  }
}

class ApplicationsPage extends StatelessWidget {
  // a callback which is ran after the frame callback.
  void initPostFrame(BuildContext context) async {
    WidgetsBinding.instance.addPostFrameCallback(
      (_) => Provider.of<ApplicationPageModel>(context, listen: false).init(),
    );
  }

  @override
  Widget build(BuildContext context) {
    initPostFrame(context);
    return Scaffold(
      appBar: AppBar(
          title: Text(
            // Number of installed applications which can be launched
            Provider.of<ApplicationPageModel>(context).count.toString(),
          ),
          actions: [
            FlatButton(
              onPressed: () {
                // Updates the application collection
                Provider.of<ApplicationPageModel>(context, listen: false)
                    .refresh();
              },
              child: Text('Refresh'),
            ),
          ]),
      body: Consumer<ApplicationPageModel>(
        builder: (context, model, _) {
          if (model.count == 0) {
            return Center(
              // displays a progress indicator if the list is empty
              child: CircularProgressIndicator(),
            );
          }
          return AppIconShape(
            // Here the model provides the shape which will be used by AppIconShape consumers
            data: model.iconShape,
            child: ListView.builder(
              itemCount: model.count,
              itemBuilder: (context, index) {
                // An Application on this collection at index location
                Application app = model.apps[index];
                // Other information of the app
                String subtitle =
                    '${app.packageName}\n${app.versionName}.${app.versionCode}';
                return ListTile(
                  // package name is unique hence can be used in key creation
                  key: new ObjectKey(app.packageName),
                  onTap: () {
                    // Open Icon's shape customizer page
                    Navigator.of(context).push(
                      MaterialPageRoute(
                        builder: (context) => ShapeCustomizerPage(app),
                      ),
                    );
                  },
                  // the icon of this app
                  leading: app.icon,
                  // the label of this app
                  title: Text(app.label),
                  subtitle: Text(subtitle),
                );
              },
            ),
          );
        },
      ),
    );
  }
}

class ShapeCustomizerPage extends StatelessWidget {
  final Application app;
  const ShapeCustomizerPage(
    this.app, {
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer<ApplicationPageModel>(
      builder: (context, model, _) {
        return Scaffold(
          backgroundColor: Colors.grey[400],
          appBar: AppBar(
            title: Row(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Text(app.label),
                SizedBox(
                  width: 5,
                ),
                // Shows a red warning if the icon is not adaptable
                app.isAdaptableIcon
                    ? SizedBox()
                    : Container(
                        color: Colors.red,
                        child: Text(
                          'Not adaptable',
                          style: TextStyle(
                            color: Colors.white,
                            fontSize: 11,
                          ),
                        ),
                      )
              ],
            ),
          ),
          body: AppIconShape(
            data: model.iconShape,
            child: ListView(
              children: <Widget>[
                Row(
                  mainAxisSize: MainAxisSize.min,
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: app
                          .icon, // this icon will be affected by the modifications
                    ),
                  ],
                ),
                Divider(),
                Padding(
                  padding: const EdgeInsets.only(left: 15, right: 15),
                  child: FlatButton(
                    color: Colors.cyan,
                    child: Text(
                      'Open',
                    ),
                    onPressed: () {
                      app.launch(); // launches the app
                    },
                  ),
                ),
                Heading('Change Icon shape'),
                SizedBox(height: 10),
                // below buttons allow the shape to be changed with some predefined data
                OutlineButton(
                  child: Text('Circular'),
                  onPressed: () {
                    // This constructor creates shape data of a circular icon
                    model.setIconShape(AppIconShapeData.circular());
                  },
                ),
                OutlineButton(
                  child: Text('Square'),
                  onPressed: () {
                    model.setIconShape(AppIconShapeData.square());
                  },
                ),
                OutlineButton(
                  child: Text('Squircle'),
                  onPressed: () {
                    model.setIconShape(AppIconShapeData.squircle());
                  },
                ),
                OutlineButton(
                  child: Text('Teardrop'),
                  onPressed: () {
                    model.setIconShape(AppIconShapeData.teardrop());
                  },
                ),
                Divider(),
                // Below option changes icon size i.e radius
                Heading('Change Icon radius ${model.iconShape.radius}'),
                SizedBox(height: 5),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Slider(
                    // This slider controls the radius of icons
                    value: model.iconShape.radius,
                    min: 20,
                    max: 100,
                    onChanged: (double value) {
                      AppIconShape.of(context).copyWith(
                        radius: value,
                      );
                      model.setIconShape(
                        AppIconShape.of(context).copyWith(
                          radius: value,
                        ),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

class Heading extends StatelessWidget {
  final String text;

  const Heading(
    this.text, {
    Key key,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(5.0),
      child: Text(
        text,
        style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
      ),
    );
  }
}

class ShowcaseButton extends StatelessWidget {
  final String title;
  final void Function() onPressed;
  final EdgeInsetsGeometry margin;
  const ShowcaseButton({Key key, this.title, this.onPressed, this.margin})
      : assert(title != null),
        super(key: key);
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: margin ?? EdgeInsets.all(12),
      child: OutlineButton(
        child: Text(title ?? ''),
        onPressed: onPressed,
      ),
    );
  }
}

class WallpaperPageModel extends ChangeNotifier {
  Uint8List _wallpaperData;
  Image wallpaper;
  bool _hasWallpaper = false;
  bool get hasWallpaper => _hasWallpaper;

  WallpaperPageModel() {
    init();
  }

  // Asynchronously sets wallpaper. Used only once or in the constructor.
  init() async {
    // Retrieves the wallpaper
    _wallpaperData = await LauncherHelper.getWallpaper;
    wallpaper = Image.memory(_wallpaperData);
    _hasWallpaper = true;
    notifyListeners();
  }

  // Updates wallpaper if changed
  Future<void> refresh() async {
    // Fresh copy of wallpaper is obtained
    var sub = await LauncherHelper.getWallpaper;
    // The new and existing wallpaper is compared
    if (sub.length == _wallpaperData.length) {
      bool same = true;
      for (var i = 0; i < sub.length; i++) {
        // Comparing bytes at same index of both new and old wallpaper
        same = (sub[i] == _wallpaperData[i]);
        if (!same) break;
      }

      if (same) {
        // the wallpaper is same as before, hence no changes shall be made/notified
        return;
      }
    }
    // The new wallpaper is different
    // Making changes in the app to display new wallpaper
    _wallpaperData = sub;
    wallpaper = Image.memory(_wallpaperData);
    notifyListeners();
  }
}

class ApplicationPageModel extends ChangeNotifier {
  ApplicationCollection _applicationCollection;
  ApplicationCollection get apps => _applicationCollection;
  bool _hasApplications = false;
  int get count => apps?.length ?? 0;
  bool get hasApplications => _hasApplications;
  AppIconShapeData _iconShape = AppIconShapeData.circular();

  // Describes an icon's shape.
  // This will be passed to AppIconShape's data.
  AppIconShapeData get iconShape => _iconShape;

  // Setting icon shape through this method.
  void setIconShape(AppIconShapeData iconShape) {
    _iconShape = iconShape;
    notifyListeners();
  }

  ApplicationPageModel();

  // Asynchronously fetches all applications. Used only once as this is an expensive operation.
  init() async {
    if (hasApplications) return;
    // Retrievig applications
    _applicationCollection = await LauncherHelper.getApplications();
    _hasApplications = true;
    notifyListeners();
  }

  // Updating changes in the applications
  Future<void> refresh() async {
    // updates application without much performance issues.
    await _applicationCollection.update();
    notifyListeners();
  }
}
7
likes
40
pub points
0%
popularity

Publisher

verified publishermagnificsoftware.com

To help create an android launcher this plugin provides wallpaper, installed package details, etc in an easy way.

Repository (GitHub)
View/report issues

License

MIT (LICENSE)

Dependencies

flutter, palette_generator, provider

More

Packages that depend on launcher_helper