老孟導讀:Flutter 中獲取文件路徑,咱們都知道使用 path_provider,但對其目錄對含義不是很清楚,此文介紹 Android、iOS 系統的文件目錄,不一樣場景下建議使用的目錄。android
不一樣的平臺對應的文件系統是不一樣的,好比文件路徑,所以 Flutter 中獲取文件路徑須要原生支持,原生端經過 MethodChannel 傳遞文件路徑到 Flutter,若是沒有特殊的需求,推薦你們使用 Google 官方維護的插件 path_provider。ios
pub 地址:https://pub.flutter-io.cn/packages/path_providergit
Github 地址:https://github.com/flutter/plugins/tree/master/packages/path_provider/path_providergithub
在項目的 pubspec.yaml
文件中添加依賴:sql
dependencies: path_provider: ^1.6.14
執行命令:緩存
flutter pub get
path_provider(版本:1.6.14)提供了8個方法獲取不一樣的文件路徑,目前 Flutter(Flutter 1.20.1 • channel stable )只發布了正式版本的 Android 和 iOS,所以下面僅介紹 Android 和 iOS 平臺的文件路徑。安全
getTemporaryDirectory微信
臨時目錄,適用於下載的緩存文件,此目錄隨時能夠清除,此目錄爲應用程序私有目錄,其餘應用程序沒法訪問此目錄。app
Android 上對應getCacheDir
。ide
iOS上對應NSCachesDirectory
。
getApplicationSupportDirectory
應用程序能夠在其中放置應用程序支持文件的目錄的路徑。
將此文件用於您不想向用戶公開的文件。 您的應用不該將此目錄用於存放用戶數據文件。
在iOS上,對應NSApplicationSupportDirectory
,若是此目錄不存在,則會自動建立。
在Android上,對應getFilesDir
。
getLibraryDirectory
應用程序能夠在其中存儲持久性文件,備份文件以及對用戶不可見的文件的目錄路徑,例如storage.sqlite.db。
在Android上,此函數拋出[UnsupportedError]異常,沒有等效項路徑存在。
getApplicationDocumentsDirectory
應用程序可能在其中放置用戶生成的數據或應用程序沒法從新建立的數據的目錄路徑。
在iOS上,對應NSDocumentDirectory
API。 若是數據不是用戶生成的,考慮使用[getApplicationSupportDirectory]。
在Android上,對應getDataDirectory
API。 若是要讓用戶看到數據,請考慮改用[getExternalStorageDirectory]。
getExternalStorageDirectory
應用程序能夠訪問頂級存儲的目錄的路徑。因爲此功能僅在Android上可用,所以應在發出此函數調用以前肯定當前操做系統。
在iOS上,此功能會引起[UnsupportedError]異常,由於沒法在應用程序的沙箱外部訪問。
在Android上,對應getExternalFilesDir(null)
。
getExternalCacheDirectories
存儲特定於應用程序的外部緩存數據的目錄的路徑。 這些路徑一般位於外部存儲(如單獨的分區或SD卡)上。 電話可能具備多個可用的存儲目錄。
因爲此功能僅在Android上可用,所以應在發出此函數調用以前肯定當前操做系統。
在iOS上,此功能會拋出UnsupportedError,由於這是不可能的在應用程序的沙箱外部訪問。
在Android上,對應Context.getExternalCacheDirs()
或API Level 低於19的Context.getExternalCacheDir()
。
getExternalStorageDirectories
能夠存儲應用程序特定數據的目錄的路徑。 這些路徑一般位於外部存儲(如單獨的分區或SD卡)上。
因爲此功能僅在Android上可用,所以應在發出此函數調用以前肯定當前操做系統。
在iOS上,此功能會拋出UnsupportedError,由於這是不可能的在應用程序的沙箱外部訪問。
在Android上,對應Context.getExternalFilesDirs(String type)
或API Level 低於19的Context.getExternalFilesDir(String type)
。
getDownloadsDirectory
存儲下載文件的目錄的路徑,這一般僅與臺式機操做系統有關。
在Android和iOS上,此函數將引起[UnsupportedError]異常。
若是沒有 Android 或者 iOS開發經驗,看完上面的說明應該是一臉懵逼的,這麼多路徑到底用哪一個?有什麼區別?下面從 Android 和 iOS 平臺的角度介紹其文件路徑,最後給出路徑使用的建議以及使用過程當中須要注意的事項。
Android 文件存儲分爲內部存儲和外部存儲。
用於保存應用的私有文件,其餘應用沒法訪問這些數據,建立的文件在此應用的包名目錄下,沒有 root 權限 的手機沒法在手機的 文件管理 應用中看到此目錄,不過能夠經過 Android Studio 工具查看,路徑爲:data/data/包名:
看下包名下具體的目錄結構:
SharePreferences 和 sqlite 是兩種保存數據的第三方插件。
內部存儲的特色:
外部存儲能夠經過手機的 文件管理 應用查看,
這裏面有一個特殊的目錄:Android/data/包名:
看到這個目錄是否是以爲和內部存儲目錄很是類似,一個包名錶明一個應用程序:
此目錄的特色:
外部存儲除了 Android/data/ 目錄,還有和此目錄同級的目錄,特色:
Android 官方對此目錄的管理愈來愈嚴格, Android 11 系統已經開始強制執行分區存儲,詳情見:https://developer.android.com/preview/privacy/storage?hl=zh-cn
上面說了這麼多,總結以下:
iOS 文件存儲相比 Android 要簡單的多,由於 iOS 對用戶隱私保護很是嚴格,每一個 iOS 應用程序都有一個單獨的文件系統,並且只能在對應的文件系統中進行操做,此區域被稱爲沙盒。
每一個應用沙盒含有3個文件夾:Documents, Library 和 tmp:
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), ], ), ), ); } }
Android 系統各個路徑:
iOS 系統各個路徑:
老孟Flutter博客(330個控件用法+實戰入門系列文章):http://laomengit.com
歡迎加入Flutter交流羣(微信:laomengit)、關注公衆號【老孟Flutter】:
![]() |
![]() |