Awesome SMS library for Flutter App, flutter_sms

xxhdpi

Flutter SMS

This is an SMS library for flutter.

It only support Android for now (I can’t do it for iOS because I don’t own Mac).

The flutter_sms library is now unmaintained, use at your own risk.

Getting Started

For help getting started with Flutter, view our online documentation.

For help on editing plugin code, view the documentation.

Installation and Usage

Once you’re familiar with Flutter you may install this package adding sms (0.1.4 or higher) to the dependencies list of the pubspec.yaml file as follow:

dependencies:
  flutter:
    sdk: flutter

  sms: ^0.2.0

Then run the command flutter packages get on the console.

Querying SMS messages

Add the import statement for sms and create an instance of the SmsQuery class:

import 'package:sms/sms.dart';

void main() {
  SmsQuery query = new SmsQuery();
}

Getting all SMS messages

List<SmsMessage> messages = await query.getAllSms;

Notethe use of await keyword means that getAllSms is resolved asynchronously and a Future is retorned.

Filtering SMS messages

The method querySms from the SmsQuery class returns a list of sms depending of the supplied parameters. For example, for querying all the sms messages sent and received write the followed code:

await query.querySms({
    kinds: [SmsQueryKind.Inbox, SmsQueryKind.Sent]
});

You can also query all the sms messages sent and received from a specific contact:

await query.querySms({
    address: getContactAddress()
});

Getting all Threads Conversations

With SmsQuery you can also get the entire list of conversations:

List<SmsThread> threads = await query.getAllThreads;

Getting the Contact info

Each conversation thread is related with a Contact. The class Contact contains all the info of a thread contact (address, photo, full name). To get access to Contact class you must import 'package:sms/contact.dart' into your dart file:

import 'package:sms/contact.dart';

void main() {
  ...
  Contact contact = threads.first.contact;
  print(contact.address);
}

Querying Contact

You can also query a contact by its address (phone number):

import 'package:sms/contact.dart';

void main() {
  ContactQuery contacts = new ContactQuery();
  Contact contact = await contacts.queryContact(someAddress());
  print(contact.fullName);
}
String getAddress() {...}

The Contact photo

You can retrieve the photo of the contact (full size or thumbnail):

...
Uint8List fullSize = contact.photo.bytes;
Uint8List thumbnail = contact.thumbnail.bytes;

User Profile

Some times it is useful to request basic info of the phone owner, like the contact photo, addresses, etc.

import 'package:sms/contact.dart';

UserProfileProvider provider = new UserProfileProvider();
UserProfile profile = await provider.getUserProfile();
print(profile.fullName);

Sending SMS

What about sending a SMS? All you have to do is to create an instance of the SmsSender class:

import 'package:sms/sms.dart';

void main() {
  SmsSender sender = new SmsSender();
  String address = someAddress();
  ...
  sender.sendSms(new SmsMessage(address, 'Hello flutter!'));
}

To be notified when the message is sent and/or delivered, you must add a listener to your message:

import 'package:sms/sms.dart';

void main() {
  SmsSender sender = new SmsSender();
  String address = someAddress();
  ...
  SmsMessage message = new SmsMessage(address, 'Hello flutter!');
  message.onStateChanged.listen((state) {
    if (state == SmsMessageState.Sent) {
      print("SMS is sent!");
    } else if (state == SmsMessageState.Delivered) {
      print("SMS is delivered!");
    }
  });
  sender.sendSms(message);
}

Some times it is useful to be notified of delivered messages regardless of the message. To do that you must subscribe to the onSmsDelivered of the SmsSender class instance:

void main() {
...
SmsSender sender = new SmsSender();
sender.onSmsDelivered.listen((SmsMessage message){
  print('${message.address} received your message.');
}));
}

You can also send with another SimCard:

void main() {
SimCardsProvider provider = new SimCardsProvider();
SimCard card = await provider.getSimCards()[0];
SmsSender sender = new SmsSender();
SmsMessage message = new SmsMessage("address", "message");
sender.sendSMS(message, simCard: card);
}

Note: Using the onSmsDelivered from the SmsSender will only notify to listeners of messages that has been sent through SmsSender.send().

Receiving SMS

If you want to be notified for incoming new messages you must subscribe to an instance of the SmsReceiver class:

import 'package:sms/sms.dart';

void main() {
  SmsReceiver receiver = new SmsReceiver();
  receiver.onSmsReceived.listen((SmsMessage msg) => print(msg.body));
}

Example

  • Create a flutter app, using flutter command: flutter create app SMS. Here SMS being the name of the app.
  • In the lib folder is where we store all our .dart codes.
  • Create files app.dart and main.dart.
  • Create conversation, conversations, sim, utils folders in lib itself.
  • Create files inside the above folders as given below:
  • app.dart
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'sim/sim_bloc.dart';
import 'sim/sim_bloc_provider.dart';
import './conversations/threads.dart';

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    final bloc = new SimCardsBloc();
    bloc.loadSimCards();

    return new SimCardsBlocProvider(
      simCardBloc: bloc,
      child: new MaterialApp(
        title: 'Flutter SMS',
        home: new Threads(),
      ),
    );
  }
}
  • main.dart
import 'package:flutter/widgets.dart';
import './app.dart';

void main() => runApp(new App());
  • Inside the conversation folder create the given files.dart and paste the given code:

  • conversation / arrow_painter.dart
import 'package:flutter/rendering.dart';

enum ArrowDirection { Left, Right }

class ArrowPainter extends CustomPainter {
  final Color color;
  final ArrowDirection direction;
  final _paint = new Paint();

  ArrowPainter({this.color, this.direction}) {
    _paint.color = this.color;
  }

  @override
  void paint(Canvas canvas, Size size) {
    canvas.save();
    Path path = new Path();

    if (this.direction == ArrowDirection.Left) {
      canvas.translate(56.0, 0.0);
      path.lineTo(-15.0, 0.0);
    } else {
      canvas.translate(size.width - 56.0, 0.0);
      path.lineTo(15.0, 0.0);
    }

    path.lineTo(0.0, 20.0);
    path.lineTo(0.0, 0.0);
    canvas.drawPath(path, _paint);

    canvas.restore();
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}
  • conversation / conversation.dart
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

import '../utils/colors.dart';
import 'conversationStore.dart';
import 'formSend.dart';
import 'messages.dart';

class Conversation extends StatefulWidget {
  Conversation(this.thread, this.userProfile) : super();

  final SmsThread thread;
  final UserProfile userProfile;

  @override
  State<Conversation> createState() => new _ConversationState();
}

class _ConversationState extends State<Conversation> {
  final SmsReceiver _receiver = new SmsReceiver();

  @override
  void initState() {
    _receiver.onSmsReceived.listen((sms) {
      setState(() {});
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print('building conversation');
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(
            widget.thread.contact.fullName ?? widget.thread.contact.address),
        backgroundColor: ContactColor.getColor(widget.thread.contact.fullName),
      ),
      body: new Column(
        children: <Widget>[
          new Expanded(
            child: new ConversationStore(
              widget.userProfile,
              widget.thread,
              child: new Messages(widget.thread.messages),
            ),
          ),
          new FormSend(
            widget.thread,
            onMessageSent: _onMessageSent,
          ),
        ],
      ),
    );
  }

  void _onMessageSent(SmsMessage message) {
    setState(() {
      widget.thread.addNewMessage(message);
    });
  }
}
  • conversation / conversationStore.dart
import 'package:flutter/widgets.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

class ConversationStore extends InheritedWidget {
  const ConversationStore(this.userProfile, this.thread, {Widget child})
      : super(child: child);

  final UserProfile userProfile;
  final SmsThread thread;

  static ConversationStore of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(ConversationStore)
        as ConversationStore;
  }

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) {
    return true;
  }
}
  • conversation / formSend.dart
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';
import '../sim/sim_bloc_provider.dart';

typedef void MessageSentCallback(SmsMessage message);

class FormSend extends StatelessWidget {
  FormSend(this.thread, {this.onMessageSent});

  final SmsThread thread;
  final MessageSentCallback onMessageSent;
  final TextEditingController _textField = new TextEditingController();
  final SmsSender _sender = new SmsSender();

  @override
  Widget build(BuildContext context) {
    final simCards = SimCardsBlocProvider.of(context);
    return new Material(
      elevation: 4.0,
      child: new Row(
        children: [
          new Expanded(
            child: new Container(
              child: new TextField(
                controller: _textField,
                decoration: new InputDecoration(
                  border: InputBorder.none,
                  labelStyle: new TextStyle(fontSize: 16.0),
                  hintText: "Send message:",
                ),
              ),
              padding: new EdgeInsets.only(left: 20.0, top: 8.0, bottom: 8.0),
            ),
          ),
          new IconButton(
              icon: new StreamBuilder<SimCard>(
                  stream: simCards.onSimCardChanged,
                  initialData: simCards.selectedSimCard,
                  builder: (context, snapshot) {
                    return new Row(
                      children: [
                        new Icon(
                          Icons.sim_card,
                          color: snapshot.data.state == SimCardState.Ready
                              ? Colors.blue
                              : Colors.grey
                        ),
                        new Text(snapshot.data.slot.toString(),
                          style: new TextStyle(color: snapshot.data.state == SimCardState.Ready
                              ? Colors.black
                              : Colors.grey
                          ),
                        ),
                      ],
                    );
                  }),
              onPressed: () {
                SimCardsBlocProvider.of(context).toggleSelectedSim();
              }),
          new IconButton(
            icon: new Icon(Icons.send),
            onPressed: () {
              _sendMessage(context);
            },
            color: Colors.blue,
          ),
        ],
      ),
    );
  }

  void _sendMessage(BuildContext context) async {
    SmsMessage message =
        new SmsMessage(thread.address, _textField.text, threadId: thread.id);
    message.onStateChanged.listen((SmsMessageState state) {
      if (state == SmsMessageState.Delivered) {
        print('Message delivered to ${message.address}');
        _notifyDelivery(message, context);
      }
      if (state == SmsMessageState.Sent) {
        print('Message sent to ${message.address}');
      }
    });

    final simCard = SimCardsBlocProvider.of(context).selectedSimCard;
    await _sender.sendSms(message, simCard: simCard);
    _textField.clear();
    onMessageSent(message);
  }

  void _notifyDelivery(SmsMessage message, BuildContext context) async {
    final contacts = new ContactQuery();
    Contact contact = await contacts.queryContact(message.address);
    final snackBar = new SnackBar(
        content: new Text('Message to ${contact.fullName} delivered'));
    Scaffold.of(context).showSnackBar(snackBar);
  }
}
  • conversation / message.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

import '../conversations/avatar.dart';
import 'arrow_painter.dart';

abstract class Message extends StatelessWidget {
  Message(this.message,
      {this.compactMode = false, this.backgroundColor, this.arrowDirection})
      : super();

  final SmsMessage message;
  final bool compactMode;
  final Color backgroundColor;
  final ArrowDirection arrowDirection;

  bool get sent =>
      message.kind == SmsMessageKind.Sent ||
      message.state == SmsMessageState.Sent ||
      message.state == SmsMessageState.Sending ||
      message.state == SmsMessageState.Delivered;

  get time {
    return new TimeOfDay(hour: message.date.hour, minute: message.date.minute);
  }

  createAvatar(Photo thumbnail, String alternativeText) {
    if (compactMode) {
      return new Container(width: 40.0);
    }

    return new Avatar(thumbnail, alternativeText);
  }

  createArrow() {
    if (compactMode) {
      return new Container();
    }

    return new CustomPaint(
      painter: new ArrowPainter(
          color: this.backgroundColor, direction: this.arrowDirection),
    );
  }
}
  • conversation / messageGroup.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/sms.dart';

import '../utils/group.dart';
import 'conversationStore.dart';
import 'received_message.dart';
import 'sent_message.dart';

class MessageGroup extends StatelessWidget {
  final Group group;

  MessageGroup(this.group) : super();

  @override
  Widget build(BuildContext context) {
    final userProfile = ConversationStore.of(context).userProfile;
    final thread = ConversationStore.of(context).thread;

    List<Widget> widgets = <Widget>[
      new Container(
        child: new Text(_formatDatetime(group.messages[0], context)),
        margin: new EdgeInsets.only(top: 25.0),
      )
    ];

    for (int i = 0; i < group.messages.length; i++) {
      if (group.messages[i].kind == SmsMessageKind.Sent) {
        widgets.add(
            new SentMessage(group.messages[i], _isCompactMode(i), userProfile));
      } else {
        widgets.add(new ReceivedMessage(
            group.messages[i], _isCompactMode(i), thread.contact));
      }
    }

    return new Padding(
      padding: const EdgeInsets.only(bottom: 10.0),
      child: new Container(
        child: new Column(
          children: widgets,
        ),
      ),
    );
  }

  String _formatDatetime(SmsMessage message, BuildContext context) {
    return MaterialLocalizations.of(context).formatFullDate(message.date);
  }

  bool _isCompactMode(int i) {
    return i > 0 && group.messages[i].kind == group.messages[i - 1].kind;
  }
}
  • conversation / messages.dart
import 'package:flutter/material.dart';
import 'package:sms/sms.dart';

import '../utils/group.dart';
import 'messageGroup.dart';

class Messages extends StatelessWidget {
  final List<SmsMessage> messages;

  Messages(this.messages);

  @override
  Widget build(BuildContext context) {
    final groups = MessageGroupService.of(context).groupByDate(messages);
    return new ListView.builder(
        reverse: true,
        itemCount: groups.length,
        itemBuilder: (context, index) {
          return new MessageGroup(groups[index]);
        });
  }
}
  • conversation / received_message.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

import 'arrow_painter.dart';
import 'message.dart';

class ReceivedMessage extends Message {
  ReceivedMessage(SmsMessage message, bool compactMode, this.contact)
      : super(message,
            compactMode: compactMode,
            backgroundColor: Colors.grey[300],
            arrowDirection: ArrowDirection.Left);

  final Contact contact;

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Stack(
        children: [
          new Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              new Container(
                child: createAvatar(contact.thumbnail, contact.fullName),
                margin: new EdgeInsets.only(right: 8.0, top: 8.0),
              ),
              new Expanded(
                child: new Container(
                  decoration: new BoxDecoration(
                    borderRadius: new BorderRadius.circular(10.0),
                    color: this.backgroundColor
                  ),
                  child: new Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      new Text(message.body.trim()),
                      new Align(
                        child: new Padding(
                          padding: new EdgeInsets.only(top: 5.0),
                          child: new Text(
                            time.format(context),
                            style: new TextStyle(color: Colors.grey),
                          ),
                        ),
                        alignment: Alignment.centerLeft,
                      ),
                    ],
                  ),
                  margin: new EdgeInsets.only(right: 48.0),
                  padding: new EdgeInsets.all(10.0),
                ),
              ),
            ],
          ),
          this.createArrow()
        ],
      ),
      margin: new EdgeInsets.only(
          top: compactMode ? 2.0 : 10.0, bottom: 0.0, left: 15.0, right: 15.0),
    );
  }
}
  • conversation / sent_message.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';
import 'arrow_painter.dart';
import 'message.dart';

class SentMessage extends Message {
  SentMessage(SmsMessage message, bool compactMode, this.userProfile)
      : super(message,
            compactMode: compactMode,
            backgroundColor: Colors.lightBlue[100],
            arrowDirection: ArrowDirection.Right);

  final UserProfile userProfile;

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Stack(
        children: [
          new Row(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              new Expanded(
                child: new Container(
                  child: new Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: <Widget>[
                      new Text(message.body.trim()),
                      new Align(
                        child: new Padding(
                          padding: new EdgeInsets.only(top: 5.0),
                          child: new Text(
                            time.format(context),
                            style: new TextStyle(color: Colors.grey[500]),
                          ),
                        ),
                        alignment: Alignment.centerRight,
                      ),
                    ],
                  ),
                  margin: new EdgeInsets.only(left: 48.0),
                  padding: new EdgeInsets.all(10.0),
                  decoration: new BoxDecoration(
                    borderRadius: new BorderRadius.circular(10.0),
                    color: this.backgroundColor
                  ),
                ),
              ),
              new Container(
                child:
                    createAvatar(userProfile.thumbnail, userProfile.fullName),
                margin: new EdgeInsets.only(left: 8.0, top: 8.0),
              ),
            ],
          ),
          new Container(
            width: double.infinity,
            child: createArrow(),
          ),
        ],
      ),
      margin: new EdgeInsets.only(
          top: compactMode ? 2.0 : 10.0, bottom: 0.0, left: 15.0, right: 15.0),
    );
  }
}
  • Inside the conversations folder create the given files.dart and paste the given code:

  • conversations / avatar.dart
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:sms/contact.dart';

import '../utils/colors.dart';

class Avatar extends StatelessWidget {
  Avatar(Photo photo, String alternativeText)
      : photo = photo,
        alternativeText = alternativeText,
        super(key: new ObjectKey(photo));

  final Photo photo;
  final String alternativeText;

  @override
  Widget build(BuildContext context) {
    if (photo != null) {
      return new CircleAvatar(
        backgroundImage: new MemoryImage(photo.bytes),
      );
    }

    return new CircleAvatar(
      backgroundColor: ContactColor.getColor(alternativeText),
      child: new Text(alternativeText != null ? alternativeText[0] : 'C'),
    );
  }
}
  • conversations / badge.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/sms.dart';

class Badge extends StatelessWidget {
  Badge(this.messages) : super();

  final List<SmsMessage> messages;

  @override
  Widget build(BuildContext context) {
    if (_countUnreadMessages() == 0) {
      return new Container();
    }

    return new Container(
      padding: const EdgeInsets.all(8.0),
      decoration:
          new ShapeDecoration(shape: new CircleBorder(), color: Colors.red),
      child: new Text(_countUnreadMessages().toString(),
          style: new TextStyle(color: Colors.white)),
    );
  }

  int _countUnreadMessages() {
    return messages
        .where((msg) => msg.kind == SmsMessageKind.Received && !msg.isRead)
        .length;
  }
}
  • conversations / thread.dart
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

import '../conversation/conversation.dart';
import 'avatar.dart';
import 'badge.dart';

class Thread extends StatelessWidget {
  Thread(SmsThread thread, UserProfile userProfile)
      : thread = thread,
        userProfile = userProfile,
        super(key: new ObjectKey(thread));

  final SmsThread thread;
  final UserProfile userProfile;

  @override
  Widget build(BuildContext context) {
    return new ListTile(
      dense: true,
      leading: new Avatar(thread.contact.thumbnail, thread.contact.fullName),
      title: new Text(thread.contact.fullName ?? thread.contact.address),
      subtitle: new Text(
        thread.messages.first.body.trim(),
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
      ),
      trailing: new Badge(thread.messages),
      onTap: () => _showConversation(context),
    );
  }

  void _showConversation(BuildContext context) {
    Navigator.of(context).push(new MaterialPageRoute(
        builder: (context) => new Conversation(thread, userProfile)));
  }
}
  • conversations / threads.dart
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:sms/contact.dart';
import 'package:sms/sms.dart';

import 'thread.dart';

class Threads extends StatefulWidget {
  @override
  State<Threads> createState() => new _ThreadsState();
}

class _ThreadsState extends State<Threads> with TickerProviderStateMixin {
  bool _loading = true;
  List<SmsThread> _threads;
  UserProfile _userProfile;
  final SmsQuery _query = new SmsQuery();
  final SmsReceiver _receiver = new SmsReceiver();
  final UserProfileProvider _userProfileProvider = new UserProfileProvider();
  final SmsSender _smsSender = new SmsSender();

  // Animation
  AnimationController opacityController;

  @override
  void initState() {
    super.initState();
    _receiver.onSmsReceived.listen(_onSmsReceived);
    _userProfileProvider.getUserProfile().then(_onUserProfileLoaded);
    _query.getAllThreads.then(_onThreadsLoaded);
    _smsSender.onSmsDelivered.listen(_onSmsDelivered);

    // Animation
    opacityController = new AnimationController(
        duration: const Duration(milliseconds: 500), vsync: this, value: 0.0);
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('SMS Conversations'),
      ),
      body: _getThreadsWidgets(),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {},
        child: new Icon(Icons.add),
      ),
    );
  }

  Widget _getThreadsWidgets() {
    if (_loading) {
      return new Center(
        child: new CircularProgressIndicator(),
      );
    } else {
      return new FadeTransition(
        opacity: opacityController,
        child: new ListView.builder(
            itemCount: _threads.length,
            itemBuilder: (context, index) {
              return new Thread(_threads[index], _userProfile);
            }),
      );
    }
  }

  void _onSmsReceived(SmsMessage sms) async {
    var thread = _threads.singleWhere((thread) {
      return thread.id == sms.threadId;
    }, orElse: () {
      var thread = new SmsThread(sms.threadId);
      _threads.insert(0, thread);
      return thread;
    });

    thread.addNewMessage(sms);
    await thread.findContact();

    int index = _threads.indexOf(thread);
    if (index != 0) {
      _threads.removeAt(index);
      _threads.insert(0, thread);
    }

    setState(() {});
  }

  void _onThreadsLoaded(List<SmsThread> threads) {
    _threads = threads;
    _checkIfLoadCompleted();
  }

  void _onUserProfileLoaded(UserProfile userProfile) {
    _userProfile = userProfile;
    _checkIfLoadCompleted();
  }

  void _checkIfLoadCompleted() {
    if (_threads != null && _userProfile != null) {
      setState(() {
        _loading = false;
        opacityController.animateTo(1.0, curve: Curves.easeIn);
      });
    }
  }

  void _onSmsDelivered(SmsMessage sms) async {
    final contacts = new ContactQuery();
    Contact contact = await contacts.queryContact(sms.address);
    final snackBar = new SnackBar(
        content: new Text('Message to ${contact.fullName} delivered'));
    Scaffold.of(context).showSnackBar(snackBar);
  }
}
  • Inside the sim folder create the given files.dart and paste the given code:

  • sim / sim_bloc.dart
import 'dart:async';

import 'package:sms/sms.dart';

class SimCardsBloc {
  SimCardsBloc() {
    _onSimCardChanged = _streamController.stream.asBroadcastStream();
  }

  final _simCardsProvider = new SimCardsProvider();
  final _streamController = new StreamController<SimCard>();
  Stream<SimCard> _onSimCardChanged;
  List<SimCard> _simCards;
  SimCard _selectedSimCard;

  Stream<SimCard> get onSimCardChanged => _onSimCardChanged;

  SimCard get selectedSimCard => _selectedSimCard;

  void loadSimCards() async {
    _simCards = await _simCardsProvider.getSimCards();
    _simCards.forEach((sim) {
      if (sim.state == SimCardState.Ready) {
        this.selectSimCard(sim);
      }
    });
  }

  void toggleSelectedSim() async {
    if (_simCards == null) {
      _simCards = await _simCardsProvider.getSimCards();
    }

    _selectNextSimCard();
    _streamController.add(_selectedSimCard);
  }

  SimCard _selectNextSimCard() {
    if (_selectedSimCard == null) {
      _selectedSimCard = _simCards[0];
      return _selectedSimCard;
    }

    for (var i = 0; i < _simCards.length; i++) {
      if (_simCards[i].imei == _selectedSimCard.imei) {
        if (i + 1 < _simCards.length) {
          _selectedSimCard = _simCards[i + 1];
        } else {
          _selectedSimCard = _simCards[0];
        }
        break;
      }
    }

    return _selectedSimCard;
  }

  void selectSimCard(SimCard sim) {
    _selectedSimCard = sim;
    _streamController.add(_selectedSimCard);
  }
}
  • sim / sim_bloc_porvider.dart
import 'package:flutter/widgets.dart';
import 'sim_bloc.dart';

class SimCardsBlocProvider extends InheritedWidget {
  SimCardsBlocProvider({this.simCardBloc, @required Widget child})
      : assert(child != null),
        super(child: child);

  final SimCardsBloc simCardBloc;

  static SimCardsBloc of(BuildContext context) {
    final provider = context.inheritFromWidgetOfExactType(SimCardsBlocProvider);
    if (provider != null) {
      return (provider as SimCardsBlocProvider).simCardBloc;
    }

    return null;
  }

  @override
  bool updateShouldNotify(SimCardsBlocProvider old) {
    return simCardBloc != old.simCardBloc;
  }
}
  • Inside the utils folder create the given files.dart and paste the given code:

  • utils / colors.dart
import 'package:flutter/material.dart';

class ContactColor {
  static List<Color> _colors = [
    new Color(0xFFDB4437),
    new Color(0xFFE91E63),
    new Color(0xFF9C27B0),
    new Color(0xFF673AB7),
    new Color(0xFF3F51B5),
    new Color(0xFF4285F4),
    new Color(0xFF039BE5),
    new Color(0xFF0097A7),
    new Color(0xFF009688),
    new Color(0xFF0F9D58),
    new Color(0xFF689F38),
    new Color(0xFFEF6C00),
    new Color(0xFFFF5722),
    new Color(0xFF757575),
  ];

  static List<Color> get allColors {
    return _colors;
  }

  static Color getColor(String contactId) {
    final int color = (contactId.hashCode % ContactColor.allColors.length);
    return ContactColor.allColors.elementAt(color);
  }
}
  • utils / group.dart
import 'package:flutter/material.dart';
import 'package:sms/sms.dart';

class MessageGroupService {
  static MessageGroupService of(BuildContext context) {
    return new MessageGroupService._private(context);
  }

  MessageGroupService._private(this.context);

  final BuildContext context;

  List<Group> groupByDate(List<SmsMessage> messages) {
    final groups = new _GroupCollection();
    messages.forEach((message) {
      String groupLabel =
          MaterialLocalizations.of(context).formatFullDate(message.date);
      if (groups.contains(groupLabel)) {
        groups.get(groupLabel).addMessage(message);
      } else {
        groups.add(new Group(groupLabel, messages: [message]));
      }
    });
    return groups.groups;
  }
}

class Group {
  String label;
  List<SmsMessage> messages;

  Group(this.label, {this.messages = const <SmsMessage>[]});

  void addMessage(SmsMessage message) {
    messages.insert(0, message);
  }
}

class _GroupCollection {
  List<Group> groups = <Group>[];

  bool contains(String label) {
    return groups.any((group) {
      return group.label == label;
    });
  }

  Group get(String label) {
    return groups.singleWhere((group) {
      return group.label == label;
    });
  }

  void add(Group group) {
    groups.add(group);
  }
}

SHARE Awesome SMS library for Flutter App, flutter_sms

You may also like...

Leave a Reply

Your email address will not be published.

Share