tauri-plugin-sharetarget

Crates.iotauri-plugin-sharetarget
lib.rstauri-plugin-sharetarget
version
sourcesrc
created_at2024-11-01 12:46:49.585953
updated_at2024-11-02 19:57:19.879835
descriptiontauri apps: receive share intents on Android
homepage
repositoryhttps://gitlab.com/lafleurdeboum/tauri-plugin-sharetarget
max_upload_size
id1431753
Cargo.toml error:TOML parse error at line 26, column 1 | 26 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include`
size0
la Fleur (lafleurdeboum)

documentation

README

Tauri Plugin sharetarget

NPM Version NPM Downloads Documentation

A plugin for Tauri applications to appear as a share target under Android. Desktop OSes are unsupported (they lack the feature). Behaviour on iOs is indeterminate.

Installation

In src-tauri/Cargo.toml :

[dependencies]
tauri-plugin-sharetarget = "LATEST_VERSION_HERE"

In src-tauri/src/lib.rs, add the plugin entry :

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_sharetarget::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

To build for Android, you must first tauri android init successfully. This gets some files generated. To signal your app as a share target to Android, you then need to modify your AndroidManifest.xml. In src-tauri/gen/android/app/src/main/AndroidManifest.xml, add your intent-filters :

<?xml version="1.0" encoding="utf-8">
<manifest ...>
    ...
    <application ...>
        ...
        <activity ...>
            <intent-filter>
                <!-- Support receiving share events. -->
                <action android:name="android.intent.action.SEND" />
                <category android:name="android.intent.category.DEFAULT" />
                <!-- You can scope any MIME type here. You'll see what Intent Android returns. -->
                <data android:mimeType="text/*" />
            </intent-filter>
        </activity ...>
        ...

Permissions

First you need permissions in tauri, just to get ipc events in javascript. In src-tauri/capabilities/default.json, add sharetarget to the permissions :

{
    "$schema": "../gen/schemas/desktop-schema.json",
    "identifier": "anything_you_like",
    "windows": ["main"],
    "permissions": [
        ...
        "sharetarget:default"
    ]
}

Usage

Use the provided API in javascript/typescript. For example in React, in src/main.tsx :

import { useEffect, useState } from 'react';
import { listenForShareEvents, type ShareEvent } from 'tauri-plugin-sharetarget-api';
import { PluginListener } from '@tauri-apps/api/core';

function App() {
    const [logs, setLogs] = useState('');
    useEffect(() => {
        let listener: PluginListener;
        const setupListener = async () => {
            listener = await listenForShareEvents((intent: ShareEvent) => {
                setLogs(intent.uri);
            });
        };
        return () => { listener?.unregister(); };
    };
    return (<>
        <h3>Share this</h3>
        <p>{ logs }</p>
        <button onClick={ yourCallbackFunction }>share</button>
    </>);
}

Receive attached stream (images, etc)

To receive shared images, you need

  • an intent targeting image/*
  • @tauri-apps/plugin-fs in package.json dependencies to read the sent data
  • fs:default in the capabilities of your app
  • in javascript, use readFile() from @tauri-apps/plugin-fs on the intent's stream.

Here is the previous example revamped to fetch binary contents. Upload({ file }) is not implemented because users may do whatever they like with the File object. This just showcases how to grab the binary data.

import { useEffect, useState } from 'react';
import { listenForShareEvents, type ShareEvent } from 'tauri-plugin-sharetarget-api';
import { PluginListener } from '@tauri-apps/api/core';
import { readFile } from '@tauri-apps/plugin-fs';

function App() {
    const [logs, setLogs] = useState('');
    const [file, setFile] = useState<File>();
    useEffect(() => {
        let listener: PluginListener;
        const setupListener = async () => {
            listener = await listenForShareEvents(async (intent: ShareEvent) => {
                if(event.stream) {
                    const contents = await readFile(intent.stream).catch((error: Error) => {
                        console.warn('fetching shared content failed:');
                        throw error;
                    });
                    setFile(new File([contents], intent.name, { type: intent.content_type }));
                } else {
                    // This intent contains no binary bundle.
                    console.warn('unused share intent', intent.uri);
                }
                setLogs(intent.uri);
            });
        };
        setupListener();
        return () => { listener?.unregister(); };
    };
    return (<>
        <h3>Sharing { intent.name }</h3>
        <Upload file={ file } />
    </>);
}

Caveats

Unfortunately, multiple files in a single share intent are not supported right now. iOs is also unsupported - I don't have the platform. PRs welcome !

Commit count: 31

cargo fmt