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

PlatformAndroid

Flutter plugin to read SMS inbox, conversations, and messages on Android with typed models.

example/lib/main.dart

import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:flutter_sms_reader/flutter_sms_reader.dart';
import 'package:permission_handler/permission_handler.dart';

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

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

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

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  List<SmsMessage> _smsMessages = [];
  List<SmsConversation> _conversations = [];
  bool _isLoading = false;
  String _statusMessage = '';

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

  Future<void> _requestPermissions() async {
    final status = await Permission.sms.request();
    if (status.isGranted) {
      setState(() {
        _statusMessage = 'SMS permission granted';
      });
    } else {
      setState(() {
        _statusMessage = 'SMS permission denied';
      });
    }
  }

  Future<void> _getAllSMS() async {
    setState(() {
      _isLoading = true;
      _statusMessage = '';
    });

    try {
      final messages = await FlutterSmsReader.getAllSms();
      setState(() {
        _smsMessages = messages;
        _statusMessage = 'Loaded ${messages.length} SMS messages';
      });
    } catch (e) {
      log(e.toString());
      setState(() {
        _statusMessage = 'Error loading SMS: $e';
      });
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  Future<void> _getConversations() async {
    setState(() {
      _isLoading = true;
      _statusMessage = '';
    });

    try {
      final conversations = await FlutterSmsReader.getConversations(limit: 20);
      setState(() {
        _conversations = conversations;
        _statusMessage = 'Loaded ${conversations.length} conversations';
      });
    } catch (e) {
      setState(() {
        _statusMessage = 'Error loading conversations: $e';
      });
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const SizedBox(height: 8),
                    if (_statusMessage.isNotEmpty)
                      Text(
                        _statusMessage,
                        style: TextStyle(
                          color: _statusMessage.contains('Error')
                              ? Colors.red
                              : Colors.green,
                        ),
                      ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: 16),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton(
                  onPressed: _requestPermissions,
                  child: const Text('Request Permissions'),
                ),
                ElevatedButton(
                  onPressed: _isLoading ? null : _getAllSMS,
                  child: const Text('Get All SMS'),
                ),
                ElevatedButton(
                  onPressed: _isLoading ? null : _getConversations,
                  child: const Text('Get Conversations'),
                ),
              ],
            ),
            const SizedBox(height: 16),
            if (_isLoading)
              const Center(child: CircularProgressIndicator())
            else
              Expanded(
                child: DefaultTabController(
                  length: 2,
                  child: Column(
                    children: [
                      const TabBar(
                        tabs: [
                          Tab(text: 'SMS Messages'),
                          Tab(text: 'Conversations'),
                        ],
                      ),
                      Expanded(
                        child: TabBarView(
                          children: [
                            _buildSMSList(),
                            _buildConversationsList(),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }

  Widget _buildSMSList() {
    if (_smsMessages.isEmpty) {
      return const Center(
        child: Text('No SMS messages loaded. Tap "Get All SMS" to load.'),
      );
    }

    return ListView.builder(
      itemCount: _smsMessages.length,
      itemBuilder: (context, index) {
        final sms = _smsMessages[index];
        return Card(
          margin: const EdgeInsets.symmetric(vertical: 4),
          child: ListTile(
            title: Text(sms.address),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(sms.body),
                const SizedBox(height: 4),
                Text(
                  'Date: ${_formatDate(sms.date)}',
                  style: const TextStyle(fontSize: 12, color: Colors.grey),
                ),
              ],
            ),
            trailing: Icon(
              sms.read ? Icons.mark_email_read : Icons.mark_email_unread,
              color: sms.read ? Colors.green : Colors.orange,
            ),
            onTap: () => _showSMSDetails(context, sms),
          ),
        );
      },
    );
  }

  Widget _buildConversationsList() {
    if (_conversations.isEmpty) {
      return const Center(
        child: Text(
          'No conversations loaded. Tap "Get Conversations" to load.',
        ),
      );
    }

    return ListView.builder(
      itemCount: _conversations.length,
      itemBuilder: (context, index) {
        final conversation = _conversations[index];
        return Card(
          margin: const EdgeInsets.symmetric(vertical: 4),
          child: ListTile(
            title: Text(conversation.address),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(conversation.snippet),
                const SizedBox(height: 4),
                Text(
                  'Date: ${_formatDate(conversation.date)}',
                  style: const TextStyle(fontSize: 12, color: Colors.grey),
                ),
              ],
            ),
            trailing: const Icon(Icons.chat),
            onTap: () => _showConversationMessages(context, conversation),
          ),
        );
      },
    );
  }

  String _formatDate(DateTime date) {
    return '${date.day}/${date.month}/${date.year} ${date.hour}:${date.minute.toString().padLeft(2, '0')}';
  }

  void _showSMSDetails(BuildContext context, SmsMessage sms) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('SMS from ${sms.address}'),
        content: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text('Body: ${sms.body}'),
              const SizedBox(height: 8),
              Text('Date: ${_formatDate(sms.date)}'),
              Text('Date Sent: ${_formatDate(sms.dateSent)}'),
              Text('Type: ${sms.type.description}'),
              Text('Read: ${sms.read ? "Yes" : "No"}'),
              Text('ID: ${sms.id}'),
            ],
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }

  void _showConversationMessages(
    BuildContext context,
    SmsConversation conversation,
  ) async {
    try {
      final messages = await FlutterSmsReader.getConversationMessages(
        conversation.threadId,
      );

      if (!context.mounted) return;

      showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: Text('Messages with ${conversation.address}'),
          content: SizedBox(
            width: double.maxFinite,
            height: 400,
            child: ListView.builder(
              itemCount: messages.length,
              itemBuilder: (context, index) {
                final message = messages[index];
                return Card(
                  child: Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(message.body),
                        const SizedBox(height: 4),
                        Text(
                          _formatDate(message.date),
                          style: const TextStyle(
                            fontSize: 12,
                            color: Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
          ),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('Close'),
            ),
          ],
        ),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Error loading conversation messages: $e')),
      );
    }
  }
}
1
likes
160
points
19
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter plugin to read SMS inbox, conversations, and messages on Android with typed models.

Repository (GitHub)
View/report issues

Topics

#sms #telephony #android #plugin #messages

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flutter_sms_reader

Packages that implement flutter_sms_reader