social_share_kit
Share text, links and files directly to a chosen app — X, WhatsApp, Instagram, Threads, Telegram, LinkedIn, Messenger, TikTok, SMS, mail — or to the system share sheet.
Two things set it apart from a share-sheet wrapper:
- It tells you what will work before you try. What each app accepts differs sharply by platform. X takes text and up to four images on Android, but only text on iOS. Instagram strips pre-filled captions everywhere.
SocialShareKit.capabilities()reports all of it up front, so you can disable a button instead of discovering the limit after the user taps it. - It bundles no vendor SDKs. No Facebook SDK, no TikTok OpenSDK. Sharing goes through published URL schemes, Android intents and system composers. Nothing to register, no app id, no client token, no
AppDelegatewiring — except for the two story composers, which genuinely require a Facebook app id.
final result = await SocialShareKit.shareTo(
ShareTarget.x,
ShareContent.text('Shipping today', url: 'https://example.com'),
);
switch (result.status) {
case ShareStatus.success: // the composer opened
case ShareStatus.appNotInstalled: // hide the button next time
case ShareStatus.unsupportedContent: // result.message says why
default: break;
}
Install
dependencies:
social_share_kit: ^0.1.0
Android needs nothing. The <queries> declarations and the FileProvider ship in the plugin's own manifest and merge into your app.
iOS needs two Info.plist keys. iOS reports every app as missing unless its scheme is listed, so this is not optional:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>twitter</string> <!-- X -->
<string>whatsapp</string>
<string>instagram</string>
<string>instagram-stories</string>
<string>barcelona</string> <!-- Threads -->
<string>fb</string>
<string>facebook-stories</string>
<string>fb-messenger</string>
<string>tg</string> <!-- Telegram -->
<string>linkedin</string>
<string>snssdk1233</string> <!-- TikTok -->
</array>
<!-- Only if you share to Instagram feed or Reels -->
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Saves the media you share so Instagram can open it.</string>
Trim the list to the targets you offer; Apple caps it at 50 entries.
What each target accepts
✓ supported · clip accepted but the app strips it, so it goes to the clipboard · — not supported
| Target | Android | iOS |
|---|---|---|
x |
text · link · 4 media | text · link |
whatsapp |
text · link · files | text · link · 1 image |
instagramFeed |
clip · 10 media | clip · 1 media |
instagramReels |
clip · 1 video | clip · 1 video |
instagramDirect |
text · link | text · link |
instagramStory |
story | story |
facebook |
clip · link · 10 media | — |
facebookStory |
story | story |
messenger |
text · link · media | link only |
telegram |
text · link · files | text · link |
threads |
text · link · 10 media | clip |
linkedinFeed |
text · link · 1 image | clip + link |
linkedinDirect |
text · link · 1 image | text · link |
tiktok |
clip · 35 media | — |
sms |
text · link · files | text · link · files · cancel reported |
email |
text · link · files · subject | text · link · files · subject · cancel reported |
systemSheet |
everything | everything · cancel reported |
clipboard |
text | text |
Read this at runtime rather than from the table:
final caps = SocialShareKit.capabilities(ShareTarget.x);
caps.supportsFiles // false on iOS, true on Android
caps.maxFiles // 4 on Android
caps.textLimit // 280
caps.prefillsText // false for Instagram, Facebook, TikTok
caps.note // the caveat, in prose
The two that are not supported on iOS
facebook and tiktok return ShareStatus.unsupportedPlatform on iOS with an explanation. Facebook's iOS app publishes no sharing URL scheme, and TikTok requires its OpenSDK — both would mean bundling a vendor SDK on every user of this package to serve a minority. Either pass fallbackToSystemSheet: true, or send them to ShareTarget.systemSheet and let the user pick.
Usage
Text, links and files
// text only
await SocialShareKit.shareTo(ShareTarget.whatsapp, ShareContent.text('Hello'));
// files only
await SocialShareKit.shareTo(
ShareTarget.instagramFeed,
ShareContent.files(['/path/photo.jpg']),
);
// both
await SocialShareKit.shareTo(
ShareTarget.telegram,
ShareContent.textWithFiles(text: 'Look', files: ['/path/a.png', '/path/b.png']),
);
// a link as a distinct field — required by the LinkedIn feed composer on iOS,
// which ignores URLs embedded in body text
await SocialShareKit.shareTo(
ShareTarget.linkedinFeed,
ShareContent.link('https://example.com', text: 'My commentary'),
);
File paths must be absolute paths to files your app can read. On Android they are handed over as content:// URIs from the plugin's own FileProvider, which covers your cache, files, and external directories.
Falling back
await SocialShareKit.shareTo(
ShareTarget.x,
ShareContent.files(['/path/clip.mp4']),
fallbackToSystemSheet: true, // X takes no files on iOS — use the sheet there
);
The fallback triggers when the target cannot take this content on this platform. It does not trigger on empty content, which is a caller bug rather than a platform limit.
Stories
The only calls needing a Facebook app id.
await SocialShareKit.shareStory(
ShareTarget.instagramStory,
StoryContent(
appId: '<your facebook app id>',
backgroundImage: '/path/bg.jpg',
stickerImage: '/path/sticker.png', // transparent PNG
attributionUrl: 'https://example.com',
text: 'Copied to the clipboard for pasting',
),
);
A story needs a background image, a background video, or both gradient colours. Neither composer accepts pre-filled text, so text rides along on the clipboard.
Checking what is installed
final installed = await SocialShareKit.installedTargets();
if (installed[ShareTarget.whatsapp] == true) { /* show the button */ }
A target can read as missing purely because your app cannot see it — Android 11+ hides packages absent from <queries> (handled for you), iOS hides schemes absent from LSApplicationQueriesSchemes (yours to add).
Fitting text to a composer
Nothing is truncated automatically; ShareText is there when you want it.
ShareText.stripHtml('<p>Rich <b>text</b></p>'); // 'Rich text'
ShareText.truncateForTarget(
longPost,
ShareTarget.x,
keepSuffix: 'https://example.com', // reserves room so the link survives
);
What success means
That the target's composer opened. Not that the user posted — no mainstream social app reports that back, and any package claiming otherwise is guessing.
Only sms, email and systemSheet distinguish cancelled from success, because only they hand control back to your app. Everything else is a one-way URL or intent handoff. ShareCapabilities.reportsCancellation tells you which is which.
Errors
Calls complete with a ShareResult rather than throwing — a missing app is an ordinary outcome. ArgumentError is thrown only for programming mistakes: passing a story target to shareTo, or a non-story target to shareStory.
Contributing
flutter test # 57 unit tests
cd example && flutter test # widget tests
cd example && flutter test integration_test # on a device
The capability table in lib/src/models/share_capabilities.dart is mirrored by enums in android/…/ShareTargets.kt and ios/…/ShareTarget.swift. Adding a target means touching all three; the integration test fails if the native side omits one.
Licence
MIT. See LICENSE.
Libraries
- Share text, links and files to specific social apps from Flutter.