Mob.Storage (mob v0.9.21)

Copy Markdown View Source

App-local file storage.

Provides a thin Elixir wrapper over the device filesystem using named locations instead of raw paths. Basic file operations (list, stat, delete, copy, move, read, write) are pure File.* calls — no NIF overhead except for the initial dir/1 path resolution.

Locations

  • :temp — ephemeral; may be purged by the OS at any time
  • :documents — persists across app sessions; backed up to iCloud on
                 iOS; user-visible there when `UIFileSharingEnabled` is
                 set (see `mix mob.enable`)
  • :cache — persists until OS needs space; not user-visible, not
                 backed up
  • :app_support — persists, hidden from user; backed up to iCloud on iOS
                 unless excluded (see `exclude_from_backup/1`)

On Android a generated app sets android:allowBackup="false", so none of these go to a cloud backup. On Android 12 and higher that flag doesn't stop a device-to-device transfer; only android:dataExtractionRules does.

Backup

Apple rejects apps that back up data they can download again. Keep such data (downloaded models, content packs, media caches you don't want purged) in :app_support and mark its directory with exclude_from_backup/1.

Platform-specific storage

See Mob.Storage.Apple and Mob.Storage.Android for saving to the native photo/media library and accessing platform-specific directories.

Results

Operations that can fail return {:ok, value} | {:error, posix}. dir/1 raises on an unknown location atom.

Summary

Functions

Copy src to dest.

Delete a file.

Resolve a location atom to its absolute path on the current device.

Exclude a file or directory from iCloud and device backups.

Whether path is excluded from backup, read back from the filesystem.

Return the file extension including the leading dot, or "" if none.

List all files in a location or an absolute path.

Move src to dest.

Read a file's contents as a binary.

Return metadata for a file.

Write data to path.

Functions

copy(src, dest)

@spec copy(String.t(), atom() | String.t()) :: {:ok, String.t()} | {:error, atom()}

Copy src to dest.

dest may be a location atom (file is placed there keeping its basename) or a full absolute path.

Returns {:ok, dest_path} on success.

delete(path)

@spec delete(String.t()) :: :ok | {:error, atom()}

Delete a file.

dir(location)

@spec dir(atom()) :: String.t()

Resolve a location atom to its absolute path on the current device.

exclude_from_backup(path, nif \\ :mob_nif)

@spec exclude_from_backup(String.t(), module()) ::
  :ok | {:error, :enoent | :unsupported | String.t()}

Exclude a file or directory from iCloud and device backups.

On iOS this sets NSURLIsExcludedFromBackupKey on path. On a directory the flag covers everything beneath it, including files created later, so marking the top directory of your downloaded data is enough. Call it at every launch, not once: restoring the app or moving it to a new device can drop the attribute, and setting it again is cheap.

On Android this does nothing; Android has no per-file flag. Generated apps set android:allowBackup="false", which keeps app data out of cloud backups (and, up to Android 11, device-to-device transfers). To keep a path out of either when backup is on, or out of an Android 12+ device-to-device transfer, exclude it in the app's backup rules (android:fullBackupContent for Android 11 and lower, android:dataExtractionRules for 12 and higher). Off device (host, tests) it also does nothing.

Returns {:error, :enoent} on every platform when path doesn't exist, and on iOS {:error, description} with the system's message when the attribute can't be set. On an iOS app whose native build predates this function (mob 0.9.20 or older, not rebuilt with mix mob.deploy --native) it returns {:error, :unsupported}: the path stays backed up, and saying :ok would hide that.

excluded_from_backup?(path, nif \\ :mob_nif)

@spec excluded_from_backup?(String.t(), module()) :: boolean()

Whether path is excluded from backup, read back from the filesystem.

true only on iOS, for a path whose NSURLIsExcludedFromBackupKey is set. A path inside an excluded directory reports false (the flag is on the directory, not copied to its contents), yet it is not backed up. Android and the host always answer false, and so does an iOS native build that predates this function; see exclude_from_backup/1.

extension(path)

@spec extension(String.t()) :: String.t()

Return the file extension including the leading dot, or "" if none.

No I/O — derived from the filename only.

Mob.Storage.extension("/tmp/clip.mp4")   #=> ".mp4"
Mob.Storage.extension("/tmp/notes")      #=> ""

list(location)

@spec list(atom() | String.t()) :: {:ok, [String.t()]} | {:error, atom()}

List all files in a location or an absolute path.

Returns full paths, not just names.

move(src, dest)

@spec move(String.t(), atom() | String.t()) :: {:ok, String.t()} | {:error, atom()}

Move src to dest.

dest may be a location atom or a full absolute path.

Returns {:ok, dest_path} on success.

read(path)

@spec read(String.t()) :: {:ok, binary()} | {:error, atom()}

Read a file's contents as a binary.

stat(path)

@spec stat(String.t()) :: {:ok, map()} | {:error, atom()}

Return metadata for a file.

%{name: "clip.mp4", path: "/…/clip.mp4", size: 204_800,
  modified_at: ~U[2026-04-24 10:00:00Z]}

write(path, data)

@spec write(String.t(), binary()) :: {:ok, String.t()} | {:error, atom()}

Write data to path.

Returns {:ok, path} on success.