DEV Community

Cover image for Using Share Sheets on iOS and Android
Jake Bloom
Jake Bloom

Posted on

Using Share Sheets on iOS and Android

A Share Sheet is a really powerful feature that's available on pretty much any phone today. If you are an application developer and you want your users to be talking about your product, a compelling experience with a well set up Share Sheet can help unlock network-effect growth.

What is a Share Sheet and why should I use it?

Share Sheets are interfaces in both iOS and Android that allows you to share content from your app to another app. For example, in your Photos app, you can select an image and then share it to other apps like Instagram, your mail app, your messaging app and plenty more.

The actual logic behind the Share Sheets is handled by the operating system, all you need to do as an app developer is tell it to open. Share sheets are set up this way so you don't have to update your app code to handle new apps that can share the same content. You send the operating system your content to be shared, and it will tell the user where it can be shared to.

On iOS, the Share Sheet looks like this:

Share Sheet

And on Android, it looks like this:

Android share sheet

How do I do it?

Lets get into some code!

iOS

On iOS, the Share Sheet comes in the form of a view controller that you need to programmatically create and present to the user. It is called UIActivityViewController, and for simple use cases, it is pretty easy:

let textToSend = "This is some text that will be exported to another app!"
let activityViewController = UIActivityViewController(activityItems: [textToSend], applicationActivities: nil)

currentViewController.present(activityViewController, animated: true, completion: nil)

With that code in place, this is what we see:

Simple share sheet

And that works great for text, but what if we wanted to share an image?

let image: UIImage = getImage()
let activityViewController = UIActivityViewController(activityItems: [image], applicationActivities: nil)

currentViewController.present(activityViewController, animated: true, completion: nil)

Broken thumbnail

It works great, but looks a little plain. It is possible to customise the Share Sheet with a title, description and thumbnail though, by passing the controller an instance of UIActivityItemProvider instead of just raw data:

class ShareImage: UIActivityItemProvider {
  var image: UIImage

  override var item: Any {
    get {
      return self.image
    }
  }

  override init(placeholderItem: Any) {
    guard let image = placeholderItem as? UIImage else {
      fatalError("Couldn't create image from provided item")
    }

    self.image = image
    super.init(placeholderItem: placeholderItem)
  }

  @available(iOS 13.0, *)
  override func activityViewControllerLinkMetadata(_ activityViewController: UIActivityViewController) -> LPLinkMetadata? {

    let metadata = LPLinkMetadata()
    metadata.title = "1 Image"

    var thumbnail: NSSecureCoding = NSNull()
    if let imageData = self.image.pngData() {
      thumbnail = NSData(data: imageData)
    }

    metadata.imageProvider = NSItemProvider(item: thumbnail, typeIdentifier: "public.png")

    return metadata
  }

}

...

let image: UIImage = getImage()
let item = ShareImage(placeholderItem: image)
let activityViewController = UIActivityViewController(activityItems: [item], applicationActivities: nil)

currentViewController.present(activityViewController, animated: true, completion: nil)

Finished product

And there you have it! It is also possible to send multiple data objects to the Share Sheet, or specify which apps can access the data using the applicationActivities parameter.

Android

I've found that doing this on Android is more complex than on iOS, mainly due to how Android deals with file permissions. Basically, you have to set the permissions of the file you want to share manually, whereas in iOS it was handled automatically.

In android, you need to designate the class you are going to be calling from as a FileProvider, and specifying which files it is allowed to access. You do this by specifying the class in the AndroidManifest.xml file:

<activity name=".MainActivity">
  <provider
    android:authorities="com.package.ClassName"
    android:exported="false"
    android:grantUriPermissions="true"
    android:name="androidx.core.content.FileProvider">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"  />
</provider>

And then creating a new directory called xml and a file in it called file_paths:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images/"/>
</paths>

Note that you might need to use a different tag than files-path depending on where your files are stored. If you are using temp files, you might need to use cache-path. For a full list of what you might need, see the android docs here

Now, inside the class that we specified in the provider above:

File file = getFile()
Uri uri = FileProvider.getUriForFile(getContext(), this.getClass().getName(), file);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.setType("MIME_TYPE_OF_FILE");

Intent shareIntent = Intent.createChooser(intent, "Share File");
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);

startActivity(shareIntent);

Android share sheet

Executing that will open up the Share Sheet and send your file on it's merry way. I haven't found a consistent way to customise the Share Sheet on Android like we did earlier on iOS, but if I do, I'll update this post.

Top comments (0)