share_intent_package 1.0.31 copy "share_intent_package: ^1.0.31" to clipboard
share_intent_package: ^1.0.31 copied to clipboard

Zero-configuration Flutter share intent plugin. Receive shared content from other apps with one-command setup. Fully automated iOS ShareExtension + Android intent filters.

example/lib/main.dart

import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:share_intent_package/share_intent_package.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Share Intent Test',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const ShareTestPage(),
    );
  }
}

class ShareTestPage extends StatefulWidget {
  const ShareTestPage({super.key});

  @override
  State<ShareTestPage> createState() => _ShareTestPageState();
}

class _ShareTestPageState extends State<ShareTestPage> with SingleTickerProviderStateMixin {
  late TabController _tabController;
  StreamSubscription? _subscription;
  SharedData? _sharedData;
  String _status = 'Waiting for shared content...';

  // Share Out Controllers
  final TextEditingController _textController = TextEditingController(
    text: 'Hello from Share Intent Package!',
  );
  final TextEditingController _fileContentController = TextEditingController(
    text: 'This is a temporary text file shared from the example app.',
  );
  final TextEditingController _mixedTextController = TextEditingController(
    text: 'Check out this file!',
  );
  final TextEditingController _mixedFileContentController = TextEditingController(
    text: 'Content of the mixed share file.',
  );

  String _shareOutStatus = 'Idle';

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
    _initSharing();
  }

  Future<void> _initSharing() async {
    try {
      // Initialize the plugin
      await ShareIntentPackage.instance.init();

      // Get initial sharing data (if app was opened via share)
      final initial = await ShareIntentPackage.instance.getInitialSharing();
      if (initial != null && initial.hasContent) {
        setState(() {
          _sharedData = initial;
          _status = 'Received initial shared content!';
        });
      }

      // Listen for shares while app is running
      _subscription = ShareIntentPackage.instance.getMediaStream().listen((
        data,
      ) {
        setState(() {
          _sharedData = data;
          _status = 'Received new shared content!';
        });
      });

      setState(() {
        if (_sharedData == null) {
          _status = 'Plugin initialized. Share something to this app!';
        }
      });
    } catch (e) {
      setState(() {
        _status = 'Error initializing: $e';
      });
    }
  }

  @override
  void dispose() {
    _tabController.dispose();
    _subscription?.cancel();
    _textController.dispose();
    _fileContentController.dispose();
    _mixedTextController.dispose();
    _mixedFileContentController.dispose();
    super.dispose();
  }

  Future<File> _createTempFile(String name, String content) async {
    final tempDir = Directory.systemTemp;
    final file = File('${tempDir.path}/$name');
    await file.writeAsString(content);
    return file;
  }

  Future<void> _shareText() async {
    final text = _textController.text.trim();
    if (text.isEmpty) {
      setState(() => _shareOutStatus = 'Error: Share text cannot be empty');
      return;
    }
    setState(() => _shareOutStatus = 'Sharing text...');
    try {
      await ShareIntentPackage.shareText(text);
      setState(() => _shareOutStatus = 'Text shared successfully!');
    } catch (e) {
      setState(() => _shareOutStatus = 'Error sharing text: $e');
    }
  }

  Future<void> _shareFile() async {
    final content = _fileContentController.text;
    setState(() => _shareOutStatus = 'Creating temp file...');
    try {
      final file = await _createTempFile('share_test_file.txt', content);
      setState(() => _shareOutStatus = 'Sharing file...');
      await ShareIntentPackage.shareFiles([file.path]);
      setState(() => _shareOutStatus = 'File shared successfully!');
    } catch (e) {
      setState(() => _shareOutStatus = 'Error sharing file: $e');
    }
  }

  Future<void> _shareMixed() async {
    final text = _mixedTextController.text.trim();
    final content = _mixedFileContentController.text;
    setState(() => _shareOutStatus = 'Creating temp file for mixed share...');
    try {
      final file = await _createTempFile('share_test_mixed.txt', content);
      setState(() => _shareOutStatus = 'Sharing mixed content...');
      await ShareIntentPackage.shareContent(
        text: text.isEmpty ? null : text,
        filePaths: [file.path],
      );
      setState(() => _shareOutStatus = 'Mixed content shared successfully!');
    } catch (e) {
      setState(() => _shareOutStatus = 'Error sharing mixed content: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Share Intent Test'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(icon: Icon(Icons.download), text: 'Receive Share (In)'),
            Tab(icon: Icon(Icons.upload), text: 'Send Share (Out)'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          _buildReceiveShareTab(),
          _buildSendShareTab(),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _sharedData = null;
            _status = 'Cleared. Waiting for shared content...';
            _shareOutStatus = 'Idle';
          });
        },
        tooltip: 'Clear',
        child: const Icon(Icons.clear),
      ),
    );
  }

  Widget _buildReceiveShareTab() {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Status Card
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Status',
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 8),
                  Text(_status),
                ],
              ),
            ),
          ),
          const SizedBox(height: 16),

          // Shared Data Card
          if (_sharedData != null) ...[
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Shared Content',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 16),

                    // Content Type
                    _buildInfoRow('Type', _getContentType()),
                    const SizedBox(height: 8),

                    // MIME Type
                    if (_sharedData!.mimeType != null)
                      _buildInfoRow('MIME Type', _sharedData!.mimeType!),

                    // Text Content
                    if (_sharedData!.text != null) ...[
                      const SizedBox(height: 8),
                      _buildInfoRow('Text', _sharedData!.text!),
                    ],

                    // File Paths
                    if (_sharedData!.filePaths.isNotEmpty) ...[
                      const SizedBox(height: 16),
                      Text(
                        'Files (${_sharedData!.filePaths.length}):',
                        style: Theme.of(context).textTheme.titleSmall,
                      ),
                      const SizedBox(height: 8),
                      ..._sharedData!.filePaths.map((path) {
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              path,
                              style: Theme.of(context).textTheme.bodySmall,
                            ),
                            const SizedBox(height: 8),
                            // Show image preview if it's an image
                            if (_isImageFile(path))
                              ClipRRect(
                                borderRadius: BorderRadius.circular(8),
                                child: Image.file(
                                  File(path),
                                  height: 200,
                                  fit: BoxFit.cover,
                                  errorBuilder: (context, error, stackTrace) {
                                    return Container(
                                      height: 100,
                                      color: Colors.grey[300],
                                      child: const Center(
                                        child: Text('Could not load image'),
                                      ),
                                    );
                                  },
                                ),
                              ),
                            const SizedBox(height: 16),
                          ],
                        );
                      }),
                    ],
                  ],
                ),
              ),
            ),
          ] else ...[
            Card(
              child: Padding(
                padding: const EdgeInsets.all(32),
                child: Center(
                  child: Column(
                    children: [
                      Icon(Icons.share, size: 64, color: Colors.grey[400]),
                      const SizedBox(height: 16),
                      Text(
                        'No shared content yet',
                        style: Theme.of(context).textTheme.titleMedium
                            ?.copyWith(color: Colors.grey[600]),
                      ),
                      const SizedBox(height: 8),
                      Text(
                        'Share an image, text, or URL from another app to test',
                        textAlign: TextAlign.center,
                        style: Theme.of(context).textTheme.bodyMedium
                            ?.copyWith(color: Colors.grey[500]),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ],

          const SizedBox(height: 24),

          // Instructions Card
          Card(
            color: Colors.blue[50],
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      Icon(Icons.info_outline, color: Colors.blue[700]),
                      const SizedBox(width: 8),
                      Text(
                        'How to Test Receive',
                        style: Theme.of(context).textTheme.titleMedium
                            ?.copyWith(color: Colors.blue[700]),
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  Text(
                    '1. Open your photo gallery or browser\n'
                    '2. Select an image, video, or copy a URL\n'
                    '3. Tap the share button\n'
                    '4. Select this app from the share menu\n'
                    '5. The shared content will appear here',
                    style: Theme.of(context).textTheme.bodyMedium,
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSendShareTab() {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // Operation Status Card
          Card(
            color: Colors.green[50],
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Row(
                children: [
                  Icon(Icons.sync, color: Colors.green[700]),
                  const SizedBox(width: 12),
                  Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'Share Out Action Status',
                          style: Theme.of(context).textTheme.titleSmall
                              ?.copyWith(color: Colors.green[800]),
                        ),
                        Text(
                          _shareOutStatus,
                          style: Theme.of(context).textTheme.bodyMedium,
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 16),

          // 1. Share Text
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '1. Share Text / URL',
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 8),
                  TextField(
                    key: const Key('share_text_field'),
                    controller: _textController,
                    decoration: const InputDecoration(
                      labelText: 'Text to Share',
                      border: OutlineInputBorder(),
                    ),
                    maxLines: 2,
                  ),
                  const SizedBox(height: 12),
                  ElevatedButton.icon(
                    key: const Key('share_text_button'),
                    onPressed: _shareText,
                    icon: const Icon(Icons.text_fields),
                    label: const Text('Share Text'),
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 16),

          // 2. Share File
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '2. Share File (Temporary Text File)',
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 8),
                  TextField(
                    key: const Key('share_file_content_field'),
                    controller: _fileContentController,
                    decoration: const InputDecoration(
                      labelText: 'Temp File Content',
                      border: OutlineInputBorder(),
                    ),
                    maxLines: 2,
                  ),
                  const SizedBox(height: 12),
                  ElevatedButton.icon(
                    key: const Key('share_file_button'),
                    onPressed: _shareFile,
                    icon: const Icon(Icons.insert_drive_file),
                    label: const Text('Create & Share File'),
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 16),

          // 3. Share Mixed
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '3. Share Mixed (Text + File)',
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 8),
                  TextField(
                    key: const Key('share_mixed_text_field'),
                    controller: _mixedTextController,
                    decoration: const InputDecoration(
                      labelText: 'Mixed Share Text',
                      border: OutlineInputBorder(),
                    ),
                  ),
                  const SizedBox(height: 8),
                  TextField(
                    key: const Key('share_mixed_content_field'),
                    controller: _mixedFileContentController,
                    decoration: const InputDecoration(
                      labelText: 'Mixed Temp File Content',
                      border: OutlineInputBorder(),
                    ),
                  ),
                  const SizedBox(height: 12),
                  ElevatedButton.icon(
                    key: const Key('share_mixed_button'),
                    onPressed: _shareMixed,
                    icon: const Icon(Icons.all_inclusive),
                    label: const Text('Share Mixed Content'),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildInfoRow(String label, String value) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          width: 80,
          child: Text(
            '$label:',
            style: const TextStyle(fontWeight: FontWeight.bold),
          ),
        ),
        Expanded(child: Text(value)),
      ],
    );
  }

  String _getContentType() {
    if (_sharedData == null) return 'Unknown';
    if (_sharedData!.isImage) return 'Image';
    if (_sharedData!.isVideo) return 'Video';
    if (_sharedData!.isUrl) return 'URL';
    if (_sharedData!.isText) return 'Text';
    if (_sharedData!.isMedia) return 'File';
    return 'Unknown';
  }

  bool _isImageFile(String path) {
    final lower = path.toLowerCase();
    return lower.endsWith('.jpg') ||
        lower.endsWith('.jpeg') ||
        lower.endsWith('.png') ||
        lower.endsWith('.gif') ||
        lower.endsWith('.webp') ||
        lower.endsWith('.bmp');
  }
}
9
likes
150
points
469
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Zero-configuration Flutter share intent plugin. Receive shared content from other apps with one-command setup. Fully automated iOS ShareExtension + Android intent filters.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on share_intent_package

Packages that implement share_intent_package