{"id":23975037,"url":"https://github.com/dan-leech/com.danleech.cordova.plugin.openwith","last_synced_at":"2026-05-13T08:37:06.427Z","repository":{"id":97234158,"uuid":"154636160","full_name":"dan-leech/com.danleech.cordova.plugin.openwith","owner":"dan-leech","description":"Get your Cordova App in the O.S. \"Share\" menu on iOS and Android","archived":false,"fork":false,"pushed_at":"2018-11-20T05:37:20.000Z","size":34,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-24T16:42:35.161Z","etag":null,"topics":["cordova","cordova-android","cordova-ios","cordova-plugin","openwith","share-extension"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dan-leech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-10-25T08:28:36.000Z","updated_at":"2019-03-08T17:58:53.000Z","dependencies_parsed_at":null,"dependency_job_id":"0fe8dce1-3ff5-4103-8126-eb9eff378bf3","html_url":"https://github.com/dan-leech/com.danleech.cordova.plugin.openwith","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dan-leech/com.danleech.cordova.plugin.openwith","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dan-leech%2Fcom.danleech.cordova.plugin.openwith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dan-leech%2Fcom.danleech.cordova.plugin.openwith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dan-leech%2Fcom.danleech.cordova.plugin.openwith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dan-leech%2Fcom.danleech.cordova.plugin.openwith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dan-leech","download_url":"https://codeload.github.com/dan-leech/com.danleech.cordova.plugin.openwith/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dan-leech%2Fcom.danleech.cordova.plugin.openwith/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32975180,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T06:31:55.726Z","status":"ssl_error","status_checked_at":"2026-05-13T06:31:51.336Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cordova","cordova-android","cordova-ios","cordova-plugin","openwith","share-extension"],"created_at":"2025-01-07T05:57:04.089Z","updated_at":"2026-05-13T08:37:06.421Z","avatar_url":"https://github.com/dan-leech.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cordova-plugin-openwith\nBased on [fovea openwith plugin](https://github.com/j3k0/cordova-plugin-openwith) and \n[missive openwith plugin](https://github.com/missive/cordova-plugin-openwith)\n\u003e This plugin for [Apache Cordova](https://cordova.apache.org/) registers your app to handle certain types of files.\n\nThis plugin supports text, from 1 to 5 images, one video those you can share to your app.\n## Overview\n\nYou'd like your app to be listed in the **Send to...** section for certain types of files, on both **Android** and **iOS**? This is THE plugin! No need to meddle into Android's manifests and iOS's plist files, it's (almost) all managed for you by a no brainer one liner installation command.\n\n## Table of Contents\n\n- [Background](#background)\n- [Installation](#installation)\n- [Usage](#usage)\n- [API](#api)\n- [License](#license)\n\n\n## Background\n\niOS and Android each have their own ways of handing over files to an app. This plugin abstracts them behind a single and simplified interface. It does not expose all subtleties of each system, be this should be enough for 99% of people. Are you the 1% that needs more? Fork and PR if it makes sense, or [ask for help](mailto://contact@fovea.cc).\n\nThe plugin's API mostly follows Android's terminology.\n\nBelow is a short introduction to how the technology works on Android and iOS.\n\n#### Android\n\nOn Android, the app defines, in its __AndroidManifest.xml__ file, the **mime type** of file types it can handle. Wildcard are accepted, so `image/*` can be used to accept all images regardless of the sub-type. The app also defines the type of actions accepted for this file types. By default, only the [SEND](https://developer.android.com/reference/android/content/Intent.html#ACTION_SEND) event is declared by the plugin. Other events that can be of interest are `SEND_MULTIPLE` and `VIEW`.\n\nWhen a user sends a file to your app, the system provides an [Intent](https://developer.android.com/reference/android/content/Intent.html) to the application. An Intent is just an abstract description of an operation to be performed. This Intent defines an action and can be linked with internal URIs to one or more files through the [\"stream\" property](https://developer.android.com/reference/android/content/Intent.html#EXTRA_STREAM) attached to the intent. Starting Android 4.4 KitKat, [ClipData](https://developer.android.com/reference/android/content/ClipData.html) was introduced to mimick a sort of Clipboard used to exchange data between apps. Both methods are supported.\n\nIf you are interested to learn more, the documentations for [Intent.ACTION_SEND](https://developer.android.com/reference/android/content/Intent.html#ACTION_SEND), [ClipData](https://developer.android.com/reference/android/content/ClipData.html) and the [Clipboard Framework](https://developer.android.com/guide/topics/text/copy-paste.html) are good places to start.\n\n#### iOS\n\nOn iOS, there are many ways apps can communicate. This plugin uses a [Share Extension](https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/Share.html#//apple_ref/doc/uid/TP40014214-CH12-SW1). This is a particular type of App Extension which intent is, as Apple puts it: _\"to post to a sharing website or share content with others\"_.\n\nA share extension can be used to share any type of content. You have to define which you want to support using an [Universal Type Identifier](https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_intro/understand_utis_intro.html) (or UTI). For a full list of what your options are, please check [Apple's System-Declared UTI](https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259-SW1).\n\nAs with all extensions, the flow of events is expected to be handled by a small app, external to your Cordova App but bundled with it. When installing the plugin, we will add a new target called **ShareExtension** to your XCode project which implements this Extension App. The Extension and the Cordova App live in different processes and can only communicate with each other using inter-app communication methods.\n\nWhen a user posts some content using the Share Extension, the content will be stored in a Shared User-Preferences Container. To enable this, the Cordova App and Share Extension should define a group and add both the app and extension to it, manually. At the moment, it seems like it's not possible to automate the process. You can read more about this [here](http://www.atomicbird.com/blog/sharing-with-app-extensions).\n\nOnce the data is in place in the Shared User-Preferences Container, the Share Extension will open the Cordova App by calling a [Custom URL Scheme](https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Inter-AppCommunication/Inter-AppCommunication.html#//apple_ref/doc/uid/TP40007072-CH6-SW1). This seems a little borderline as Apple tries hard to prevent this from being possible, but brave iOS developers always find [solutions](https://stackoverflow.com/questions/24297273/openurl-not-work-in-action-extension/24614589#24614589)... So as for now there is one and it seems like people got their app pass the review process with it. The recommended solution is be to implement the posting logic in the Share Extension, but this doesn't play well with Cordova Apps architecture...\n\nOn the Cordova App side, the plugin checks listens for app start or resume events. When this happens, it looks into the Shared User-Preferences Container for any content to share and report it to the javascript application.\n\n## Installation\n\nHere's the promised one liner:\n\n```\ncordova plugin add https://github.com/dan-leech/my-plugins-com.danleech.cordova.plugin.openwith \\\n  --variable IOS_URL_SCHEME=ccfoveaopenwithdemo\n```\n\n| variable | example | notes |\n|---|---|---|\n| `IOS_URL_SCHEME` | uniquelonglowercase | **iOS only** Any random long string of lowercase alphabetical characters |\n\nIt shouldn't be too hard. But just in case, I [posted a screencast of it](https://youtu.be/eaE4m_xO1mg).\n\n### iOS Setup\n\nAfter having installed the plugin, with the ios platform in place, 1 operation needs to be done manually: setup the App Group on both the Cordova App and the Share Extension.\n\n 1. open the **xcodeproject** for your application\n 1. select the root element of your **project navigator** (the left-side pane)\n 1. select the **target** of your application\n 1. select **capabilities**\n 1. scroll down to **App Groups**\n 1. make sure it's **ON**\n 1. create and activate an **App Group** called: `group.\u003cYOUR_APP_BUNDLE_ID\u003e.shareextension`\n 1. repeat the previous five steps for the **ShareExtension target**.\n 1. Set `#define SHAREEXT_GROUP_IDENTIFIER` in `ShereExtension/ShareViewController.h`\n \nYou might also have to select a Team for both the App and Share Extension targets, make sure to select the same.\n\nBuild, XCode might complain about a few things to setup that it will fix for you (creation entitlements files, etc).\n\n### Advanced installation options\n\nIf you do not need anything fancy, you can skip this section.\n\n**Android: accept extra actions**\n\nOn Android, you can define more supported actions (see the \"Background\" section above to learn more about this).\n\nUse the `ANDROID_EXTRA_ACTIONS` to accept additional actions. The variable should contain one or more valid XML action-elements. Example:\n\n```\nMY_EXTRA_ACTIONS='\u003caction android:name=\"android.intent.action.VIEW\" /\u003e'\ncordova plugin add com.danleech.cordova.plugin.openwith \\\n  --variable ANDROID_MIME_TYPE=\"image/*\" \\\n  --variable \"ANDROID_EXTRA_ACTIONS=$MY_EXTRA_ACTIONS\"\n```\n\nTo specify more than one extra action, just put them all in the `ANDROID_EXTRA_ACTIONS`:\n\n```\nMY_EXTRA_ACTIONS='\u003caction ... /\u003e\u003caction ... /\u003e'\n```\n\n## Usage\n\n```js\ndocument.addEventListener('deviceready', setupOpenwith, false);\n\nfunction setupOpenwith() {\n\n  // Increase verbosity if you need more logs\n  //cordova.openwith.setVerbosity(cordova.openwith.DEBUG);\n\n  // Initialize the plugin\n  cordova.openwith.init(initSuccess, initError);\n\n  function initSuccess()  { console.log('init success!'); }\n  function initError(err) { console.log('init failed: ' + err); }\n\n  // Define your file handler\n  cordova.openwith.addHandler(myHandler);\n\n  function myHandler(intent) {\n    console.log('intent received');\n\n    console.log('  action: ' + intent.action); // type of action requested by the user\n    console.log('  exit: ' + intent.exit); // if true, you should exit the app after processing\n\n    for (var i = 0; i \u003c intent.items.length; ++i) {\n      var item = intent.items[i];\n      console.log('  type: ', item.type);   // mime type\n      console.log('  uri:  ', item.uri);     // uri to the file, probably NOT a web uri\n\n      // some optional additional info\n      console.log('  text: ', item.text);   // text to share alongside the item, iOS only\n      console.log('  name: ', item.name);   // suggested name of the image, iOS 11+ only\n      console.log('  utis: ', item.utis);\n      console.log('  path: ', item.path);   // path on the device, generally undefined\n    }\n\n    // ...\n    // Here, you probably want to do something useful with the data\n    // ...\n    // An example...\n\n    if (intent.items.length \u003e 0) {\n      cordova.openwith.load(intent.items[0], function(data, item) {\n\n        // data is a long base64 string with the content of the file\n        console.log(\"the item weights \" + data.length + \" bytes\");\n        uploadToServer(item);\n\n        // \"exit\" when done.\n        // Note that there is no need to wait for the upload to finish,\n        // the app can continue while in background.\n        if (intent.exit) { cordova.openwith.exit(); }\n      });\n    }\n    else {\n      if (intent.exit) { cordova.openwith.exit(); }\n    }\n  }\n}\n```\n\nCheck out the [demo project](https://github.com/j3k0/cordova-plugin-openwith-demo) for a functional example.\n\n## API\n\n### cordova.openwith.setVerbosity(level)\n\nChange the verbosity level of the plugin.\n\n`level` can be set to:\n\n - `cordova.openwith.DEBUG` for maximal verbosity, log everything.\n - `cordova.openwith.INFO` for the default verbosity, log interesting stuff only.\n - `cordova.openwith.WARN` for low verbosity, log only warnings and errors.\n - `cordova.openwith.ERROR` for minimal verbosity, log only errors.\n\n### cordova.openwith.addHandler(handlerFunction)\n\nAdd an handler function, that will get notified when a file is received.\n\n**Handler function**\n\nThe signature for the handler function is `function handlerFunction(intent)`. See below for what an intent is.\n\n**Intent**\n\n`intent` describe the operation to perform, toghether with the associated data. It has the following fields:\n\n - `action`: the desired action. see below for possible values.\n - `exit`: true if the app should exit after processing.\n - `items`: an array containing one or more data descriptor.\n\n**Action**\n\nHere are the possible actions.\n\n - `cordova.openwith.SEND`: when the user wants to send the file(s)\n - `cordova.openwith.VIEW`: when the user wants to view the file(s)\n\n**Data descriptor**\n\nA data descriptor describe one file. It is a javascript object with the following fields:\n\n - `uri`: uri to the file.\n   - _probably NOT a web uri, use `load()` if you want the data from this uri._\n - `type`: the mime type.\n - `text`: text entered by the user when sharing (**iOS only**)\n - `name`: suggested file name, generally undefined.\n - `path`: path on the device, generally undefined.\n - `utis`: list of UTIs the file belongs to (**iOS only**).\n - `base64`: a long base64 string with the content of the file.\n   - _might be undefined until `load()` has been called and completed successfully._\n\n### cordova.openwith.load(dataDescriptor, loadSuccessCallback, loadErrorCallback)\n\nLoad data for an item. `dataDescriptor` is an item in an intent's items list, see the section about `addHandler()` above for details.\n\n**loadSuccessCallback**: function (base64, dataDescriptor)\n\nWhen data has been successfully loaded, `loadSuccessCallback` will be called. It is expected to have the following signature: `function (base64, dataDescriptor)`\n\n`base64` is a long string containing the data. `dataDescriptor` is the loaded `dataDescriptor`, extended to contain the `base64` field.\n\n**loadErrorCallback**: function (err, dataDescriptor)\n\nCalled when data can't be loaded.\n\n### cordova.openwith.exit()\n\nAttempt to return the the calling app when sharing is done. Your app will be backgrounded,\nit should be able to finish the upload.\n\nOn iOS, this call might have no effects. The plugin needs to recognize the app\nyou are sharing from in order to send you back to it. The user can still select the\n\"Back-to-app\" button visible on the top left. Make sure your UI shows the user\nthat he can now safely go back to what he was doing.\n\nOn Android, the app will be backgrounded no matter what.\n\n## Contribute\n\nContributions in the form of GitHub pull requests are welcome. Please adhere to the following guidelines:\n  - Before embarking on a significant change, please create an issue to discuss the proposed change and ensure that it is likely to be merged.\n  - Follow the coding conventions used throughout the project. Many conventions are enforced using eslint and pmd. Run `npm t` to make sure of that.\n  - Any contributions must be licensed under the MIT license.\n\n## License\n\n[MIT](./LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdan-leech%2Fcom.danleech.cordova.plugin.openwith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdan-leech%2Fcom.danleech.cordova.plugin.openwith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdan-leech%2Fcom.danleech.cordova.plugin.openwith/lists"}