Class Attachments

java.lang.Object
com.aurelienpierre.sioul.Attachments

public final class Attachments extends Object
A mail attachment opened in the app you choose, or saved where you choose (docs/client.md, "Antivirus"; crates/sioul-app/src/attachments.rs). Rust writes the attachment in Sioul's cache, cache/sioul/attachments/<message>/<name>, after Sioul's own checks: mail set aside keeps its attachments closed, and programs and installers are never opened. A phone has no antivirus Sioul can call, and nothing here claims one.

Since Android 7 a file goes to another app by a content:// address, never by its path. Here it is an address of Qt's FileProvider (authority <package>.qtprovider), whose root "attachments" (res/xml/qtprovider_paths.xml) is that folder of the cache alone. Android lends the address, to read only, to the one app that opens it: that app reads this file and nothing else of Sioul's. When no app is set for its type, Android asks which one ("Open with").

Saving asks Android where (ACTION_CREATE_DOCUMENT, in AttachmentSave), then copies the file there; the copy in the cache goes, saved or not.

The pure parts (the address, the type, what an app is handed, what Android is asked) are checked on a computer: android/jvm-checks, AttachmentsCheck.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    (package private) static final class 
    Android's question "where?" for a file to save: an action, a category, a type, the name offered.
    (package private) static final class 
    What another app is handed to open a file: an action, an address, a type, flags.
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    (package private) static final String
    Qt's FileProvider, the one Sioul declares: its authority, after the package's name.
    (package private) static final String
    A type nothing more is known of.
    (package private) static final String
    That root's folder, in the app's cache, where Rust writes attachments (XDG_CACHE_HOME/sioul/attachments).
    private static final char[]
     
    (package private) static final String
    Android's installer's type: never handed to open, whatever the name says.
    (package private) static final String
    The provider's root for attachments, by its name in res/xml/qtprovider_paths.xml.
    (package private) static final String
     
    (package private) static final int
    A file handed to open: to read, and nothing more, in a task of its own (Rust asks from Sioul's application, not from its window).
  • Constructor Summary

    Constructors
    Modifier
    Constructor
    Description
    private
     
  • Method Summary

    Modifier and Type
    Method
    Description
    private static String
    Android's own type for a file's extension; null when it has none.
    (package private) static String
    call(Context context, String verb, JSONObject asked)
    Rust's question (StepService.call(android.content.Context, java.lang.String, java.lang.String), verbs "attachment-…"): "attachment-open" {path, type}, answered {opened} or {problem}; "attachment-save" {path, name, type}, answered {asked} or {problem}, then AttachmentSave tells Rust what became of it.
    (package private) static String
    contentUri(String packageName, String folder, String file)
    The address FileProvider gives file in the root "attachments", whose folder is folder (both canonical paths, as FileProvider compares them): content://<package>.qtprovider/attachments/<the rest, encoded part by part>.
    (package private) static String
    contentUri(String packageName, String folder, String file, String root)
    The address FileProvider gives file in its root root (res/xml/qtprovider_paths.xml), whose folder is folder, as contentUri(String, String, String) says it for the attachments: a multimedia message's file, for Android to read it (TextSend.sendMms, root "files_path").
    (package private) static String
    decode(String text)
    Uri.decode's way back: each %XX a byte, the bytes read as UTF-8.
    (package private) static String
    encode(String text)
    A part of an address as Android's Uri.encode writes it, as FileProvider does: letters, digits and _-!.~'()* kept, every other byte of its UTF-8 as %XX.
    (package private) static String
    fileOf(String packageName, String folder, String uri)
    FileProvider's way back (its getFileForUri), for the checks: the file an address names in the root "attachments", whose folder is folder; null when it names no file there.
    private static String
    folder(Context context)
    The attachments' folder in this app's cache, as FileProvider reads it (canonical).
    (package private) static JSONObject
    open(Context context, String path, String given)
    The attachment at path handed to the app you choose: {opened: true}, else {problem: "refused" | "gone" | "no-app" | "failed"}.
    (package private) static JSONObject
    said(Object... pairs)
    A JSON answer from pairs of names and values; what cannot be written is left out.
    (package private) static JSONObject
    save(Context context, String path, String name, String type)
    Android asked where to save the attachment at path (AttachmentSave, never shown itself): {asked: true}, else {problem: "refused" | "gone" | "failed"}.
    (package private) static Attachments.SaveAs
    saveAs(String name, String type)
    What Android is asked to save a file: ACTION_CREATE_DOCUMENT, among the files that open (CATEGORY_OPENABLE), of its type (plain bytes when none), under its name (the attachment's when none).
    private static String
    shownName(Context context, Uri target, String name)
    The name the saved file has where it went (Android may add " (1)"); name when it does not say.
    (package private) static String
    type(String given, String android)
    The type an app is asked to open: Rust's, from the name's extension (sioul_core::compose::mime_of), else Android's own for that extension, else plain bytes; in lower case.
    (package private) static Attachments.View
    view(String packageName, String folder, String file, String type)
    What is handed to open file (a canonical path) of type type (from type()): ACTION_VIEW, its content address, the type, read only; null when the file is not in the attachments' folder, or for an installer.
    (package private) static JSONObject
    write(Context context, String path, Uri target, String name)
    The attachment at path copied where Android's question answered (target, null when you closed it), then taken out of the cache, saved or not: {path, name, saved, shown (the name it has there)} or {path, name, saved: false, problem}.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

  • Constructor Details

  • Method Details

    • encode

      static String encode(String text)
      A part of an address as Android's Uri.encode writes it, as FileProvider does: letters, digits and _-!.~'()* kept, every other byte of its UTF-8 as %XX.
    • decode

      static String decode(String text)
      Uri.decode's way back: each %XX a byte, the bytes read as UTF-8.
    • contentUri

      static String contentUri(String packageName, String folder, String file)
      The address FileProvider gives file in the root "attachments", whose folder is folder (both canonical paths, as FileProvider compares them): content://<package>.qtprovider/attachments/<the rest, encoded part by part>. Null for a file outside the folder, the folder itself, or a path with an empty, "." or ".." part.
    • contentUri

      static String contentUri(String packageName, String folder, String file, String root)
      The address FileProvider gives file in its root root (res/xml/qtprovider_paths.xml), whose folder is folder, as contentUri(String, String, String) says it for the attachments: a multimedia message's file, for Android to read it (TextSend.sendMms, root "files_path").
    • fileOf

      static String fileOf(String packageName, String folder, String uri)
      FileProvider's way back (its getFileForUri), for the checks: the file an address names in the root "attachments", whose folder is folder; null when it names no file there.
    • type

      static String type(String given, String android)
      The type an app is asked to open: Rust's, from the name's extension (sioul_core::compose::mime_of), else Android's own for that extension, else plain bytes; in lower case. Null for Android's installer, whatever gave it: an installer is never handed to open.
    • view

      static Attachments.View view(String packageName, String folder, String file, String type)
      What is handed to open file (a canonical path) of type type (from type()): ACTION_VIEW, its content address, the type, read only; null when the file is not in the attachments' folder, or for an installer.
    • saveAs

      static Attachments.SaveAs saveAs(String name, String type)
      What Android is asked to save a file: ACTION_CREATE_DOCUMENT, among the files that open (CATEGORY_OPENABLE), of its type (plain bytes when none), under its name (the attachment's when none).
    • call

      static String call(Context context, String verb, JSONObject asked)
      Rust's question (StepService.call(android.content.Context, java.lang.String, java.lang.String), verbs "attachment-…"): "attachment-open" {path, type}, answered {opened} or {problem}; "attachment-save" {path, name, type}, answered {asked} or {problem}, then AttachmentSave tells Rust what became of it.
    • said

      static JSONObject said(Object... pairs)
      A JSON answer from pairs of names and values; what cannot be written is left out.
    • androidType

      private static String androidType(String file)
      Android's own type for a file's extension; null when it has none.
    • folder

      private static String folder(Context context) throws IOException
      The attachments' folder in this app's cache, as FileProvider reads it (canonical).
      Throws:
      IOException
    • open

      static JSONObject open(Context context, String path, String given)
      The attachment at path handed to the app you choose: {opened: true}, else {problem: "refused" | "gone" | "no-app" | "failed"}. Nothing of the file's name goes to the log.
    • save

      static JSONObject save(Context context, String path, String name, String type)
      Android asked where to save the attachment at path (AttachmentSave, never shown itself): {asked: true}, else {problem: "refused" | "gone" | "failed"}.
    • write

      static JSONObject write(Context context, String path, Uri target, String name)
      The attachment at path copied where Android's question answered (target, null when you closed it), then taken out of the cache, saved or not: {path, name, saved, shown (the name it has there)} or {path, name, saved: false, problem}. A copy that fails midway is removed there. On a thread of its own.
    • shownName

      private static String shownName(Context context, Uri target, String name)
      The name the saved file has where it went (Android may add " (1)"); name when it does not say.