rn-watch-connectv2.0

File Transfer

Send files to the Watch in the background, and receive the files it sends you.

A File Transfer is a file, with optional metadata, queued for background delivery to the Watch. The Watch doesn't have to be reachable.

Each file you send is a Transfer until it's delivered:

Files the Watch sends you are Received files. They arrive through onFileReceived, or through onFileReceiveFailed when one couldn't be kept.

Transfer ids last for one app run

After your app restarts, a Transfer that's still outstanding gets a new id. Read outstandingFileTransfers at launch to pick them up. Their finish events and cancelFileTransfer use the new ids.

transferFile

transferFile(file: string, metadata?: Record<string, any>): FileTransfer

Queues a file for delivery to the Watch and returns at once. The Watch app receives it in session(_:didReceive:).

WatchConnectivity keeps its own copy of the file, so you can delete yours right after calling transferFile. That doesn't stop or fail the Transfer.

Parameters

NameTypeDescription
filestringA file:// URL of an existing file, such as the uri of an expo-file-system File.
metadataRecord<string, any> (optional)A dictionary sent with the file, for example its original name.

Returns the Transfer snapshot, FileTransfer, in the same shape as outstandingFileTransfers:

FieldTypeDescription
idstringThe Transfer id, valid for the current app run.
isTransferringbooleanWhether the Transfer is in progress right now.
progressFileProgressfractionCompleted (0 to 1), completedUnitCount and totalUnitCount (bytes).
fileFilefileURL (the file being sent) and metadata (what you passed).

Throws (synchronously):

CodeWhen
ERR_INVALID_FILE_URLfile isn't a URL the library can read.
ERR_FILE_NOT_FOUNDThere's no file at file.
ERR_UNSUPPORTED_PLATFORMCalled on a platform other than iOS.

Its error message starts with Expo's prefix, "Calling the 'transferFile' function has failed", so match on code. Delivery failures don't throw here: they arrive later, in onFileTransferFinished.

Example

import , { type  } from "rn-watch-connect";

const  = "file:///path/to/Documents/route.gpx";

try {
  const  = .(, { : "route.gpx" });
  .("Queued Transfer", .);
} catch () {
  const  = ( as { ?:  }).;
  if ( === "ERR_FILE_NOT_FOUND") {
    // The file was moved or deleted before you could send it.
  }
}

cancelFileTransfer

cancelFileTransfer(transferId: string): { id: string }

Cancels an outstanding File Transfer. Its onFileTransferFinished event is sent immediately, with error.code "ERR_TRANSFER_CANCELLED".

Parameters

NameTypeDescription
transferIdstringThe id of an outstanding Transfer, from the current app run.

Returns { id: string }: the id of the cancelled Transfer.

Throws (synchronously):

CodeWhen
ERR_INVALID_TRANSFER_IDtransferId isn't an outstanding Transfer: it was already delivered, already cancelled, or is from an earlier app run.
ERR_UNSUPPORTED_PLATFORMCalled on a platform other than iOS.

Its error message starts with Expo's prefix, "Calling the 'cancelFileTransfer' function has failed", so match on code.

If the Transfer was delivered just before you cancel, the cancel throws ERR_INVALID_TRANSFER_ID and the finish event reports the delivery, with error: null.

Example

import  from "rn-watch-connect";

// Cancel every File Transfer still waiting.
for (const  of .) {
  .(.);
}

outstandingFileTransfers

readonly outstandingFileTransfers: FileTransfer[]

The File Transfers that haven't been delivered yet, as Transfer snapshots (id, isTransferring, progress, file). It's [] when there are none, and on platforms other than iOS.

WatchConnectivity has no progress event. To show progress, read this property every so often, and use onFileTransferFinished to know when a Transfer is done.

Example

import  from "rn-watch-connect";

const  = (() => {
  for (const { ,  } of .) {
    .(, `${.(. * 100)}%`);
  }
}, 1000);

// Later: clearInterval(timer);

onFileReceived

onFileReceived: (file: File) => void

Fires when a Received file arrives from the Watch.

Event

FieldTypeDescription
fileURLstringWhere the file is now: in your app's temporary directory.
metadataRecord<string, any>What the Watch sent with the file.

The file is yours from this event on. The library moves each Received file into your app's temporary directory, then never moves, overwrites or deletes it again.

  • iOS can delete files in the temporary directory while your app isn't running. Move or copy the file somewhere permanent if you need to keep it, and delete it when you're done.
  • Received files never overwrite each other. If the name is taken, the new file is numbered the way Finder does it: photo.jpg, then photo(1).jpg, photo(2).jpg, and so on. metadata is passed through unchanged, so you can still read the original name if the Watch sent it there.

Example

import {  } from "expo";
import  from "rn-watch-connect";

export function () {
  (, "onFileReceived", ({ ,  }) => {
    const  = .name ?? .("/").();
    .(`Received ${} at ${}`);
    // Move or copy it somewhere permanent here if you need to keep it.
  });
  return null;
}

onFileReceiveFailed

onFileReceiveFailed: (event: FileReceiveFailedEvent) => void

Fires when a file from the Watch arrived but couldn't be kept, for example because the iPhone is out of storage. The file is lost: WatchConnectivity has already deleted it, and onFileReceived doesn't fire for it. Use fileName and metadata to tell which file it was, for example to ask the Watch to send it again.

Event

FieldTypeDescription
messagestringWhy the file couldn't be kept.
codeWatchConnectErrorCodeERR_INSUFFICIENT_SPACE when the iPhone is out of storage, otherwise ERR_FILE_RECEIVE_FAILED.
fileNamestringThe file name the Watch sent.
metadataRecord<string, any> | nullWhat the Watch sent with the file, or null when it sent nothing.

Example

import {  } from "expo";
import  from "rn-watch-connect";

export function () {
  (, "onFileReceiveFailed", ({ ,  }) => {
    if ( === "ERR_INSUFFICIENT_SPACE") {
      .(`Not enough storage to keep ${} from the Watch.`);
    } else {
      .(`Couldn't keep ${} from the Watch.`);
    }
  });
  return null;
}

onFileTransferFinished

onFileTransferFinished: (event: FileTransferFinishedEvent) => void

Fires exactly once per File Transfer, however it ends. The event is the Transfer snapshot (id, isTransferring, progress, file) plus error:

How it endederror
Delivered to the Watchnull
Failed{ message, code } from WatchConnectivity, for example code: "ERR_DELIVERY_FAILED"
Cancelled with cancelFileTransfer{ message, code: "ERR_TRANSFER_CANCELLED" }, sent immediately

If your Watch app is uninstalled during a Transfer, the Transfer stays outstanding and no finish event is sent, even after a reinstall. Cancel it to end it, for example when onWatchAppInstallChanged reports isWatchAppInstalled: false.

Example

import {  } from "expo";
import  from "rn-watch-connect";

export function () {
  (, "onFileTransferFinished", () => {
    if (.?. === "ERR_TRANSFER_CANCELLED") {
      .("Cancelled:", .);
    } else if (.) {
      .("Failed:", ., ..);
    } else {
      .("Delivered:", ..);
    }
  });
  return null;
}

On this page