[Flutter actual combat] file system directory

Lao Meng's guide : We all know that path_provider is used to obtain file paths in Flutter , but the meaning of its directory is not very clear. This article introduces the file directories of Android and iOS systems and the recommended directories in different scenarios.

The file systems corresponding to different platforms are different, such as file paths. Therefore, obtaining file paths in Flutter requires native support. The native side passes the file path to Flutter through MethodChannel. If there is no special requirement, it is recommended that you use the official Google plugin path_provider .

Pub address: https://pub.flutter-io.cn/packages/path_provider

Github address: https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider

Add dependency

In the project pubspec.yamlfile to add dependencies:

dependencies:
  path_provider: ^1.6.14

Excuting an order:

flutter pub get

file path

path_provider (version: 1.6.14) provides 8 methods to obtain different file paths. Currently Flutter (Flutter 1.20.1 • channel stable) only releases the official version of Android and iOS, so only the files for Android and iOS platforms are introduced below path.

  • getTemporaryDirectory

    Temporary directory, suitable for downloaded cache files, this directory can be cleared at any time, this directory is a private directory of the application, other applications cannot access this directory.

    Corresponding on Android getCacheDir.

    Corresponds to iOS NSCachesDirectory.

  • getApplicationSupportDirectory

    The path to the directory where the application can place application support files.

    Use this file for files that you do not want to disclose to users. Your application should not use this directory to store user data files.

    On iOS NSApplicationSupportDirectory, if this directory does not exist, it will be created automatically. On Android, we correspond getFilesDir.

  • getLibraryDirectory

    The application can store persistent files, backup files, and directory paths for files that are not visible to users, such as storage.sqlite.db.

    On Android, this function throws an [UnsupportedError] exception, and no equivalent path exists.

  • getApplicationDocumentsDirectory

    The directory path where the application may place user-generated data or data that the application cannot recreate.

    On iOS, it corresponds to the NSDocumentDirectoryAPI. If the data is not user-generated, consider using [getApplicationSupportDirectory].

    On Android, it corresponds to the getDataDirectoryAPI. If you want users to see the data, consider using [getExternalStorageDirectory] instead.

  • getExternalStorageDirectory

    The path of the directory where the application can access the top-level storage. Since this feature is only available on Android, the current operating system should be determined before issuing this function call.

    On iOS, this feature will raise an [UnsupportedError] exception because it cannot be accessed outside the sandbox of the application.

    On Android, we correspond getExternalFilesDir(null).

  • getExternalCacheDirectories

    The path to the directory where application-specific external cache data is stored. These paths are usually located on external storage (such as a separate partition or SD card). The phone may have multiple storage directories available. Since this feature is only available on Android, the current operating system should be determined before issuing this function call. On iOS, this feature will throw an UnsupportedError because it is impossible to access outside the sandbox of the app.

    On Android, the corresponding Context.getExternalCacheDirs()or API Level is lower than 19 Context.getExternalCacheDir().

  • getExternalStorageDirectories

    The path to the directory where application-specific data can be stored. These paths are usually located on external storage (such as a separate partition or SD card). Since this feature is only available on Android, the current operating system should be determined before issuing this function call. On iOS, this feature will throw an UnsupportedError because it is impossible to access outside the sandbox of the app. On Android, the corresponding Context.getExternalFilesDirs(String type)or API Level is lower than 19 Context.getExternalFilesDir(String type).

  • getDownloadsDirectory

    The path to the directory where the downloaded file is stored. This is usually only related to the desktop operating system. On Android and iOS, this function will raise an [UnsupportedError] exception.

If there is no Android or iOS development experience, reading the above description should look ignorant force , and with so many paths in the end what? What's the difference? The following introduces its file path from the perspective of Android and iOS platforms, and finally gives suggestions on the use of the path and matters that need to be paid attention to during use.

Android file storage

Android file storage is divided into internal storage and external storage .

Internal storage

Private files used to store applications, other applications can not access the data, files created in the directory for this application package name, without root privileges mobile phone can not be in the file manager to see this directory application, but you can by Android Studio Tool view, the path is: data/data/package name:

Look at the specific directory structure under the package name:

  • cache directory: Corresponding to the getTemporaryDirectory method, used to cache files, this directory may be cleared by the system at any time.
  • files directory: corresponding to the getApplicationSupportDirectory method.
  • code_cache: This directory stores Flutter related code and resources.
    • flutter_engine/skia: Flutter rendering engine.
    • flutter_guidePVWGWK/flutter_guide/build/flutter_assets:Flutter 资源文件。
  • shared_prefs: The default path of SharePreferences .
  • app_flutter: Corresponds to the getApplicationDocumentsDirectory method.
  • app_flutter / dbName: Use sqlite default path, sqlite can also specify the location.

SharePreferences and sqlite are two third-party plug-ins that save data.

Features of internal storage:

  • Security, other applications cannot access this data.
  • When the application is uninstalled, these data will also be deleted to avoid junk files.
  • No need to apply for additional permissions.
  • Limited storage space, this directory may be cleared at any time data system, you can also set the Clear data to clear this directory data.
  • With domestic characteristics , different mobile phone manufacturers have imposed different restrictions on this catalog, such as overall size restrictions, restrictions on the size of the space occupied by a single application, and different data clearing strategies.

External storage

The external storage can phone's file manager to view the application,

There is a special directory: Android/data/package name:

Seeing that this directory feels very similar to the internal storage directory, a package name represents an application:

  • cache: cache directory, corresponding to the getExternalCacheDirectories method.
  • files: Corresponding to the getExternalStorageDirectories method.

Features of this catalog:

  • When the application is uninstalled, these data will also be deleted to avoid junk files.
  • No need to apply for additional permissions.
  • Space is large and the system will not be cleared, by setting the Clear data to clear this directory data.
  • Users can directly delete and import files.

In addition to the Android/data/ directory, external storage also has a directory at the same level as this directory. Features:

  • All applications can be accessed.
  • Users can directly delete and import files.
  • Need to apply for read and write permissions .

The Android official management of this directory is becoming more and more strict. The Android 11 system has begun to enforce partition storage. For details, please see: https://developer.android.com/preview/privacy/storage?hl=zh-cn

So much has been said above, summarized as follows:

  • SharePreferences and sqlite data are recommended to be stored in internal storage. The plug-in has already done it for us, without manual processing.
  • Strictly confidential data, such as user data, is recommended to be stored in internal storage, corresponding to the getApplicationSupportDirectory method.
  • It is recommended to store all other data in Android/data/package name/ , corresponding to the getExternalCacheDirectories and getExternalStorageDirectories methods.

iOS file storage

iOS file storage is much simpler than Android, because iOS is very strict on user privacy protection. Each iOS application has a separate file system and can only be operated in the corresponding file system. This area is called Sandbox.

Each application sandbox contains 3 folders: Documents, Library and tmp:

  • Documents: Application data files are written to this directory. This directory is used to store user data. Save important data files and user data files of the application. iTunes will back up this directory during synchronization, corresponding to the getApplicationDocumentsDirectory method.
  • Library: Corresponds to the getLibraryDirectory method.
    • Caches: Save support files, cache files, log files, etc. generated when the application is used, such as downloaded music, video, SDWebImage cache, etc. Corresponds to the getTemporaryDirectory method.
    • Preferences: Contains the preference setting file of the application, iCloud will back up the setting information.
    • Application Support: Corresponds to the getApplicationSupportDirectory method.
  • tmp: Stores temporary files and will not be backed up, and the data under this file may be cleared at any time. According to the official statement, the cached data is cleaned up every three days.

path_provider use

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

///
/// desc:
///

class PathProviderDemo extends StatefulWidget {
  @override
  _PathProviderDemoState createState() => _PathProviderDemoState();
}

class _PathProviderDemoState extends State<PathProviderDemo> {
  Future<Directory> _tempDirectory;
  Future<Directory> _appSupportDirectory;
  Future<Directory> _appLibraryDirectory;
  Future<Directory> _appDocumentsDirectory;
  Future<Directory> _externalStorageDirectory;
  Future<List<Directory>> _externalStorageDirectories;
  Future<List<Directory>> _externalCacheDirectories;
  Future<Directory> _downloadDirectory;

  @override
  void initState() {
    super.initState();
    setState(() {
      _tempDirectory = getTemporaryDirectory();
      _appSupportDirectory = getApplicationSupportDirectory();
      _appLibraryDirectory = getLibraryDirectory();
      _appDocumentsDirectory = getApplicationDocumentsDirectory();
      _externalStorageDirectory = getExternalStorageDirectory();
      _externalCacheDirectories = getExternalCacheDirectories();
      _externalStorageDirectories = getExternalStorageDirectories();
      _downloadDirectory = getDownloadsDirectory();
    });
  }

  Widget _buildDirectory(
      BuildContext context, AsyncSnapshot<Directory> snapshot) {
    Text text = const Text('');
    if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        text = Text('Error: ${snapshot.error}');
      } else if (snapshot.hasData) {
        text = Text('path: ${snapshot.data.path}');
      } else {
        text = const Text('path unavailable');
      }
    }
    return Padding(padding: EdgeInsets.symmetric(horizontal: 16), child: text);
  }

  Widget _buildDirectories(
      BuildContext context, AsyncSnapshot<List<Directory>> snapshot) {
    Text text = const Text('');
    if (snapshot.connectionState == ConnectionState.done) {
      if (snapshot.hasError) {
        text = Text('Error: ${snapshot.error}');
      } else if (snapshot.hasData) {
        final String combined =
            snapshot.data.map((Directory d) => d.path).join(', ');
        text = Text('paths: $combined');
      } else {
        text = const Text('path unavailable');
      }
    }
    return Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16), child: text);
  }

  Widget _buildItem(String title, Future<Directory> future) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Text(title),
        ),
        FutureBuilder<Directory>(future: future, builder: _buildDirectory),
      ],
    );
  }

  Widget _buildItem1(String title, Future<List<Directory>> future) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Text(title),
        ),
        FutureBuilder<List<Directory>>(
            future: future,
            builder: _buildDirectories),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Center(
        child: ListView(
          itemExtent: 120,
          children: <Widget>[
            _buildItem('getTemporaryDirectory', _tempDirectory),
            _buildItem('getApplicationSupportDirectory', _appSupportDirectory),
            _buildItem('getLibraryDirectory', _appLibraryDirectory),
            _buildItem(
                'getApplicationDocumentsDirectory', _appDocumentsDirectory),
            _buildItem(
                'getExternalStorageDirectory', _externalStorageDirectory),
            _buildItem('getDownloadsDirectory', _downloadDirectory),

            _buildItem1('getExternalStorageDirectories',_externalStorageDirectories),
            _buildItem1('getExternalCacheDirectories',_externalCacheDirectories),

          ],
        ),
      ),
    );
  }
}

Each path of the Android system:

Various paths of iOS system:

communicate with

communicate with

Laomeng Flutter blog (330 control usage + actual combat introduction series): http://laomengit.com

Welcome to join the Flutter exchange group (WeChat: laomengit) and follow the public account [Lao Meng Flutter]:

Guess you like

Origin blog.csdn.net/mengks1987/article/details/108657135