Here's a comprehensive guide to building a MAUI app that allows users to share text and images on social networks.
1. Set Up the Project
First, create a new MAUI project:
dotnet new maui -name SocialShareApp
2. Add Required Permissions
For Android, add these permissions to Platforms/Android/AndroidManifest.xml
:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" />
For iOS, add these entries to Platforms/iOS/Info.plist
:
<key>NSPhotoLibraryUsageDescription</key> <string>Need photo library access to share images</string> <key>NSPhotoLibraryAddUsageDescription</key> <string>Need photo library access to save images</string>
3. Create the Sharing Service Interface
Add an interface in Services/IShareService.cs
:
public interface IShareService { Task ShareText(string text); Task ShareImage(byte[] imageData, string title, string message); Task ShareTextAndImage(string text, byte[] imageData, string title); Task PickAndShareImage(); }
4. Implement Platform-Specific Sharing
Create platform implementations:
Android Implementation (Platforms/Android/ShareService.android.cs
):
using Android.Content; using Android.Net; public partial class ShareService : IShareService { public async Task ShareText(string text) { var intent = new Intent(Intent.ActionSend); intent.SetType("text/plain"); intent.PutExtra(Intent.ExtraText, text); intent.AddFlags(ActivityFlags.NewTask); Platform.CurrentActivity.StartActivity(Intent.CreateChooser(intent, "Share via")); } public async Task ShareImage(byte[] imageData, string title, string message) { var tempFile = System.IO.Path.Combine(FileSystem.CacheDirectory, "temp_image.jpg"); await File.WriteAllBytesAsync(tempFile, imageData); var uri = FileProvider.GetUriForFile(Platform.CurrentActivity, $"{Platform.CurrentActivity.PackageName}.fileprovider", new Java.IO.File(tempFile)); var intent = new Intent(Intent.ActionSend); intent.SetType("image/*"); intent.PutExtra(Intent.ExtraStream, uri); intent.PutExtra(Intent.ExtraText, message); intent.AddFlags(ActivityFlags.GrantReadUriPermission); Platform.CurrentActivity.StartActivity(Intent.CreateChooser(intent, title)); } public async Task ShareTextAndImage(string text, byte[] imageData, string title) { var tempFile = System.IO.Path.Combine(FileSystem.CacheDirectory, "temp_image.jpg"); await File.WriteAllBytesAsync(tempFile, imageData); var uri = FileProvider.GetUriForFile(Platform.CurrentActivity, $"{Platform.CurrentActivity.PackageName}.fileprovider", new Java.IO.File(tempFile)); var intent = new Intent(Intent.ActionSend); intent.SetType("image/*"); intent.PutExtra(Intent.ExtraStream, uri); intent.PutExtra(Intent.ExtraText, text); intent.AddFlags(ActivityFlags.GrantReadUriPermission); Platform.CurrentActivity.StartActivity(Intent.CreateChooser(intent, title)); } public async Task PickAndShareImage() { try { var fileResult = await MediaPicker.PickPhotoAsync(); if (fileResult != null) { using var stream = await fileResult.OpenReadAsync(); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); await ShareImage(memoryStream.ToArray(), "Share Image", "Check out this image!"); } } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", ex.Message, "OK"); } } }
iOS Implementation (Platforms/iOS/ShareService.ios.cs
):
using UIKit; public partial class ShareService : IShareService { public Task ShareText(string text) { var items = new NSObject[] { new NSString(text) }; var activityController = new UIActivityViewController(items, null); var window = UIApplication.SharedApplication.KeyWindow; var rootViewController = window.RootViewController; if (rootViewController.PresentedViewController is UINavigationController navController) { navController.PresentViewController(activityController, true, null); } else { rootViewController.PresentViewController(activityController, true, null); } return Task.CompletedTask; } public Task ShareImage(byte[] imageData, string title, string message) { var image = new UIImage(NSData.FromArray(imageData)); var items = new NSObject[] { image, new NSString(message) }; var activityController = new UIActivityViewController(items, null); var window = UIApplication.SharedApplication.KeyWindow; var rootViewController = window.RootViewController; if (rootViewController.PresentedViewController is UINavigationController navController) { navController.PresentViewController(activityController, true, null); } else { rootViewController.PresentViewController(activityController, true, null); } return Task.CompletedTask; } public Task ShareTextAndImage(string text, byte[] imageData, string title) { var image = new UIImage(NSData.FromArray(imageData)); var items = new NSObject[] { image, new NSString(text) }; var activityController = new UIActivityViewController(items, null); var window = UIApplication.SharedApplication.KeyWindow; var rootViewController = window.RootViewController; if (rootViewController.PresentedViewController is UINavigationController navController) { navController.PresentViewController(activityController, true, null); } else { rootViewController.PresentViewController(activityController, true, null); } return Task.CompletedTask; } public async Task PickAndShareImage() { try { var fileResult = await MediaPicker.PickPhotoAsync(); if (fileResult != null) { using var stream = await fileResult.OpenReadAsync(); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); await ShareImage(memoryStream.ToArray(), "Share Image", "Check out this image!"); } } catch (Exception ex) { await Shell.Current.DisplayAlert("Error", ex.Message, "OK"); } } }
5. Register the Service
In MauiProgram.cs
:
builder.Services.AddSingleton<IShareService, ShareService>();
6. Create the UI
Here's a simple UI in MainPage.xaml
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SocialShareApp.MainPage" Title="Social Share App"> <ScrollView> <VerticalStackLayout Spacing="20" Padding="20"> <!-- Text Sharing --> <Label Text="Share Text" FontSize="Title" /> <Entry x:Name="ShareTextEntry" Placeholder="Enter text to share" /> <Button Text="Share Text" Clicked="OnShareTextClicked" /> <!-- Image Sharing --> <Label Text="Share Image" FontSize="Title" Margin="0,20,0,0" /> <Button Text="Select Image" Clicked="OnSelectImageClicked" /> <Image x:Name="PreviewImage" HeightRequest="200" Aspect="AspectFit" /> <Entry x:Name="ImageCaptionEntry" Placeholder="Enter caption for image" /> <Button Text="Share Image" Clicked="OnShareImageClicked" /> <!-- Combined Sharing --> <Label Text="Share Text with Image" FontSize="Title" Margin="0,20,0,0" /> <Entry x:Name="CombinedTextEntry" Placeholder="Enter text to share with image" /> <Button Text="Share Text with Image" Clicked="OnShareTextWithImageClicked" /> </VerticalStackLayout> </ScrollView> </ContentPage>
7. Implement the Code-Behind
In MainPage.xaml.cs
:
public partial class MainPage : ContentPage { private byte[] _selectedImageData; private readonly IShareService _shareService; public MainPage(IShareService shareService) { InitializeComponent(); _shareService = shareService; } private async void OnShareTextClicked(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(ShareTextEntry.Text)) { await DisplayAlert("Error", "Please enter some text to share", "OK"); return; } await _shareService.ShareText(ShareTextEntry.Text); } private async void OnSelectImageClicked(object sender, EventArgs e) { try { var fileResult = await MediaPicker.PickPhotoAsync(); if (fileResult != null) { using var stream = await fileResult.OpenReadAsync(); PreviewImage.Source = ImageSource.FromStream(() => stream); // Store the image data for sharing using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); _selectedImageData = memoryStream.ToArray(); } } catch (Exception ex) { await DisplayAlert("Error", ex.Message, "OK"); } } private async void OnShareImageClicked(object sender, EventArgs e) { if (_selectedImageData == null) { await DisplayAlert("Error", "Please select an image first", "OK"); return; } await _shareService.ShareImage( _selectedImageData, "Shared from my app", ImageCaptionEntry.Text ?? "Check out this image!"); } private async void OnShareTextWithImageClicked(object sender, EventArgs e) { if (_selectedImageData == null) { await DisplayAlert("Error", "Please select an image first", "OK"); return; } if (string.IsNullOrWhiteSpace(CombinedTextEntry.Text)) { await DisplayAlert("Error", "Please enter some text to share", "OK"); return; } await _shareService.ShareTextAndImage( CombinedTextEntry.Text, _selectedImageData, "Shared from my app"); } }
8. Android-Specific Configuration
For Android file sharing, add this to Platforms/Android/MainApplication.cs
:
[Application] public class MainApplication : MauiApplication { public MainApplication(IntPtr handle, JniHandleOwnership ownership) : base(handle, ownership) { } protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); }
And create Platforms/Android/Resources/xml/file_paths.xml
:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <cache-path name="shared_images" path="." /> </paths>
Add this to Platforms/Android/AndroidManifest.xml
inside the <application>
tag:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
9. iOS-Specific Configuration
No additional configuration is needed for iOS beyond the Info.plist entries we already added.
10. Testing the App
Now you can:
Share plain text to any social app
Select and share images
Share text with images
Add captions to shared images
Additional Features to Consider
Social Platform-Specific Sharing: Add direct sharing to specific platforms using their SDKs
Multiple Image Sharing: Extend to share multiple images at once
Video Sharing: Add support for video sharing
Analytics: Track what content is being shared
Link Preview: Generate link previews when sharing URLs
This implementation provides a complete cross-platform solution for sharing content to social networks from a MAUI app.
No comments:
Post a Comment