---
description: Capacitor plugin to receive content such as text, links, and files from other apps. Available for Android, iOS, and Web.
title: Capacitor Share Target Plugin for Android, iOS & Web - Capawesome
image: https://capawesome.io/docs/assets/images/social/sdks/capacitor/share-target.png
---

<!doctype html> 

[Skip to content ](#capacitor-share-target-plugin) 

[🖥️ Introducing the **Capacitor Electron Platform** — build desktop apps for macOS, Windows, and Linux. Free & open source. ](/blog/announcing-the-capacitor-electron-platform/) 

* [ SDKs ](/docs/sdks/)
* [ Formbricks ](/docs/sdks/capacitor/formbricks/)
* [ Geocoder ](/docs/sdks/capacitor/geocoder/)
* [ Google Sign-In ](/docs/sdks/capacitor/google-sign-in/)
* [ Grafana Faro ](/docs/sdks/capacitor/grafana-faro/)
* [ Gyroscope ](/docs/sdks/capacitor/gyroscope/)
* [ Haptics ](/docs/sdks/capacitor/haptics/)
* [ Home Indicator ](/docs/sdks/capacitor/home-indicator/)
* [ In-App Browser ](/docs/sdks/capacitor/in-app-browser/)
* [ Install Referrer ](/docs/sdks/capacitor/install-referrer/)
* [ Intercom ](/docs/sdks/capacitor/intercom/)
* [ Intune ](/docs/sdks/capacitor/intune/)
* [ Keep Awake ](/docs/sdks/capacitor/keep-awake/)
* [ libSQL ](/docs/sdks/capacitor/libsql/)
* [ Light Sensor ](/docs/sdks/capacitor/light-sensor/)
* [ Live Update ](/docs/sdks/capacitor/live-update/)
* [ Localization ](/docs/sdks/capacitor/localization/)
* [ Mail Composer ](/docs/sdks/capacitor/mail-composer/)
* [ Managed Configurations ](/docs/sdks/capacitor/managed-configurations/)
* [ Maps Launcher ](/docs/sdks/capacitor/maps-launcher/)
* [ Media Session ](/docs/sdks/capacitor/media-session/)
* [ ML Kit ](/docs/sdks/capacitor/mlkit/)
* [ Navigation Bar ](/docs/sdks/capacitor/navigation-bar/)
* [ Network ](/docs/sdks/capacitor/network/)
* [ NFC ](/docs/sdks/capacitor/nfc/)
* [ Node.js ](/docs/sdks/capacitor/nodejs/)
* [ OAuth ](/docs/sdks/capacitor/oauth/)
* [ Passkeys ](/docs/sdks/capacitor/passkeys/)
* [ Password Autofill ](/docs/sdks/capacitor/password-autofill/)
* [ PDF Generator ](/docs/sdks/capacitor/pdf-generator/)
* [ PDF Viewer ](/docs/sdks/capacitor/pdf-viewer/)
* [ Pedometer ](/docs/sdks/capacitor/pedometer/)
* [ Permissions ](/docs/sdks/capacitor/permissions/)
* [ Phone Dialer ](/docs/sdks/capacitor/phone-dialer/)
* [ Photo Editor ](/docs/sdks/capacitor/photo-editor/)
* [ Photo Manipulator ](/docs/sdks/capacitor/photo-manipulator/)
* [ PixLive ](/docs/sdks/capacitor/pixlive/)
* [ PostHog ](/docs/sdks/capacitor/posthog/)
* [ Printer ](/docs/sdks/capacitor/printer/)
* [ Privacy Screen ](/docs/sdks/capacitor/privacy-screen/)
* [ Proximity Sensor ](/docs/sdks/capacitor/proximity-sensor/)
* [ Purchases ](/docs/sdks/capacitor/purchases/)
* [ RealtimeKit ](/docs/sdks/capacitor/realtimekit/)
* [ Root Detection ](/docs/sdks/capacitor/root-detection/)
* [ Screen Brightness ](/docs/sdks/capacitor/screen-brightness/)
* [ Screen Orientation ](/docs/sdks/capacitor/screen-orientation/)
* [ Screen Reader ](/docs/sdks/capacitor/screen-reader/)
* [ Screenshot ](/docs/sdks/capacitor/screenshot/)
* [ Secure Preferences ](/docs/sdks/capacitor/secure-preferences/)
* [ Settings Launcher ](/docs/sdks/capacitor/settings-launcher/)
* [ Shake ](/docs/sdks/capacitor/shake/)
* [ Silent Mode ](/docs/sdks/capacitor/silent-mode/)
* [ SIM ](/docs/sdks/capacitor/sim/)
* [ SMS Composer ](/docs/sdks/capacitor/sms-composer/)
* [ Speech Recognition ](/docs/sdks/capacitor/speech-recognition/)
* [ Speech Synthesis ](/docs/sdks/capacitor/speech-synthesis/)
* Share Target [ Share Target ](/docs/sdks/capacitor/share-target/)
* [ iOS ](#ios)
* [ Configuration ](#configuration)
* [ Web ](#web)
* [ Usage ](#usage)
* [ API ](#api)
* [ Troubleshooting ](#troubleshooting)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ Breaking Changes ](#breaking-changes)
* [ License ](#license)
* [ Square Mobile Payments ](/docs/sdks/capacitor/square-mobile-payments/)
* [ SQLite ](/docs/sdks/capacitor/sqlite/)
* [ Superwall ](/docs/sdks/capacitor/superwall/)
* [ System WebView ](/docs/sdks/capacitor/system-webview/)
* [ Tauri ](/docs/sdks/capacitor/tauri/)
* [ Text Interaction ](/docs/sdks/capacitor/text-interaction/)
* [ Text Zoom ](/docs/sdks/capacitor/text-zoom/)
* [ Thermal State ](/docs/sdks/capacitor/thermal-state/)
* [ Toast ](/docs/sdks/capacitor/toast/)
* [ Torch ](/docs/sdks/capacitor/torch/)
* [ Vault ](/docs/sdks/capacitor/vault/)
* [ Volume ](/docs/sdks/capacitor/volume/)
* [ Wallet ](/docs/sdks/capacitor/wallet/)
* [ Wifi ](/docs/sdks/capacitor/wifi/)
* [ YouTube Player ](/docs/sdks/capacitor/youtube-player/)
* [ Zip ](/docs/sdks/capacitor/zip/)
* [ Cordova ](/docs/sdks/cordova/)
* [ Cloud ](/docs/cloud/)
* [ Integrations ](/docs/cloud/live-updates/integrations/)
* Concepts
* Reference
* [ Troubleshooting ](/docs/cloud/live-updates/troubleshooting/)
* [ FAQ ](/docs/cloud/live-updates/faq/)
* [ Native Builds ](/docs/cloud/native-builds/)
* [ Set Up Environments ](/docs/cloud/native-builds/environments/)
* [ Overwrite Native Configurations ](/docs/cloud/native-builds/native-configurations/)
* [ Auto-Increment Build Numbers ](/docs/cloud/native-builds/auto-incrementing-build-numbers/)
* [ Configure the Web Build Script ](/docs/cloud/native-builds/web-build-script/)
* [ Build from a Monorepo ](/docs/cloud/native-builds/monorepo/)
* [ Use pnpm, Yarn, or bun ](/docs/cloud/native-builds/package-managers/)
* [ Install Private npm Packages ](/docs/cloud/native-builds/npm-private-registry/)
* [ Override the Java Version ](/docs/cloud/native-builds/override-java-version/)
* [ Custom iOS Provisioning Profiles ](/docs/cloud/native-builds/custom-ios-provisioning-profiles/)
* [ Build without Git ](/docs/cloud/native-builds/build-without-git/)
* [ Access Git Behind a Firewall ](/docs/cloud/native-builds/firewall-access/)
* [ Integrations ](/docs/cloud/native-builds/integrations/)
* Reference
* [ Troubleshooting ](/docs/cloud/native-builds/troubleshooting/)
* [ FAQ ](/docs/cloud/native-builds/faq/)
* [ App Store Publishing ](/docs/cloud/app-store-publishing/)
* [ Submit a Build ](/docs/cloud/app-store-publishing/submit-a-build/)
* [ Submit Automatically After a Build ](/docs/cloud/app-store-publishing/submit-automatically/)
* [ Troubleshooting ](/docs/cloud/app-store-publishing/troubleshooting/)
* [ FAQ ](/docs/cloud/app-store-publishing/faq/)
* [ Automations ](/docs/cloud/automations/)
* [ Reference ](/docs/cloud/automations/reference/)
* [ Troubleshooting ](/docs/cloud/automations/troubleshooting/)
* [ FAQ ](/docs/cloud/automations/faq/)
* [ Assist ](/docs/cloud/assist/)
* [ CLI ](/docs/cloud/cli/)
* APIs and SDKs
* [ Webhooks ](/docs/cloud/webhooks/)
* [ Integrations ](/docs/cloud/integrations/)
* Account
* [ Organization ](/docs/cloud/organizations/)
* [ Two-Factor Enforcement ](/docs/cloud/organizations/two-factor-authentication/)
* [ Audit Logs ](/docs/cloud/organizations/audit-logs/)
* [ Billing ](/docs/cloud/organizations/billing/)
* [ License Keys ](/docs/cloud/license-keys/)
* [ AI ](/docs/ai/)
* [ Insiders ](/docs/insiders/)
* [ Billing & Plans ](/docs/insiders/billing-and-plans/)
* [ FAQ ](/docs/insiders/faq/)
* [ License ](https://capawesome.io/legal/eula/)
* [ Support ](/docs/support/)
* [ Contributing ](/docs/contributing/)
* Contributing code
* [ Code of Conduct ](/docs/contributing/code-of-conduct/)
* [ Questions ](https://docs.github.com/en/discussions/collaborating-with-your-community-using-discussions/participating-in-a-discussion#creating-a-discussion)
* [ Blog ](/blog/)
* Categories

* [ iOS ](#ios)
* [ Configuration ](#configuration)
* [ Web ](#web)
* [ Usage ](#usage)
* [ API ](#api)
* [ Troubleshooting ](#troubleshooting)
* [ FAQ ](#faq)
* [ Related Plugins ](#related-plugins)
* [ Newsletter ](#newsletter)
* [ Changelog ](#changelog)
* [ Breaking Changes ](#breaking-changes)
* [ License ](#license)

# Capacitor Share Target Plugin[¶](#capacitor-share-target-plugin "Permanent link")

Capacitor plugin to receive content such as text, links, and files from other apps.

[ ![Deliver Live Updates to your Capacitor app with Capawesome Cloud](../../../assets/external/cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.69628c3f.png) ](https://cloud.capawesome.io/) 

## Features[¶](#features "Permanent link")

The Capacitor Share Target plugin is one of the most complete solutions for receiving shared content in Capacitor apps. Here are some of the key features:

* 🖥️ **Cross-platform**: Supports Android, iOS and Web.
* 📝 **Multi-content types**: Handle text, URLs, images, videos, and files.
* 🌐 **Web Share Target API**: Leverage the native sharing capabilities of the web.
* 📦 **Large File Support**: Efficient file caching without memory limitations.
* 🤝 **Compatibility**: Works alongside the [Android Intent Launcher](https://capawesome.io/docs/sdks/capacitor/android-intent-launcher/), [Clipboard](https://capawesome.io/docs/sdks/capacitor/clipboard/) and [File Opener](https://capawesome.io/docs/sdks/capacitor/file-opener/) plugins.
* 📦 **CocoaPods & SPM**: Supports CocoaPods and Swift Package Manager for iOS.
* 🔁 **Up-to-date**: Always supports the latest Capacitor version.
* ⭐️ **Support**: Priority support from the Capawesome Team.
* ✨ **Handcrafted**: Built from the ground up with care and expertise, not forked or AI-generated.

Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!

## Use Cases[¶](#use-cases "Permanent link")

The Share Target plugin is typically used whenever an app wants to appear in the share sheet of the operating system, for example:

* **Media imports**: Receive images and videos shared from the gallery or other apps.
* **Save-for-later apps**: Receive links and text shared from browsers or social media apps, for example in a bookmarking or note-taking app.
* **File handling**: Receive documents such as PDFs shared from other apps for further processing.
* **PWA share target**: Let your Progressive Web App receive shared content via the Web Share Target API.

## Compatibility[¶](#compatibility "Permanent link")

| Plugin Version | Capacitor Version | Status         |
| -------------- | ----------------- | -------------- |
| 8.x.x          | \>=8.x.x          | Active support |
| 0.2.x          | 7.x.x             | Deprecated     |

## Demo[¶](#demo "Permanent link")

A working example can be found [here](https://github.com/capawesome-team/capacitor-share-target-demo).

| Android                                                                                           | iOS                                                                                       | Web                                                                                       |
| ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| ![Android Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-share-target-android.gif) | ![iOS Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-share-target-ios.gif) | ![Web Demo](https://capawesome.io/docs/assets/images/gifs/capacitor-share-target-web.gif) |

## Installation[¶](#installation "Permanent link")

This plugin is only available to [Capawesome Insiders](https://capawesome.io/insiders/). First, make sure you have the Capawesome npm registry set up. You can do this by running the following commands:

`[](#%5F%5Fcodelineno-0-1)npm config set @capawesome-team:registry https://npm.registry.capawesome.io
[](#%5F%5Fcodelineno-0-2)npm config set //npm.registry.capawesome.io/:_authToken <YOUR_LICENSE_KEY>
`

**Attention**: Replace `<YOUR_LICENSE_KEY>` with the license key you received from Polar. If you don't have a license key yet, you can get one by becoming a [Capawesome Insider](https://capawesome.io/insiders/).

Next, you can use our **AI-Assisted Setup** to install the plugin. Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:

`[](#%5F%5Fcodelineno-1-1)npx skills add capawesome-team/skills --skill capacitor-plugins
`

Then use the following prompt:

`` [](#%5F%5Fcodelineno-2-1)Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome-team/capacitor-share-target` plugin in my project.
 ``

If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:

`[](#%5F%5Fcodelineno-3-1)npm install @capawesome-team/capacitor-share-target
[](#%5F%5Fcodelineno-3-2)npx cap sync
`

### Android[¶](#android "Permanent link")

#### Intent Filters[¶](#intent-filters "Permanent link")

To enable your app to receive shared content from other apps, you need to add intent filters to your main activity in `AndroidManifest.xml` (usually `android/app/src/main/AndroidManifest.xml`).

For example, to handle text, URLs, and other text-based content, add the following intent filter:

`[](#%5F%5Fcodelineno-4-1)<intent-filter>
[](#%5F%5Fcodelineno-4-2)    <action android:name="android.intent.action.SEND" />
[](#%5F%5Fcodelineno-4-3)    <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-4-4)    <data android:mimeType="text/plain" />
[](#%5F%5Fcodelineno-4-5)</intent-filter>
`

To handle a single image, add the following intent filter:

`[](#%5F%5Fcodelineno-5-1)<intent-filter>
[](#%5F%5Fcodelineno-5-2)    <action android:name="android.intent.action.SEND" />
[](#%5F%5Fcodelineno-5-3)    <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-5-4)    <data android:mimeType="image/*" />
[](#%5F%5Fcodelineno-5-5)</intent-filter>
`

To handle multiple images, add the following intent filter:

`[](#%5F%5Fcodelineno-6-1)<intent-filter>
[](#%5F%5Fcodelineno-6-2)    <action android:name="android.intent.action.SEND_MULTIPLE" />
[](#%5F%5Fcodelineno-6-3)    <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-6-4)    <data android:mimeType="image/*" />
[](#%5F%5Fcodelineno-6-5)</intent-filter>
`

You can also add additional intent filters for other MIME types as needed, such as `application/pdf` for PDF files or `video/*` for videos.

**Attention**: Make sure to add these intent filters inside the `<activity>` tag of your main activity, typically `MainActivity`. Also, make sure the activity has the `android:exported="true"` attribute set, which allows other apps to send intents to it. The `android:launchMode="singleTask"` attribute is recommended to prevent multiple instances of your app from being created when receiving shared content.

Here's an example of how your `AndroidManifest.xml` might look like:

`[](#%5F%5Fcodelineno-7-1)<activity
[](#%5F%5Fcodelineno-7-2)    android:name=".MainActivity"
[](#%5F%5Fcodelineno-7-3)    android:exported="true"
[](#%5F%5Fcodelineno-7-4)    android:launchMode="singleTask">
[](#%5F%5Fcodelineno-7-5)    <intent-filter>
[](#%5F%5Fcodelineno-7-6)        <action android:name="android.intent.action.SEND" />
[](#%5F%5Fcodelineno-7-7)        <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-7-8)        <data android:mimeType="text/plain" />
[](#%5F%5Fcodelineno-7-9)    </intent-filter>
[](#%5F%5Fcodelineno-7-10)    <intent-filter>
[](#%5F%5Fcodelineno-7-11)        <action android:name="android.intent.action.SEND" />
[](#%5F%5Fcodelineno-7-12)        <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-7-13)        <data android:mimeType="image/*" />
[](#%5F%5Fcodelineno-7-14)    </intent-filter>
[](#%5F%5Fcodelineno-7-15)    <intent-filter>
[](#%5F%5Fcodelineno-7-16)        <action android:name="android.intent.action.SEND" />
[](#%5F%5Fcodelineno-7-17)        <category android:name="android.intent.category.DEFAULT" />
[](#%5F%5Fcodelineno-7-18)        <data android:mimeType="video/*" />
[](#%5F%5Fcodelineno-7-19)    </intent-filter>
[](#%5F%5Fcodelineno-7-20)</activity>
`

#### Proguard[¶](#proguard "Permanent link")

If you are using Proguard, you need to add the following rules to your `proguard-rules.pro` file:

`[](#%5F%5Fcodelineno-8-1)-keep class io.capawesome.capacitorjs.plugins.** { *; }
`

#### Variables[¶](#variables "Permanent link")

If needed, you can define the following project variable in your app's `variables.gradle` file to change the default version of the dependency:

* `$androidxExifInterfaceVersion` version of `androidx.exifinterface:exifinterface` (default: `1.4.2`)

This can be useful if you encounter dependency conflicts with other plugins in your project.

### iOS[¶](#ios "Permanent link")

On iOS, it's not possible to receive shared content directly in the main app. Instead, you need to create a share extension that can handle the shared content and then communicate it back to your main app. This involves setting up a URL scheme and configuring the share extension to handle the shared content. The communication between the share extension and the main app is done using URL schemes, which allows the share extension to open the main app with the shared content as parameters in the URL.

#### URL Scheme[¶](#url-scheme "Permanent link")

To enable your app to be opened by the share extension, you need to set up a URL scheme in your iOS app. This is done by adding a URL type in your app's `Info.plist` file. Add the following code to your `Info.plist` file:

`[](#%5F%5Fcodelineno-9-1)<key>CFBundleURLTypes</key>
[](#%5F%5Fcodelineno-9-2)<array>
[](#%5F%5Fcodelineno-9-3)    <dict>
[](#%5F%5Fcodelineno-9-4)        <key>CFBundleURLSchemes</key>
[](#%5F%5Fcodelineno-9-5)        <array>
[](#%5F%5Fcodelineno-9-6)            <string>YOUR_URL_SCHEME</string>
[](#%5F%5Fcodelineno-9-7)        </array>
[](#%5F%5Fcodelineno-9-8)    </dict>
[](#%5F%5Fcodelineno-9-9)</array>
`

**Attention**: Replace `YOUR_URL_SCHEME` with your desired URL scheme (e.g. `myapp`). This will allow your app to be opened with URLs like `myapp://?text=Hello%20World`.

#### Share Extension[¶](#share-extension "Permanent link")

To enable your app to receive shared content from other apps on iOS, you need to create a share extension. First, you need to add a new target to your Xcode project:

1. Open your Xcode project.
2. Go to `File` \> `New` \> `Target...`.
3. Select `Share Extension` from the list of templates.
4. Name your extension `AppShare` and click `Finish`.

This will create a new target in your Xcode project with the necessary files for a share extension. If you see a prompt to activate the new scheme, choose "Don't Activate". There is one file called `MainInterface.storyboard` that you should delete **via Xcode**, as we will not need it.

After this, you need to configure the share extension to handle the shared content. Open the `Info.plist` file of your share extension **in a text editor of your choice** and replace its content with the following:

`[](#%5F%5Fcodelineno-10-1)<?xml version="1.0" encoding="UTF-8"?>
[](#%5F%5Fcodelineno-10-2)<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
[](#%5F%5Fcodelineno-10-3)<plist version="1.0">
[](#%5F%5Fcodelineno-10-4)<dict>
[](#%5F%5Fcodelineno-10-5)    <key>NSExtension</key>
[](#%5F%5Fcodelineno-10-6)    <dict>
[](#%5F%5Fcodelineno-10-7)        <key>NSExtensionAttributes</key>
[](#%5F%5Fcodelineno-10-8)        <dict>
[](#%5F%5Fcodelineno-10-9)            <key>NSExtensionActivationRule</key>
[](#%5F%5Fcodelineno-10-10)            <dict>
[](#%5F%5Fcodelineno-10-11)                <key>NSExtensionActivationDictionaryVersion</key>
[](#%5F%5Fcodelineno-10-12)                <integer>2</integer>
[](#%5F%5Fcodelineno-10-13)                <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
[](#%5F%5Fcodelineno-10-14)                <integer>1</integer>
[](#%5F%5Fcodelineno-10-15)                <key>NSExtensionActivationSupportsText</key>
[](#%5F%5Fcodelineno-10-16)                <true/>
[](#%5F%5Fcodelineno-10-17)                <key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
[](#%5F%5Fcodelineno-10-18)                <integer>10</integer>
[](#%5F%5Fcodelineno-10-19)                <key>NSExtensionActivationSupportsFileWithMaxCount</key>
[](#%5F%5Fcodelineno-10-20)                <integer>10</integer>
[](#%5F%5Fcodelineno-10-21)                <key>NSExtensionActivationSupportsImageWithMaxCount</key>
[](#%5F%5Fcodelineno-10-22)                <integer>10</integer>
[](#%5F%5Fcodelineno-10-23)                <key>NSExtensionActivationSupportsMovieWithMaxCount</key>
[](#%5F%5Fcodelineno-10-24)                <integer>10</integer>
[](#%5F%5Fcodelineno-10-25)                <key>NSExtensionActivationSupportsWebPageWithMaxCount</key>
[](#%5F%5Fcodelineno-10-26)                <integer>1</integer>
[](#%5F%5Fcodelineno-10-27)            </dict>
[](#%5F%5Fcodelineno-10-28)        </dict>
[](#%5F%5Fcodelineno-10-29)        <key>NSExtensionPrincipalClass</key>
[](#%5F%5Fcodelineno-10-30)        <string>AppShare.ShareViewController</string>
[](#%5F%5Fcodelineno-10-31)        <key>NSExtensionPointIdentifier</key>
[](#%5F%5Fcodelineno-10-32)        <string>com.apple.share-services</string>
[](#%5F%5Fcodelineno-10-33)    </dict>
[](#%5F%5Fcodelineno-10-34)</dict>
[](#%5F%5Fcodelineno-10-35)</plist>
`

Feel free to adjust the `NSExtensionActivationRule` keys to match the types of content you want to support. The example above supports text, web URLs, files, images, and movies.

Next, you need to update the `ShareViewController.swift` file in your share extension target and replace its content with the following code:

`[](#%5F%5Fcodelineno-11-1)import MobileCoreServices
[](#%5F%5Fcodelineno-11-2)import Social
[](#%5F%5Fcodelineno-11-3)import UIKit
[](#%5F%5Fcodelineno-11-4)import UniformTypeIdentifiers
[](#%5F%5Fcodelineno-11-5)
[](#%5F%5Fcodelineno-11-6)struct SharedFileData {
[](#%5F%5Fcodelineno-11-7)    let uri: String
[](#%5F%5Fcodelineno-11-8)    let name: String?
[](#%5F%5Fcodelineno-11-9)    let mimeType: String?
[](#%5F%5Fcodelineno-11-10)}
[](#%5F%5Fcodelineno-11-11)
[](#%5F%5Fcodelineno-11-12)class ShareViewController: UIViewController {
[](#%5F%5Fcodelineno-11-13)    private let appGroupIdentifier = "group.<YOUR_APP_IDENTIFIER>"
[](#%5F%5Fcodelineno-11-14)    private let urlScheme = "<YOUR_URL_SCHEME>"
[](#%5F%5Fcodelineno-11-15)
[](#%5F%5Fcodelineno-11-16)    override func viewDidAppear(_ animated: Bool) {
[](#%5F%5Fcodelineno-11-17)        super.viewDidAppear(animated)
[](#%5F%5Fcodelineno-11-18)        self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
[](#%5F%5Fcodelineno-11-19)    }
[](#%5F%5Fcodelineno-11-20)
[](#%5F%5Fcodelineno-11-21)    override func viewDidLoad() {
[](#%5F%5Fcodelineno-11-22)        super.viewDidLoad()
[](#%5F%5Fcodelineno-11-23)        Task {
[](#%5F%5Fcodelineno-11-24)            processSharedContent()
[](#%5F%5Fcodelineno-11-25)        }
[](#%5F%5Fcodelineno-11-26)    }
[](#%5F%5Fcodelineno-11-27)
[](#%5F%5Fcodelineno-11-28)    private func openURL(_ url: URL) {
[](#%5F%5Fcodelineno-11-29)        var responder: UIResponder? = self
[](#%5F%5Fcodelineno-11-30)        while responder != nil {
[](#%5F%5Fcodelineno-11-31)            if let application = responder as? UIApplication {
[](#%5F%5Fcodelineno-11-32)                application.open(url, options: [:], completionHandler: nil)
[](#%5F%5Fcodelineno-11-33)                return
[](#%5F%5Fcodelineno-11-34)            }
[](#%5F%5Fcodelineno-11-35)            responder = responder?.next
[](#%5F%5Fcodelineno-11-36)        }
[](#%5F%5Fcodelineno-11-37)    }
[](#%5F%5Fcodelineno-11-38)
[](#%5F%5Fcodelineno-11-39)    private func sharedContainerURL(for fileName: String) -> URL? {
[](#%5F%5Fcodelineno-11-40)        guard let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) else {
[](#%5F%5Fcodelineno-11-41)            return nil
[](#%5F%5Fcodelineno-11-42)        }
[](#%5F%5Fcodelineno-11-43)        return containerURL.appendingPathComponent(fileName)
[](#%5F%5Fcodelineno-11-44)    }
[](#%5F%5Fcodelineno-11-45)
[](#%5F%5Fcodelineno-11-46)    private func removeFileIfExists(at url: URL) throws {
[](#%5F%5Fcodelineno-11-47)        if FileManager.default.fileExists(atPath: url.path) {
[](#%5F%5Fcodelineno-11-48)            try FileManager.default.removeItem(at: url)
[](#%5F%5Fcodelineno-11-49)        }
[](#%5F%5Fcodelineno-11-50)    }
[](#%5F%5Fcodelineno-11-51)
[](#%5F%5Fcodelineno-11-52)    private func copyFileToSharedContainer(_ sourceURL: URL) -> String? {
[](#%5F%5Fcodelineno-11-53)        let fileName = sourceURL.lastPathComponent
[](#%5F%5Fcodelineno-11-54)        guard let destinationURL = sharedContainerURL(for: fileName) else {
[](#%5F%5Fcodelineno-11-55)            return nil
[](#%5F%5Fcodelineno-11-56)        }
[](#%5F%5Fcodelineno-11-57)
[](#%5F%5Fcodelineno-11-58)        do {
[](#%5F%5Fcodelineno-11-59)            try removeFileIfExists(at: destinationURL)
[](#%5F%5Fcodelineno-11-60)            try FileManager.default.copyItem(at: sourceURL, to: destinationURL)
[](#%5F%5Fcodelineno-11-61)            return destinationURL.absoluteString
[](#%5F%5Fcodelineno-11-62)        } catch {
[](#%5F%5Fcodelineno-11-63)            print("Error copying file to shared container: \(error)")
[](#%5F%5Fcodelineno-11-64)            return nil
[](#%5F%5Fcodelineno-11-65)        }
[](#%5F%5Fcodelineno-11-66)    }
[](#%5F%5Fcodelineno-11-67)
[](#%5F%5Fcodelineno-11-68)    private func copyImageToSharedContainerWithFixedOrientation(_ sourceURL: URL) -> String? {
[](#%5F%5Fcodelineno-11-69)        let fileName = sourceURL.lastPathComponent
[](#%5F%5Fcodelineno-11-70)        guard let destinationURL = sharedContainerURL(for: fileName) else {
[](#%5F%5Fcodelineno-11-71)            return nil
[](#%5F%5Fcodelineno-11-72)        }
[](#%5F%5Fcodelineno-11-73)
[](#%5F%5Fcodelineno-11-74)        do {
[](#%5F%5Fcodelineno-11-75)            try removeFileIfExists(at: destinationURL)
[](#%5F%5Fcodelineno-11-76)
[](#%5F%5Fcodelineno-11-77)            if let fixedImageData = loadImageDataWithFixedOrientation(from: sourceURL) {
[](#%5F%5Fcodelineno-11-78)                try fixedImageData.write(to: destinationURL)
[](#%5F%5Fcodelineno-11-79)            } else {
[](#%5F%5Fcodelineno-11-80)                try FileManager.default.copyItem(at: sourceURL, to: destinationURL)
[](#%5F%5Fcodelineno-11-81)            }
[](#%5F%5Fcodelineno-11-82)
[](#%5F%5Fcodelineno-11-83)            return destinationURL.absoluteString
[](#%5F%5Fcodelineno-11-84)        } catch {
[](#%5F%5Fcodelineno-11-85)            print("Error copying image to shared container: \(error)")
[](#%5F%5Fcodelineno-11-86)            return nil
[](#%5F%5Fcodelineno-11-87)        }
[](#%5F%5Fcodelineno-11-88)    }
[](#%5F%5Fcodelineno-11-89)
[](#%5F%5Fcodelineno-11-90)    private func loadImageDataWithFixedOrientation(from url: URL) -> Data? {
[](#%5F%5Fcodelineno-11-91)        guard let source = CGImageSourceCreateWithURL(url as CFURL, nil),
[](#%5F%5Fcodelineno-11-92)              let cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil) else {
[](#%5F%5Fcodelineno-11-93)            return nil
[](#%5F%5Fcodelineno-11-94)        }
[](#%5F%5Fcodelineno-11-95)
[](#%5F%5Fcodelineno-11-96)        let uiImage = UIImage(cgImage: cgImage)
[](#%5F%5Fcodelineno-11-97)        let fixedImage = normalizeImageOrientation(uiImage)
[](#%5F%5Fcodelineno-11-98)
[](#%5F%5Fcodelineno-11-99)        let fileExtension = url.pathExtension.lowercased()
[](#%5F%5Fcodelineno-11-100)        if fileExtension == "jpg" || fileExtension == "jpeg" {
[](#%5F%5Fcodelineno-11-101)            return fixedImage.jpegData(compressionQuality: 0.9)
[](#%5F%5Fcodelineno-11-102)        } else {
[](#%5F%5Fcodelineno-11-103)            return fixedImage.pngData()
[](#%5F%5Fcodelineno-11-104)        }
[](#%5F%5Fcodelineno-11-105)    }
[](#%5F%5Fcodelineno-11-106)
[](#%5F%5Fcodelineno-11-107)
[](#%5F%5Fcodelineno-11-108)
[](#%5F%5Fcodelineno-11-109)    private func normalizeImageOrientation(_ image: UIImage) -> UIImage {
[](#%5F%5Fcodelineno-11-110)        if let fixedImage = image.fixedOrientation() {
[](#%5F%5Fcodelineno-11-111)            return fixedImage
[](#%5F%5Fcodelineno-11-112)        }
[](#%5F%5Fcodelineno-11-113)
[](#%5F%5Fcodelineno-11-114)        return image
[](#%5F%5Fcodelineno-11-115)    }
[](#%5F%5Fcodelineno-11-116)
[](#%5F%5Fcodelineno-11-117)    private func extractFileMetadata(from url: URL) -> (name: String, mimeType: String?) {
[](#%5F%5Fcodelineno-11-118)        let fileName = url.lastPathComponent
[](#%5F%5Fcodelineno-11-119)        let mimeType = getMimeType(from: url)
[](#%5F%5Fcodelineno-11-120)        return (fileName, mimeType.isEmpty ? nil : mimeType)
[](#%5F%5Fcodelineno-11-121)    }
[](#%5F%5Fcodelineno-11-122)
[](#%5F%5Fcodelineno-11-123)    private func getMimeType(from url: URL) -> String {
[](#%5F%5Fcodelineno-11-124)        let fileExtension = url.pathExtension as CFString
[](#%5F%5Fcodelineno-11-125)        guard let extUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, nil)?.takeUnretainedValue() else {
[](#%5F%5Fcodelineno-11-126)            return ""
[](#%5F%5Fcodelineno-11-127)        }
[](#%5F%5Fcodelineno-11-128)        guard let mimeUTI = UTTypeCopyPreferredTagWithClass(extUTI, kUTTagClassMIMEType) else {
[](#%5F%5Fcodelineno-11-129)            return ""
[](#%5F%5Fcodelineno-11-130)        }
[](#%5F%5Fcodelineno-11-131)        return mimeUTI.takeRetainedValue() as String
[](#%5F%5Fcodelineno-11-132)    }
[](#%5F%5Fcodelineno-11-133)
[](#%5F%5Fcodelineno-11-134)    private func buildAppURL(textValues: [String], fileValues: [SharedFileData], title: String) -> URL {
[](#%5F%5Fcodelineno-11-135)        var urlComponents = URLComponents(string: "\(urlScheme)://?")!
[](#%5F%5Fcodelineno-11-136)        var queryItems: [URLQueryItem] = []
[](#%5F%5Fcodelineno-11-137)
[](#%5F%5Fcodelineno-11-138)        if !title.isEmpty {
[](#%5F%5Fcodelineno-11-139)            queryItems.append(URLQueryItem(name: "title", value: title))
[](#%5F%5Fcodelineno-11-140)        }
[](#%5F%5Fcodelineno-11-141)
[](#%5F%5Fcodelineno-11-142)        queryItems.append(contentsOf: textValues.filter { !$0.isEmpty }.map {
[](#%5F%5Fcodelineno-11-143)            URLQueryItem(name: "text", value: $0)
[](#%5F%5Fcodelineno-11-144)        })
[](#%5F%5Fcodelineno-11-145)
[](#%5F%5Fcodelineno-11-146)        for (index, file) in fileValues.enumerated() {
[](#%5F%5Fcodelineno-11-147)            queryItems.append(URLQueryItem(name: "fileUri\(index)", value: file.uri))
[](#%5F%5Fcodelineno-11-148)            if let name = file.name {
[](#%5F%5Fcodelineno-11-149)                queryItems.append(URLQueryItem(name: "fileName\(index)", value: name))
[](#%5F%5Fcodelineno-11-150)            }
[](#%5F%5Fcodelineno-11-151)            if let mimeType = file.mimeType {
[](#%5F%5Fcodelineno-11-152)                queryItems.append(URLQueryItem(name: "fileMimeType\(index)", value: mimeType))
[](#%5F%5Fcodelineno-11-153)            }
[](#%5F%5Fcodelineno-11-154)        }
[](#%5F%5Fcodelineno-11-155)
[](#%5F%5Fcodelineno-11-156)        urlComponents.queryItems = queryItems.isEmpty ? nil : queryItems
[](#%5F%5Fcodelineno-11-157)        return urlComponents.url!
[](#%5F%5Fcodelineno-11-158)    }
[](#%5F%5Fcodelineno-11-159)
[](#%5F%5Fcodelineno-11-160)    private func sendData(with textValues: [String], fileValues: [SharedFileData], title: String) {
[](#%5F%5Fcodelineno-11-161)        let url = buildAppURL(textValues: textValues, fileValues: fileValues, title: title)
[](#%5F%5Fcodelineno-11-162)        openURL(url)
[](#%5F%5Fcodelineno-11-163)    }
[](#%5F%5Fcodelineno-11-164)
[](#%5F%5Fcodelineno-11-165)    private func processImageAttachment(_ attachment: NSItemProvider, dispatchGroup: DispatchGroup, completion: @escaping (SharedFileData?) -> Void) {
[](#%5F%5Fcodelineno-11-166)        dispatchGroup.enter()
[](#%5F%5Fcodelineno-11-167)        attachment.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { [weak self] (item, _) in
[](#%5F%5Fcodelineno-11-168)            defer { dispatchGroup.leave() }
[](#%5F%5Fcodelineno-11-169)            guard let self = self else { 
[](#%5F%5Fcodelineno-11-170)                completion(nil)
[](#%5F%5Fcodelineno-11-171)                return 
[](#%5F%5Fcodelineno-11-172)            }
[](#%5F%5Fcodelineno-11-173)
[](#%5F%5Fcodelineno-11-174)            if let url = item as? URL {
[](#%5F%5Fcodelineno-11-175)                if let sharedPath = self.copyImageToSharedContainerWithFixedOrientation(url) {
[](#%5F%5Fcodelineno-11-176)                    let metadata = self.extractFileMetadata(from: url)
[](#%5F%5Fcodelineno-11-177)                    completion(SharedFileData(uri: sharedPath, name: metadata.name, mimeType: metadata.mimeType))
[](#%5F%5Fcodelineno-11-178)                    return
[](#%5F%5Fcodelineno-11-179)                }
[](#%5F%5Fcodelineno-11-180)            } else if let image = item as? UIImage {
[](#%5F%5Fcodelineno-11-181)                let fixedImage = self.normalizeImageOrientation(image)
[](#%5F%5Fcodelineno-11-182)                if let data = fixedImage.pngData() {
[](#%5F%5Fcodelineno-11-183)                    let base64String = data.base64EncodedString()
[](#%5F%5Fcodelineno-11-184)                    completion(SharedFileData(uri: "data:image/png;base64,\(base64String)", name: nil, mimeType: "image/png"))
[](#%5F%5Fcodelineno-11-185)                    return
[](#%5F%5Fcodelineno-11-186)                }
[](#%5F%5Fcodelineno-11-187)            }
[](#%5F%5Fcodelineno-11-188)
[](#%5F%5Fcodelineno-11-189)            completion(nil)
[](#%5F%5Fcodelineno-11-190)        }
[](#%5F%5Fcodelineno-11-191)    }
[](#%5F%5Fcodelineno-11-192)
[](#%5F%5Fcodelineno-11-193)    private func processMovieAttachment(_ attachment: NSItemProvider, dispatchGroup: DispatchGroup, completion: @escaping (SharedFileData?) -> Void) {
[](#%5F%5Fcodelineno-11-194)        dispatchGroup.enter()
[](#%5F%5Fcodelineno-11-195)        attachment.loadItem(forTypeIdentifier: UTType.movie.identifier, options: nil) { [weak self] (item, _) in
[](#%5F%5Fcodelineno-11-196)            defer { dispatchGroup.leave() }
[](#%5F%5Fcodelineno-11-197)            guard let self = self else { 
[](#%5F%5Fcodelineno-11-198)                completion(nil)
[](#%5F%5Fcodelineno-11-199)                return 
[](#%5F%5Fcodelineno-11-200)            }
[](#%5F%5Fcodelineno-11-201)
[](#%5F%5Fcodelineno-11-202)            if let url = item as? URL {
[](#%5F%5Fcodelineno-11-203)                if let sharedPath = self.copyFileToSharedContainer(url) {
[](#%5F%5Fcodelineno-11-204)                    let metadata = self.extractFileMetadata(from: url)
[](#%5F%5Fcodelineno-11-205)                    completion(SharedFileData(uri: sharedPath, name: metadata.name, mimeType: metadata.mimeType))
[](#%5F%5Fcodelineno-11-206)                    return
[](#%5F%5Fcodelineno-11-207)                }
[](#%5F%5Fcodelineno-11-208)            }
[](#%5F%5Fcodelineno-11-209)
[](#%5F%5Fcodelineno-11-210)            completion(nil)
[](#%5F%5Fcodelineno-11-211)        }
[](#%5F%5Fcodelineno-11-212)    }
[](#%5F%5Fcodelineno-11-213)
[](#%5F%5Fcodelineno-11-214)    private func processPlainTextAttachment(_ attachment: NSItemProvider, dispatchGroup: DispatchGroup, completion: @escaping (String?) -> Void) {
[](#%5F%5Fcodelineno-11-215)        dispatchGroup.enter()
[](#%5F%5Fcodelineno-11-216)        attachment.loadItem(forTypeIdentifier: UTType.plainText.identifier, options: nil) { (item, _) in
[](#%5F%5Fcodelineno-11-217)            defer { dispatchGroup.leave() }
[](#%5F%5Fcodelineno-11-218)
[](#%5F%5Fcodelineno-11-219)            if let text = item as? String {
[](#%5F%5Fcodelineno-11-220)                completion(text)
[](#%5F%5Fcodelineno-11-221)            } else {
[](#%5F%5Fcodelineno-11-222)                completion(nil)
[](#%5F%5Fcodelineno-11-223)            }
[](#%5F%5Fcodelineno-11-224)        }
[](#%5F%5Fcodelineno-11-225)    }
[](#%5F%5Fcodelineno-11-226)
[](#%5F%5Fcodelineno-11-227)    private func processURLAttachment(_ attachment: NSItemProvider, dispatchGroup: DispatchGroup, completion: @escaping (String?) -> Void) {
[](#%5F%5Fcodelineno-11-228)        dispatchGroup.enter()
[](#%5F%5Fcodelineno-11-229)        attachment.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { (item, _) in
[](#%5F%5Fcodelineno-11-230)            defer { dispatchGroup.leave() }
[](#%5F%5Fcodelineno-11-231)
[](#%5F%5Fcodelineno-11-232)            if let url = item as? URL {
[](#%5F%5Fcodelineno-11-233)                completion(url.absoluteString)
[](#%5F%5Fcodelineno-11-234)            } else {
[](#%5F%5Fcodelineno-11-235)                completion(nil)
[](#%5F%5Fcodelineno-11-236)            }
[](#%5F%5Fcodelineno-11-237)        }
[](#%5F%5Fcodelineno-11-238)    }
[](#%5F%5Fcodelineno-11-239)
[](#%5F%5Fcodelineno-11-240)    private func processSharedContent() {
[](#%5F%5Fcodelineno-11-241)        guard let extensionContext = extensionContext,
[](#%5F%5Fcodelineno-11-242)              let item = extensionContext.inputItems.first as? NSExtensionItem,
[](#%5F%5Fcodelineno-11-243)              let attachments = item.attachments else {
[](#%5F%5Fcodelineno-11-244)            self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
[](#%5F%5Fcodelineno-11-245)            return
[](#%5F%5Fcodelineno-11-246)        }
[](#%5F%5Fcodelineno-11-247)
[](#%5F%5Fcodelineno-11-248)        var textValues: [String] = []
[](#%5F%5Fcodelineno-11-249)        var fileValues: [SharedFileData] = []
[](#%5F%5Fcodelineno-11-250)        let title = item.attributedTitle?.string ?? item.attributedContentText?.string ?? ""
[](#%5F%5Fcodelineno-11-251)        let dispatchGroup = DispatchGroup()
[](#%5F%5Fcodelineno-11-252)
[](#%5F%5Fcodelineno-11-253)        for attachment in attachments {
[](#%5F%5Fcodelineno-11-254)            if attachment.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
[](#%5F%5Fcodelineno-11-255)                processImageAttachment(attachment, dispatchGroup: dispatchGroup) { fileData in
[](#%5F%5Fcodelineno-11-256)                    if let fileData = fileData {
[](#%5F%5Fcodelineno-11-257)                        fileValues.append(fileData)
[](#%5F%5Fcodelineno-11-258)                    }
[](#%5F%5Fcodelineno-11-259)                }
[](#%5F%5Fcodelineno-11-260)            }
[](#%5F%5Fcodelineno-11-261)
[](#%5F%5Fcodelineno-11-262)            if attachment.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
[](#%5F%5Fcodelineno-11-263)                processMovieAttachment(attachment, dispatchGroup: dispatchGroup) { fileData in
[](#%5F%5Fcodelineno-11-264)                    if let fileData = fileData {
[](#%5F%5Fcodelineno-11-265)                        fileValues.append(fileData)
[](#%5F%5Fcodelineno-11-266)                    }
[](#%5F%5Fcodelineno-11-267)                }
[](#%5F%5Fcodelineno-11-268)            }
[](#%5F%5Fcodelineno-11-269)
[](#%5F%5Fcodelineno-11-270)            if attachment.hasItemConformingToTypeIdentifier(UTType.plainText.identifier) {
[](#%5F%5Fcodelineno-11-271)                processPlainTextAttachment(attachment, dispatchGroup: dispatchGroup) { text in
[](#%5F%5Fcodelineno-11-272)                    if let text = text {
[](#%5F%5Fcodelineno-11-273)                        textValues.append(text)
[](#%5F%5Fcodelineno-11-274)                    }
[](#%5F%5Fcodelineno-11-275)                }
[](#%5F%5Fcodelineno-11-276)            }
[](#%5F%5Fcodelineno-11-277)
[](#%5F%5Fcodelineno-11-278)            if attachment.hasItemConformingToTypeIdentifier(UTType.url.identifier) {
[](#%5F%5Fcodelineno-11-279)                processURLAttachment(attachment, dispatchGroup: dispatchGroup) { urlString in
[](#%5F%5Fcodelineno-11-280)                    if let urlString = urlString {
[](#%5F%5Fcodelineno-11-281)                        textValues.append(urlString)
[](#%5F%5Fcodelineno-11-282)                    }
[](#%5F%5Fcodelineno-11-283)                }
[](#%5F%5Fcodelineno-11-284)            }
[](#%5F%5Fcodelineno-11-285)        }
[](#%5F%5Fcodelineno-11-286)
[](#%5F%5Fcodelineno-11-287)        dispatchGroup.notify(queue: .main) { [weak self] in
[](#%5F%5Fcodelineno-11-288)            self?.sendData(with: textValues, fileValues: fileValues, title: title)
[](#%5F%5Fcodelineno-11-289)        }
[](#%5F%5Fcodelineno-11-290)    }
[](#%5F%5Fcodelineno-11-291)}
[](#%5F%5Fcodelineno-11-292)
[](#%5F%5Fcodelineno-11-293)extension UIImage {
[](#%5F%5Fcodelineno-11-294)
[](#%5F%5Fcodelineno-11-295)    private func applyRotationTransform(for orientation: UIImage.Orientation, to transform: CGAffineTransform, size: CGSize) -> CGAffineTransform {
[](#%5F%5Fcodelineno-11-296)        var result = transform
[](#%5F%5Fcodelineno-11-297)
[](#%5F%5Fcodelineno-11-298)        switch orientation {
[](#%5F%5Fcodelineno-11-299)        case .down, .downMirrored:
[](#%5F%5Fcodelineno-11-300)            result = result.translatedBy(x: size.width, y: size.height)
[](#%5F%5Fcodelineno-11-301)            result = result.rotated(by: .pi)
[](#%5F%5Fcodelineno-11-302)        case .left, .leftMirrored:
[](#%5F%5Fcodelineno-11-303)            result = result.translatedBy(x: size.width, y: 0)
[](#%5F%5Fcodelineno-11-304)            result = result.rotated(by: .pi / 2.0)
[](#%5F%5Fcodelineno-11-305)        case .right, .rightMirrored:
[](#%5F%5Fcodelineno-11-306)            result = result.translatedBy(x: 0, y: size.height)
[](#%5F%5Fcodelineno-11-307)            result = result.rotated(by: -.pi / 2.0)
[](#%5F%5Fcodelineno-11-308)        case .up, .upMirrored:
[](#%5F%5Fcodelineno-11-309)            break
[](#%5F%5Fcodelineno-11-310)        @unknown default:
[](#%5F%5Fcodelineno-11-311)            break
[](#%5F%5Fcodelineno-11-312)        }
[](#%5F%5Fcodelineno-11-313)
[](#%5F%5Fcodelineno-11-314)        return result
[](#%5F%5Fcodelineno-11-315)    }
[](#%5F%5Fcodelineno-11-316)
[](#%5F%5Fcodelineno-11-317)    private func applyMirrorTransform(for orientation: UIImage.Orientation, to transform: CGAffineTransform, size: CGSize) -> CGAffineTransform {
[](#%5F%5Fcodelineno-11-318)        var result = transform
[](#%5F%5Fcodelineno-11-319)
[](#%5F%5Fcodelineno-11-320)        switch orientation {
[](#%5F%5Fcodelineno-11-321)        case .upMirrored, .downMirrored:
[](#%5F%5Fcodelineno-11-322)            result = result.translatedBy(x: size.width, y: 0)
[](#%5F%5Fcodelineno-11-323)            result = result.scaledBy(x: -1, y: 1)
[](#%5F%5Fcodelineno-11-324)        case .leftMirrored, .rightMirrored:
[](#%5F%5Fcodelineno-11-325)            result = result.translatedBy(x: size.height, y: 0)
[](#%5F%5Fcodelineno-11-326)            result = result.scaledBy(x: -1, y: 1)
[](#%5F%5Fcodelineno-11-327)        case .up, .down, .left, .right:
[](#%5F%5Fcodelineno-11-328)            break
[](#%5F%5Fcodelineno-11-329)        @unknown default:
[](#%5F%5Fcodelineno-11-330)            break
[](#%5F%5Fcodelineno-11-331)        }
[](#%5F%5Fcodelineno-11-332)
[](#%5F%5Fcodelineno-11-333)        return result
[](#%5F%5Fcodelineno-11-334)    }
[](#%5F%5Fcodelineno-11-335)
[](#%5F%5Fcodelineno-11-336)    private func drawRect(for orientation: UIImage.Orientation, size: CGSize) -> CGRect {
[](#%5F%5Fcodelineno-11-337)        switch orientation {
[](#%5F%5Fcodelineno-11-338)        case .left, .leftMirrored, .right, .rightMirrored:
[](#%5F%5Fcodelineno-11-339)            return CGRect(x: 0, y: 0, width: size.height, height: size.width)
[](#%5F%5Fcodelineno-11-340)        default:
[](#%5F%5Fcodelineno-11-341)            return CGRect(x: 0, y: 0, width: size.width, height: size.height)
[](#%5F%5Fcodelineno-11-342)        }
[](#%5F%5Fcodelineno-11-343)    }
[](#%5F%5Fcodelineno-11-344)
[](#%5F%5Fcodelineno-11-345)    func fixedOrientation() -> UIImage? {
[](#%5F%5Fcodelineno-11-346)        guard imageOrientation != .up else {
[](#%5F%5Fcodelineno-11-347)            return self.copy() as? UIImage
[](#%5F%5Fcodelineno-11-348)        }
[](#%5F%5Fcodelineno-11-349)
[](#%5F%5Fcodelineno-11-350)        guard let cgImage = self.cgImage,
[](#%5F%5Fcodelineno-11-351)              let colorSpace = cgImage.colorSpace,
[](#%5F%5Fcodelineno-11-352)              let context = CGContext(data: nil,
[](#%5F%5Fcodelineno-11-353)                                    width: Int(size.width),
[](#%5F%5Fcodelineno-11-354)                                    height: Int(size.height),
[](#%5F%5Fcodelineno-11-355)                                    bitsPerComponent: cgImage.bitsPerComponent,
[](#%5F%5Fcodelineno-11-356)                                    bytesPerRow: 0,
[](#%5F%5Fcodelineno-11-357)                                    space: colorSpace,
[](#%5F%5Fcodelineno-11-358)                                    bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else {
[](#%5F%5Fcodelineno-11-359)            return nil
[](#%5F%5Fcodelineno-11-360)        }
[](#%5F%5Fcodelineno-11-361)
[](#%5F%5Fcodelineno-11-362)        var transform = CGAffineTransform.identity
[](#%5F%5Fcodelineno-11-363)        transform = applyRotationTransform(for: imageOrientation, to: transform, size: size)
[](#%5F%5Fcodelineno-11-364)        transform = applyMirrorTransform(for: imageOrientation, to: transform, size: size)
[](#%5F%5Fcodelineno-11-365)
[](#%5F%5Fcodelineno-11-366)        context.concatenate(transform)
[](#%5F%5Fcodelineno-11-367)        context.draw(cgImage, in: drawRect(for: imageOrientation, size: size))
[](#%5F%5Fcodelineno-11-368)
[](#%5F%5Fcodelineno-11-369)        guard let newCGImage = context.makeImage() else { return nil }
[](#%5F%5Fcodelineno-11-370)        return UIImage(cgImage: newCGImage, scale: 1, orientation: .up)
[](#%5F%5Fcodelineno-11-371)    }
[](#%5F%5Fcodelineno-11-372)}
`

**Attention**: Replace `<YOUR_URL_SCHEME>` with the URL scheme you defined in your main app's `Info.plist` file (e.g. `myapp`) and `<YOUR_APP_IDENTIFIER>` with your app identifier (e.g. `com.example.app`). Make sure to keep the `group.` prefix for the app group identifier.

Finally, you need to modify the `AppDelegate.swift` file of your main app target to handle the URLs opened by the share extension. Add the missing import and the following code to the `application(_:open:options:)` method:

`[](#%5F%5Fcodelineno-12-1)// If you are using Swift Package Manager, add the following import:
[](#%5F%5Fcodelineno-12-2)+ import ShareTargetPlugin
[](#%5F%5Fcodelineno-12-3)// Or if you are using CocoaPods, add the following import:
[](#%5F%5Fcodelineno-12-4)// import CapawesomeTeamCapacitorShareTarget
[](#%5F%5Fcodelineno-12-5)
[](#%5F%5Fcodelineno-12-6)func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
[](#%5F%5Fcodelineno-12-7)+    // Handle share target URLs
[](#%5F%5Fcodelineno-12-8)+    let _ = ShareTargetPlugin.handleOpenUrl(url)
[](#%5F%5Fcodelineno-12-9)+
[](#%5F%5Fcodelineno-12-10)    // Called when the app was launched with a url. Feel free to add additional processing here,
[](#%5F%5Fcodelineno-12-11)    // but if you want the App API to support tracking app url opens, make sure to keep this call
[](#%5F%5Fcodelineno-12-12)    return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
[](#%5F%5Fcodelineno-12-13)}
`

**Attention**: If you are using **CocoaPods** instead of Swift Package Manager, replace `import ShareTargetPlugin` with `import CapawesomeTeamCapacitorShareTarget`.

#### Capabilities[¶](#capabilities "Permanent link")

If you want to receive not only text but also files (e.g., images, videos) from other apps, you need to enable the "App Groups" capability for both your main app and the share extension. This allows both targets to share files in a common container. To do this, follow these steps:

1. Open your Xcode project.
2. Select your app target.
3. Go to the "Signing & Capabilities" tab.
4. Click the "+" button to add a new capability.
5. Select "App Groups" from the list.
6. Create a new app group using the format `group.<YOUR_APP_IDENTIFIER>` (e.g., `group.com.example.app`).
7. Repeat the same steps for your share extension target, ensuring that both targets use the same app group identifier.

If you don't want to receive files, you can skip this step.

## Configuration[¶](#configuration "Permanent link")

No configuration required for this plugin.

## Web[¶](#web "Permanent link")

To use this plugin on the web, you need to set up a **Progressive Web App (PWA)** with a web manifest and service worker that handles share targets.

### Manifest[¶](#manifest "Permanent link")

To allow your PWA to act as a share target, you need to add a `share_target` configuration to your web manifest (`manifest.json`):

`[](#%5F%5Fcodelineno-13-1){
[](#%5F%5Fcodelineno-13-2)  "share_target": {
[](#%5F%5Fcodelineno-13-3)    "action": "/_share-target",
[](#%5F%5Fcodelineno-13-4)    "method": "POST",
[](#%5F%5Fcodelineno-13-5)    "enctype": "multipart/form-data",
[](#%5F%5Fcodelineno-13-6)    "params": {
[](#%5F%5Fcodelineno-13-7)      "title": "title",
[](#%5F%5Fcodelineno-13-8)      "text": "text", 
[](#%5F%5Fcodelineno-13-9)      "url": "url",
[](#%5F%5Fcodelineno-13-10)      "files": [
[](#%5F%5Fcodelineno-13-11)        {
[](#%5F%5Fcodelineno-13-12)          "name": "files",
[](#%5F%5Fcodelineno-13-13)          "accept": ["*/*"]
[](#%5F%5Fcodelineno-13-14)        }
[](#%5F%5Fcodelineno-13-15)      ]
[](#%5F%5Fcodelineno-13-16)    }
[](#%5F%5Fcodelineno-13-17)  }
[](#%5F%5Fcodelineno-13-18)}
`

For more information on setting up the share target for your PWA, refer to the [Web Share Target documentation](https://developer.mozilla.org/en-US/docs/Web/Manifest/share%5Ftarget).

### Service Worker[¶](#service-worker "Permanent link")

Since service workers are the only way to intercept network requests in a PWA, you'll need to create one to handle the share target requests. Just create a file named `sw.js` in your project's root directory and add the following code:

`` [](#%5F%5Fcodelineno-14-1)self.addEventListener('fetch', event => {
[](#%5F%5Fcodelineno-14-2)  const url = new URL(event.request.url);
[](#%5F%5Fcodelineno-14-3)
[](#%5F%5Fcodelineno-14-4)  if (event.request.method === 'POST' && url.pathname === '/_share-target') {
[](#%5F%5Fcodelineno-14-5)    event.respondWith(handleShareTarget(event.request));
[](#%5F%5Fcodelineno-14-6)  } else if (url.pathname.startsWith('/_share-file/')) {
[](#%5F%5Fcodelineno-14-7)    event.respondWith(handleFileRequest(event.request));
[](#%5F%5Fcodelineno-14-8)  }
[](#%5F%5Fcodelineno-14-9)});
[](#%5F%5Fcodelineno-14-10)
[](#%5F%5Fcodelineno-14-11)async function handleFileRequest(request) {
[](#%5F%5Fcodelineno-14-12)  try {
[](#%5F%5Fcodelineno-14-13)    const url = new URL(request.url);
[](#%5F%5Fcodelineno-14-14)    const fileId = url.pathname.substring(13); // Remove '/_share-file/' prefix
[](#%5F%5Fcodelineno-14-15)    const cache = await caches.open('share-target-files');
[](#%5F%5Fcodelineno-14-16)    const cacheKey = `/${fileId}`;
[](#%5F%5Fcodelineno-14-17)
[](#%5F%5Fcodelineno-14-18)    const response = await cache.match(cacheKey);
[](#%5F%5Fcodelineno-14-19)    if (response) {
[](#%5F%5Fcodelineno-14-20)      return response;
[](#%5F%5Fcodelineno-14-21)    } else {
[](#%5F%5Fcodelineno-14-22)      return new Response('File not found', { status: 404 });
[](#%5F%5Fcodelineno-14-23)    }
[](#%5F%5Fcodelineno-14-24)  } catch (error) {
[](#%5F%5Fcodelineno-14-25)    console.error('Error serving file:', error);
[](#%5F%5Fcodelineno-14-26)    return new Response('Internal error', { status: 500 });
[](#%5F%5Fcodelineno-14-27)  }
[](#%5F%5Fcodelineno-14-28)}
[](#%5F%5Fcodelineno-14-29)
[](#%5F%5Fcodelineno-14-30)async function handleShareTarget(request) {
[](#%5F%5Fcodelineno-14-31)  try {
[](#%5F%5Fcodelineno-14-32)    const formData = await request.formData();
[](#%5F%5Fcodelineno-14-33)    const title = formData.get('title') || '';
[](#%5F%5Fcodelineno-14-34)    const text = formData.get('text') || '';
[](#%5F%5Fcodelineno-14-35)    const url = formData.get('url') || '';
[](#%5F%5Fcodelineno-14-36)    const files = formData.getAll('files');
[](#%5F%5Fcodelineno-14-37)
[](#%5F%5Fcodelineno-14-38)    const texts = [];
[](#%5F%5Fcodelineno-14-39)    if (text) texts.push(text);
[](#%5F%5Fcodelineno-14-40)    if (url) texts.push(url);
[](#%5F%5Fcodelineno-14-41)
[](#%5F%5Fcodelineno-14-42)    const shareData = {
[](#%5F%5Fcodelineno-14-43)      title: title,
[](#%5F%5Fcodelineno-14-44)      texts: texts.length > 0 ? texts : undefined,
[](#%5F%5Fcodelineno-14-45)      files: undefined,
[](#%5F%5Fcodelineno-14-46)    };
[](#%5F%5Fcodelineno-14-47)
[](#%5F%5Fcodelineno-14-48)    if (files.length > 0) {
[](#%5F%5Fcodelineno-14-49)      const sharedFiles = [];
[](#%5F%5Fcodelineno-14-50)      const cache = await caches.open('share-target-files');
[](#%5F%5Fcodelineno-14-51)
[](#%5F%5Fcodelineno-14-52)      for (const file of files) {
[](#%5F%5Fcodelineno-14-53)        if (file instanceof File && file.size > 0) {
[](#%5F%5Fcodelineno-14-54)          const fileId = `share-file-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
[](#%5F%5Fcodelineno-14-55)          const cacheKey = `/${fileId}`;
[](#%5F%5Fcodelineno-14-56)
[](#%5F%5Fcodelineno-14-57)          const response = new Response(file, {
[](#%5F%5Fcodelineno-14-58)            headers: {
[](#%5F%5Fcodelineno-14-59)              'Content-Type': file.type,
[](#%5F%5Fcodelineno-14-60)              'Content-Length': file.size.toString(),
[](#%5F%5Fcodelineno-14-61)              'X-File-Name': file.name || 'unknown',
[](#%5F%5Fcodelineno-14-62)            }
[](#%5F%5Fcodelineno-14-63)          });
[](#%5F%5Fcodelineno-14-64)          await cache.put(cacheKey, response);
[](#%5F%5Fcodelineno-14-65)
[](#%5F%5Fcodelineno-14-66)          sharedFiles.push({
[](#%5F%5Fcodelineno-14-67)            uri: `/_share-file/${fileId}`,
[](#%5F%5Fcodelineno-14-68)            name: file.name || undefined,
[](#%5F%5Fcodelineno-14-69)            mimeType: file.type || undefined,
[](#%5F%5Fcodelineno-14-70)          });
[](#%5F%5Fcodelineno-14-71)        }
[](#%5F%5Fcodelineno-14-72)      }
[](#%5F%5Fcodelineno-14-73)
[](#%5F%5Fcodelineno-14-74)      if (sharedFiles.length > 0) {
[](#%5F%5Fcodelineno-14-75)        shareData.files = sharedFiles;
[](#%5F%5Fcodelineno-14-76)      }
[](#%5F%5Fcodelineno-14-77)    }
[](#%5F%5Fcodelineno-14-78)
[](#%5F%5Fcodelineno-14-79)    const redirectUrl = new URL('/', self.location.origin);
[](#%5F%5Fcodelineno-14-80)
[](#%5F%5Fcodelineno-14-81)    if (shareData.title) {
[](#%5F%5Fcodelineno-14-82)      redirectUrl.searchParams.set('title', shareData.title);
[](#%5F%5Fcodelineno-14-83)    }
[](#%5F%5Fcodelineno-14-84)
[](#%5F%5Fcodelineno-14-85)    if (shareData.texts && shareData.texts.length > 0) {
[](#%5F%5Fcodelineno-14-86)      shareData.texts.forEach((text, index) => {
[](#%5F%5Fcodelineno-14-87)        redirectUrl.searchParams.set(`text${index}`, text);
[](#%5F%5Fcodelineno-14-88)      });
[](#%5F%5Fcodelineno-14-89)    }
[](#%5F%5Fcodelineno-14-90)
[](#%5F%5Fcodelineno-14-91)    if (shareData.files && shareData.files.length > 0) {
[](#%5F%5Fcodelineno-14-92)      shareData.files.forEach((file, index) => {
[](#%5F%5Fcodelineno-14-93)        redirectUrl.searchParams.set(`fileUri${index}`, file.uri);
[](#%5F%5Fcodelineno-14-94)        if (file.name) {
[](#%5F%5Fcodelineno-14-95)          redirectUrl.searchParams.set(`fileName${index}`, file.name);
[](#%5F%5Fcodelineno-14-96)        }
[](#%5F%5Fcodelineno-14-97)        if (file.mimeType) {
[](#%5F%5Fcodelineno-14-98)          redirectUrl.searchParams.set(`fileMimeType${index}`, file.mimeType);
[](#%5F%5Fcodelineno-14-99)        }
[](#%5F%5Fcodelineno-14-100)      });
[](#%5F%5Fcodelineno-14-101)    }
[](#%5F%5Fcodelineno-14-102)
[](#%5F%5Fcodelineno-14-103)    return Response.redirect(redirectUrl.href, 303);
[](#%5F%5Fcodelineno-14-104)  } catch (error) {
[](#%5F%5Fcodelineno-14-105)    console.error('Error handling share target:', error);
[](#%5F%5Fcodelineno-14-106)    return Response.redirect('/', 303);
[](#%5F%5Fcodelineno-14-107)  }
[](#%5F%5Fcodelineno-14-108)}
 ``

Now, register your service worker in your main JavaScript file:

`[](#%5F%5Fcodelineno-15-1)if ('serviceWorker' in navigator) {
[](#%5F%5Fcodelineno-15-2)  navigator.serviceWorker.register('/sw.js');
[](#%5F%5Fcodelineno-15-3)}
`

## Usage[¶](#usage "Permanent link")

The following example shows how to listen for content shared to your app and load the shared files.

### Listen for shared content[¶](#listen-for-shared-content "Permanent link")

Add a listener for the `shareReceived` event to handle content shared to your app. The event contains the title, text content, and files that were shared. On Android and iOS, load shared files using `Capacitor.convertFileSrc(...)` and the [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch%5FAPI/Using%5FFetch); on the web, the file URIs are cached file URLs that can be fetched directly:

`[](#%5F%5Fcodelineno-16-1)import { ShareTarget } from '@capawesome-team/capacitor-share-target';
[](#%5F%5Fcodelineno-16-2)import { Capacitor } from '@capacitor/core';
[](#%5F%5Fcodelineno-16-3)
[](#%5F%5Fcodelineno-16-4)const addListener = async () => {
[](#%5F%5Fcodelineno-16-5)    await ShareTarget.addListener('shareReceived', (event) => {
[](#%5F%5Fcodelineno-16-6)        console.log('Share received:', event);
[](#%5F%5Fcodelineno-16-7)
[](#%5F%5Fcodelineno-16-8)        // Handle shared files
[](#%5F%5Fcodelineno-16-9)        if (event.files) {
[](#%5F%5Fcodelineno-16-10)          event.files.forEach(async (file) => {
[](#%5F%5Fcodelineno-16-11)            const webPath = Capacitor.convertFileSrc(file.uri);
[](#%5F%5Fcodelineno-16-12)            const response = await fetch(webPath);
[](#%5F%5Fcodelineno-16-13)            const blob = await response.blob();
[](#%5F%5Fcodelineno-16-14)            // Process the file...
[](#%5F%5Fcodelineno-16-15)          });
[](#%5F%5Fcodelineno-16-16)        }
[](#%5F%5Fcodelineno-16-17)    });
[](#%5F%5Fcodelineno-16-18)};
`

## API[¶](#api "Permanent link")

* [addListener('shareReceived', ...)](#addlistenersharereceived-)
* [removeAllListeners()](#removealllisteners)
* [Interfaces](#interfaces)

### addListener('shareReceived', ...)[¶](#addlistenersharereceived "Permanent link")

`[](#%5F%5Fcodelineno-17-1)addListener(eventName: 'shareReceived', listenerFunc: (event: ShareReceivedEvent) => void) => Promise<PluginListenerHandle>
`

Called when a share is received.

| Param            | Type                                                       |
| ---------------- | ---------------------------------------------------------- |
| **eventName**    | 'shareReceived'                                            |
| **listenerFunc** | (event: [ShareReceivedEvent](#sharereceivedevent)) => void |

**Returns:** `Promise<[PluginListenerHandle](#pluginlistenerhandle)>`

**Since:** 0.1.0

---

### removeAllListeners()[¶](#removealllisteners "Permanent link")

`[](#%5F%5Fcodelineno-18-1)removeAllListeners() => Promise<void>
`

Remove all listeners for this plugin.

**Since:** 0.1.0

---

### Interfaces[¶](#interfaces "Permanent link")

#### PluginListenerHandle[¶](#pluginlistenerhandle "Permanent link")

| Prop       | Type                |
| ---------- | ------------------- |
| **remove** | () => Promise<void> |

#### ShareReceivedEvent[¶](#sharereceivedevent "Permanent link")

| Prop      | Type           | Description                       | Since |
| --------- | -------------- | --------------------------------- | ----- |
| **title** | string         | The title of the shared content.  | 0.1.0 |
| **texts** | string\[\]     | The text content that was shared. | 0.1.0 |
| **files** | SharedFile\[\] | The files that were shared.       | 0.2.0 |

#### SharedFile[¶](#sharedfile "Permanent link")

| Prop         | Type   | Description                                                                                                                                                                                                            | Since |
| ------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
| **mimeType** | string | The mime type of the shared file.                                                                                                                                                                                      | 0.2.0 |
| **name**     | string | The name of the shared file with or without extension.                                                                                                                                                                 | 0.2.0 |
| **uri**      | string | The URI of the shared file. On **Android** and **iOS**, this will contain the file paths or base64 encoded data URLs of the shared files. On **Web**, this will contain cached file URLs that can be fetched directly. | 0.2.0 |

## Troubleshooting[¶](#troubleshooting "Permanent link")

##### `Unable to find compatibility version string for object version XX`[¶](#unable-to-find-compatibility-version-string-for-object-version-xx "Permanent link")

When creating a share extension, you might encounter the following error when building your app:

`[](#%5F%5Fcodelineno-19-1)Unable to find compatibility version string for object version 70
`

This error is typically caused by an updated `objectVersion` value in the `project.pbxproj` file of your Xcode project. To resolve this issue, you need to manually revert the `objectVersion` value to a previous version that is compatible with your Xcode version.

## FAQ[¶](#faq "Permanent link")

### What types of content can my app receive?[¶](#what-types-of-content-can-my-app-receive "Permanent link")

The plugin can handle text, URLs, images, videos, and other files. Which content types your app actually receives depends on your configuration: the intent filters in your `AndroidManifest.xml` on Android, the `NSExtensionActivationRule` of your share extension on iOS, and the `share_target` configuration in your web manifest for Progressive Web Apps. See the [Installation](#installation) section for details.

### Why do I need a share extension on iOS?[¶](#why-do-i-need-a-share-extension-on-ios "Permanent link")

On iOS, it's not possible to receive shared content directly in the main app. Instead, a share extension handles the shared content and communicates it back to your main app via a URL scheme. The [Installation](#installation) section walks you through creating the share extension, setting up the URL scheme, and handling the URLs in your `AppDelegate.swift`.

### How do I read the files that were shared?[¶](#how-do-i-read-the-files-that-were-shared "Permanent link")

Each shared file contains a `uri` property. On Android and iOS, this contains the file path or a base64 encoded data URL of the shared file, which you can load using `Capacitor.convertFileSrc(...)` and the Fetch API. On the web, the `uri` contains a cached file URL that can be fetched directly. See the [usage example](#listen-for-shared-content) above.

### Why does my app not appear in the share sheet on Android?[¶](#why-does-my-app-not-appear-in-the-share-sheet-on-android "Permanent link")

Make sure you have added the appropriate intent filters inside the `<activity>` tag of your main activity in `AndroidManifest.xml` for the MIME types you want to receive. Also, the activity must have the `android:exported="true"` attribute set so that other apps can send intents to it, as described in the [Installation](#installation) section.

### Does the plugin work in a Progressive Web App?[¶](#does-the-plugin-work-in-a-progressive-web-app "Permanent link")

Yes, the plugin leverages the Web Share Target API. You need to add a `share_target` configuration to your web manifest and register a service worker that handles the share target requests, as described in the [Web](#web) section.

### Can I use this plugin with Ionic, React, Vue or Angular?[¶](#can-i-use-this-plugin-with-ionic-react-vue-or-angular "Permanent link")

Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects.

## Related Plugins[¶](#related-plugins "Permanent link")

* [Android Intent Launcher](https://capawesome.io/docs/sdks/capacitor/android-intent-launcher/): Launch arbitrary Android intents, for example to share content with other apps.
* [Clipboard](https://capawesome.io/docs/sdks/capacitor/clipboard/): Read from and write to the system clipboard.
* [File Opener](https://capawesome.io/docs/sdks/capacitor/file-opener/): Open a received file with the default application.
* [File Picker](https://capawesome.io/docs/sdks/capacitor/file-picker/): Let the user select a file, directory, image, or video from the device.

## Newsletter[¶](#newsletter "Permanent link")

Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).

## Changelog[¶](#changelog "Permanent link")

See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/share-target/CHANGELOG.md).

## Breaking Changes[¶](#breaking-changes "Permanent link")

See [BREAKING.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/share-target/BREAKING.md).

## License[¶](#license "Permanent link")

See [LICENSE](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/share-target/LICENSE).

July 8, 2026 

Back to top

```json
{"@context": "https://schema.org", "@graph": [{"@type": "TechArticle", "@id": "https://capawesome.io/docs/sdks/capacitor/share-target/#article", "headline": "Capacitor Share Target Plugin for Android, iOS & Web", "name": "Capacitor Share Target Plugin for Android, iOS & Web", "description": "Capacitor plugin to receive content such as text, links, and files from other apps. Available for Android, iOS, and Web.", "inLanguage": "en", "url": "https://capawesome.io/docs/sdks/capacitor/share-target/", "mainEntityOfPage": "https://capawesome.io/docs/sdks/capacitor/share-target/", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "about": {"@id": "https://capawesome.io/docs/sdks/capacitor/share-target/#software"}}, {"@type": "SoftwareSourceCode", "@id": "https://capawesome.io/docs/sdks/capacitor/share-target/#software", "name": "Capacitor Share Target Plugin for Android, iOS & Web", "description": "Capacitor plugin to receive content such as text, links, and files from other apps. Available for Android, iOS, and Web.", "url": "https://capawesome.io/docs/sdks/capacitor/share-target/", "programmingLanguage": "TypeScript", "runtimePlatform": "Capacitor", "codeRepository": "https://github.com/capawesome-team", "author": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}, "publisher": {"@type": "Organization", "name": "Capawesome", "url": "https://capawesome.io", "logo": {"@type": "ImageObject", "url": "https://capawesome.io/assets/images/logo.svg"}}}]}
{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What types of content can my app receive?", "acceptedAnswer": {"@type": "Answer", "text": "The plugin can handle text, URLs, images, videos, and other files. Which content types your app actually receives depends on your configuration: the intent filters in your AndroidManifest.xml on Android, the NSExtensionActivationRule of your share extension on iOS, and the share_target configuration in your web manifest for Progressive Web Apps. See the Installation section for details."}}, {"@type": "Question", "name": "Why do I need a share extension on iOS?", "acceptedAnswer": {"@type": "Answer", "text": "On iOS, it's not possible to receive shared content directly in the main app. Instead, a share extension handles the shared content and communicates it back to your main app via a URL scheme. The Installation section walks you through creating the share extension, setting up the URL scheme, and handling the URLs in your AppDelegate.swift."}}, {"@type": "Question", "name": "How do I read the files that were shared?", "acceptedAnswer": {"@type": "Answer", "text": "Each shared file contains a uri property. On Android and iOS, this contains the file path or a base64 encoded data URL of the shared file, which you can load using Capacitor.convertFileSrc(...) and the Fetch API. On the web, the uri contains a cached file URL that can be fetched directly. See the usage example above."}}, {"@type": "Question", "name": "Why does my app not appear in the share sheet on Android?", "acceptedAnswer": {"@type": "Answer", "text": "Make sure you have added the appropriate intent filters inside the <activity> tag of your main activity in AndroidManifest.xml for the MIME types you want to receive. Also, the activity must have the android:exported=\"true\" attribute set so that other apps can send intents to it, as described in the Installation section."}}, {"@type": "Question", "name": "Does the plugin work in a Progressive Web App?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, the plugin leverages the Web Share Target API. You need to add a share_target configuration to your web manifest and register a service worker that handles the share target requests, as described in the Web section."}}, {"@type": "Question", "name": "Can I use this plugin with Ionic, React, Vue or Angular?", "acceptedAnswer": {"@type": "Answer", "text": "Yes, the plugin is framework-agnostic. It works in any Capacitor app regardless of the web framework, including Ionic with Angular, React, or Vue, as well as plain JavaScript projects."}}], "url": "https://capawesome.io/docs/sdks/capacitor/share-target/"}
```
