ym_open_file_plus

pub package likes

Open a local file with the device's default application from Flutter. The plugin supports Android, iOS, Linux, macOS, Windows, and web.

This package is a maintained fork of open_file with a narrow Android permission model and a Dart-only desktop implementation.

Supported platforms

Platform Implementation Minimum
Android ACTION_VIEW + secure FileProvider Android 6.0 (API 23)
iOS UIDocumentInteractionController iOS 13
Linux xdg-open or another desktop opener Flutter 3.44.8
macOS open Flutter 3.44.8
Windows Win32 ShellExecuteW Flutter 3.44.8
Web Browser navigation in a new tab Flutter 3.44.8

Installation

dependencies:
  ym_open_file_plus: ^1.0.0
flutter pub get

Usage

import 'package:ym_open_file_plus/ym_open_file_plus.dart';

final result = await OpenFile.open('/path/to/report.pdf');

switch (result.type) {
  case ResultType.done:
    print('Opened');
  case ResultType.fileNotFound:
    print('File does not exist');
  case ResultType.noAppToOpen:
    print('No compatible application is installed');
  case ResultType.permissionDenied:
    print('The host app cannot read this file');
  case ResultType.error:
    print(result.message);
}

You can provide an explicit MIME type on Android and a Uniform Type Identifier on iOS:

await OpenFile.open(
  '/path/to/report.pdf',
  type: 'application/pdf',
  uti: 'com.adobe.pdf',
);

OpenFile.open returns an OpenResult with a stable ResultType and a diagnostic message. The result means that the platform accepted the open request; it does not guarantee that the user finished viewing the document.

Android storage and permissions

The plugin does not request broad storage permissions and does not declare MANAGE_EXTERNAL_STORAGE. This is intentional.

For the most reliable modern Android flow, obtain a user-selected content:// URI through the Storage Access Framework and pass that URI to OpenFile.open. For a normal file path, the host app must already have read access to the file. The plugin shares it through a temporary, read-only FileProvider URI.

If your app intentionally reads legacy shared storage on Android 9 or lower, declare the permission in the app (not in this plugin) and scope it to the supported API level:

<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="28" />

To open an APK, the host app must be allowed to request package installs and declare the permission required by Android:

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

Google Play restricts this permission to apps whose core functionality requires package installation. Do not add it unless your app qualifies.

iOS

Pass an absolute local file path. iOS presents a Quick Look preview when possible and otherwise presents the system Open In menu. The optional uti argument lets you override the document type.

Desktop

Linux uses xdg-open by default:

await OpenFile.open('/tmp/report.pdf', linuxDesktopName: 'xdg');

linuxByProcess remains available for source compatibility with older releases; the current implementation always uses an argument-safe asynchronous process invocation, so paths containing spaces and shell metacharacters are handled safely.

Web

Browsers cannot read arbitrary paths on the user's local filesystem. On web, pass an http, https, blob, or data URL and call the method directly from a user gesture:

await OpenFile.open('https://example.com/report.pdf');

Popup blockers can prevent a new tab from opening. A successful web result means that the browser accepted the navigation request.

Requirements

  • Dart SDK 3.11 or newer
  • Flutter 3.44.8 or newer
  • Android API 23 or newer
  • iOS 13 or newer

License

Copyright © 2026 Yash Manghnani. See LICENSE.