- File Storage and Access with Xamarin.Android
- Internal vs external storage
- Working with internal storage
- Reading or Writing to files on internal storage
- Using Xamarin.Essentials – File System Helpers
- Hiding files from the MediaStore
- Хранение и доступ к файлам с помощью Xamarin.Android
- Внутреннее и внешнее хранилище
- Работа с внутренним хранилищем
- Чтение или запись в файлы во внутреннем хранилище
- Использование Xamarin. Essentials — вспомогательные средства файловой системы
- Скрытие файлов из MediaStore
File Storage and Access with Xamarin.Android
A common requirement for Android apps is to manipulate files – saving pictures, downloading documents, or exporting data to share with other programs. Android (which is based on Linux) supports this by providing space for file storage. Android groups the filesystem into two different types of storage:
- Internal Storage – this is a portion of the file system that can be accessed only by the application or the operating system.
- External Storage – this is a partition for the storage of files that is accessible by all apps, the user, and possibly other devices. On some devices, external storage may be removable (such as an SD card).
These groupings are conceptual only, and don’t necessarily refer to a single partition or directory on the device. An Android device will always provide partition for internal storage and external storage. It is possible that certain devices may have multiple partitions that are considered to be external storage. Regardless of the partition the APIs for reading, writing, or creating files is the same. There are two sets of APIs that a Xamarin.Android application may use for file access:
- The .NET APIs (provided by Mono and wrapped by Xamarin.Android) – These includes the file system helpers provided by Xamarin.Essentials. The .NET APIs provide the best cross-platform compatibility and as such the focus of this guide will be on these APIs.
- The native Java file access APIs (provided by Java and wrapped by Xamarin.Android) – Java provides its own APIs for reading and writing files. These are a completely acceptable alternative to the .NET APIs, but are specific to Android and are not suitable for apps that are intended to be cross-platform.
Reading and writing to files is almost identical in Xamarin.Android as it is to any other .NET application. The Xamarin.Android app determines the path to the file that will be manipulated, then uses standard .NET idioms for file access. Because the actual paths to internal and external storage may vary from device to device or from Android version to Android version, it is not recommended to hard code the path to the files. Instead, use the Xamarin.Android APIs to determine the path to files. That way, the .NET APIs for reading and writing files exposes the native Android APIs that will help with determining the path to files on internal and external storage.
Before discussing the APIs involved with file access, it is important to understand some of the details surrounding internal and external storage. This will be discussed in the next section.
Internal vs external storage
Conceptually, internal storage and external storage are very similar – they are both places at which a Xamarin.Android app may save files. This similarity may be confusing for developers who are not familiar with Android as it is not clear when an app should use internal storage vs external storage.
Internal storage refers to the non-volatile memory that Android allocates to the operating system, APKs, and for individual apps. This space is not accessible except by the operating system or apps. Android will allocate a directory in the internal storage partition for each app. When the app is uninstalled, all the files that are kept on internal storage in that directory will also be deleted. Internal storage is best suited for files that are only accessible to the app and that will not be shared with other apps or will have very little value once the app is uninstalled. On Android 6.0 or higher, files on internal storage may be automatically backed up by Google using the Auto Backup feature in Android 6.0. Internal storage has the following disadvantages:
- Files cannot be shared.
- Files will be deleted when the app is uninstalled.
- The space available on internal storage maybe limited.
External storage refers to file storage that is not internal storage and not exclusively accessible to an app. The primary purpose of external storage is to provide a place to put files that are meant to be shared between apps or that are too large to fit on the internal storage. The advantage of external storage is that it typically has much more space for files than internal storage. However, external storage is not always guaranteed to be present on a device and may require special permission from the user to access it.
For devices that support multiple users, Android will provide each user their own directory on both internal and external storage. This directory is inaccessible to other users on the device. This separation is invisible to apps as long as they do not hardcode paths to files on internal or external storage.
As a rule of thumb, Xamarin.Android apps should prefer saving their files on internal storage when it is reasonable, and rely on external storage when files need to be shared with other apps, are very large, or should be retained even if the app is uninstalled. For example, a configuration file is best suited for a internal storage as it has no importance except to the app that creates it. In contrast, photos are a good candidate for external storage. They can be very large and in many cases the user may want to share them or access them even if the app is uninstalled.
This guide will focus on internal storage. Please see the guide External storage for details on using external storage in a Xamarin.Android application.
Working with internal storage
The internal storage directory for an application is determined by the operating system, and is exposed to Android apps by the Android.Content.Context.FilesDir property. This will return a Java.IO.File object representing the directory that Android has dedicated exclusively for the app. For example, an app with the package name com.companyname the internal storage directory might be:
This document will refer to the internal storage directory as INTERNAL_STORAGE.
The exact path to the internal storage directory can vary from device to device and between versions of Android. Because of this, apps must not hard code the path to the internal files storage directory, and instead use the Xamarin.Android APIs, such as System.Environment.GetFolderPath() .
To maximize code sharing, Xamarin.Android apps (or Xamarin.Forms apps targeting Xamarin.Android) should use the System.Environment.GetFolderPath() method. In Xamarin.Android, this method will return a string for a directory that is the same location as Android.Content.Context.FilesDir . This method takes an enum, System.Environment.SpecialFolder , which is used to identify a set of enumerated constants that represent the paths of special folders used by the operating system. Not all of the System.Environment.SpecialFolder values will map to a valid directory on Xamarin.Android. The following table describes what path can be expected for a given value of System.Environment.SpecialFolder :
System.Environment.SpecialFolder | Path |
---|---|
ApplicationData | INTERNAL_STORAGE/.config |
Desktop | INTERNAL_STORAGE/Desktop |
LocalApplicationData | INTERNAL_STORAGE/.local/share |
MyDocuments | INTERNAL_STORAGE |
MyMusic | INTERNAL_STORAGE/Music |
MyPictures | INTERNAL_STORAGE/Pictures |
MyVideos | INTERNAL_STORAGE/Videos |
Personal | INTERNAL_STORAGE |
Fonts | INTERNAL_STORAGE/.fonts |
Templates | INTERNAL_STORAGE/Templates |
CommonApplicationData | /usr/share |
CommonApplicationData | /usr/share |
Reading or Writing to files on internal storage
Any of the C# APIs for writing to a file are sufficient; all that is necessary is to get the path to the file that is in the directory allocated to the application. It is strongly recommended that the async versions of the .NET APIs are used to minimize any issues that may be associate with file access blocking the main thread.
This code snippet is one example of writing an integer to a UTF-8 text file to the internal storage directory of an application:
The next code snippet provides one way to read an integer value that was stored in a text file:
Using Xamarin.Essentials – File System Helpers
Xamarin.Essentials is a set of APIs for writing cross-platform compatible code. The File System Helpers is a class that contains a series of helpers to simplify locating the application’s cache and data directories. This code snippet provides an example of how to find the internal storage directory and the cache directory for an app:
Hiding files from the MediaStore
The MediaStore is an Android component that collects meta data about media files (videos, music, images) on an Android device. Its purpose is simplify the sharing of these files across all Android apps on the device.
Private files will not show up as shareable media. For example, if an app saves a picture to its private external storage, then that file will not be picked up by the media scanner ( MediaStore ).
Public files will be picked up by MediaStore . Directories that have a zero byte file name .NOMEDIA will not be scanned by MediaStore .
Источник
Хранение и доступ к файлам с помощью Xamarin.Android
Распространенным требованием для приложений Android является работа с файлами — сохранение изображений, скачивание документов или экспорт данных для совместного использования с другими программами. Android (на основе Linux) поддерживает эти операции, предоставляя пространство для хранения файлов. Android группирует файловую систему в два разных типа хранилища.
- внутренняя служба хранилища — это часть файловой системы, доступ к которой может получить только приложение или операционная система.
- внешние служба хранилища — это раздел для хранения файлов, доступных для всех приложений, пользователя и, возможно, других устройств. На некоторых устройствах внешнее хранилище может быть съемным (например, SD-карта).
Эти группы существуют на понятийном уровне и не обязательно ссылаются на отдельный раздел или каталог на устройстве. Устройство Android всегда будет предоставлять раздел для внутреннего и внешнего хранилища. Некоторые устройства могут иметь несколько разделов, которые считаются внешним хранилищем. Независимо от раздела API для чтения, записи или создания файлов одинаковы. Существует два набора API, которые приложение Xamarin.Android может использовать для доступа к файлам.
- API-интерфейсы .NET (предоставленные Mono и Упакованные Xamarin. Android) — включают вспомогательные функции файловой системы , предоставляемые Xamarin. Essentials. API .NET обеспечивают лучшую совместимость с различными платформами, поэтому в данной статье мы сосредоточимся на этих API.
- Собственные API-интерфейсы доступа к файлам Java (предоставляемые Java и Упакованные Xamarin. Android) — Java предоставляет собственные API для чтения и записи файлов. Это полностью приемлемая альтернатива API .NET, но они относятся только к Android и не подходят для кросс-платформенных приложений.
В Xamarin.Android чтение и запись в файлы практически идентична этим процессам в любых других приложениях .NET. Приложение Xamarin.Android определяет путь к файлу, который будет обработан, а затем использует стандартные идиомы .NET для доступа к файлам. Так как фактические пути к внутреннему и внешнему хранилищу могут отличаться в зависимости от устройства или от версии Android, не рекомендуется жестко задавать путь к файлам. Вместо этого используйте API Xamarin.Android, чтобы определить путь к файлам. Таким образом, API .NET для чтения и записи файлов предоставляют собственные API Android, которые помогут определить путь к файлам во внутреннем и внешнем хранилище.
Прежде чем обсуждать API, участвующие в доступе к файлам, важно понять некоторые сведения о внутреннем и внешнем хранилище. О них мы поговорим в следующем разделе.
Внутреннее и внешнее хранилище
По сути, внутреннее хранилище и внешнее хранилище очень похожи — они являются местами, в которых приложение Xamarin. Android может сохранять файлы. Такое сходство может запутывать разработчиков, не знакомых с Android, так как неясно, когда приложение должно использовать внутреннее хранилище, а когда — внешнее.
Внутреннее хранилище относится к энергонезависимой памяти, которую Android выделяет операционной системе, APK и отдельным приложениям. Это пространство доступно только операционной системе или приложениям. Android выделит каталог в разделе внутреннего хранилища для каждого приложения. При удалении приложения все файлы, хранящиеся во внутреннем хранилище в этом каталоге, также будут удалены. Внутреннее хранилище лучше всего подходит для файлов, доступных только для приложения, которые не будут использоваться совместно с другими приложениями или будут почти бесполезными после удаления приложения. В Android 6.0 или более поздней версии для файлов во внутреннем хранилище может автоматически создаваться резервная копия с помощью Google с использованием функции автоматического резервного копирования в Android 6.0. Внутреннее хранилище имеет следующие недостатки.
- Невозможно предоставить общий доступ к файлам.
- Файлы будут удалены при удалении приложения.
- Пространство, доступное во внутренней памяти, может быть ограничено.
Внешнее хранилище относится к хранилищу файлов, которое не является внутренним хранилищем и доступно не только для приложения. Основное предназначение внешнего хранилища — предоставление места для размещения файлов для совместного использования приложениями или файлов слишком большого размера для внутреннего хранилища. Преимущество внешнего хранилища состоит в том, что оно предоставляет для файлов гораздо больше места, чем внутреннее хранилище. Однако внешнее хранилище не всегда присутствует на устройстве и может потребовать от пользователя специального разрешения для доступа к нему.
Для устройств, поддерживающих несколько пользователей, Android предоставит каждому пользователю собственный каталог как во внутреннем, так и во внешнем хранилище. Этот каталог недоступен для других пользователей на устройстве. Это разделение невидимо для приложений, если они не используют жестко запрограммированные пути к файлам во внутреннем или внешнем хранилище.
Как правило, приложения Xamarin.Android должны сохранять свои файлы во внутреннем хранилище, когда это разумно, и использовать внешнее хранилище, если файлы должны быть доступны другим приложениям, имеют большой размер или должны сохраняться даже при удалении приложения. Например, файл конфигурации лучше всего подходит для внутреннего хранилища, так как он важен только для приложения, которое его создает. Фотографии, напротив, лучше хранить во внешнем хранилище. Они могут быть очень большими, и часто пользователю может потребоваться предоставить или получить доступ к ним, даже если приложение удалено.
В этом руководстве основное внимание уделяется внутреннему хранилищу. Дополнительные сведения об использовании внешнего хранилища в приложении Xamarin.Android см. в разделе Внешнее хранилище.
Работа с внутренним хранилищем
Каталог внутреннего хранилища для приложения определяется операционной системой и предоставляется приложениям Android с помощью свойства Android.Content.Context.FilesDir . Будет возвращен объект Java.IO.File , представляющий каталог, выделенный Android исключительно для приложения. Например, для приложения с именем пакета com.companyname каталогом внутреннего хранилища может быть:
Этот документ будет ссылаться на внутренний каталог хранилища как на INTERNAL_STORAGE.
Точный путь к каталогу внутреннего хранилища может отличаться на разных устройствах и в разных версиях Android. По этой причине приложения не должны жестко кодировать путь к каталогу внутреннего хранилища файлов и вместо этого должны использовать интерфейсы API Xamarin.Android, например System.Environment.GetFolderPath() .
Чтобы максимально увеличить общий доступ к коду, приложения Xamarin.Android (или приложения Xamarin.Forms для Xamarin.Android) должны использовать метод System.Environment.GetFolderPath() . В Xamarin.Android этот метод возвращает строку для каталога, который находится в том же расположении, что и Android.Content.Context.FilesDir . Этот метод принимает перечисление, System.Environment.SpecialFolder , которое используется для определения набора перечислимых констант, представляющих пути специальных папок, используемых операционной системой. Не все значения System.Environment.SpecialFolder будут сопоставляться с допустимым каталогом в Xamarin.Android. В следующей таблице описано, каким может быть путь для заданного значения System.Environment.SpecialFolder :
System.Environment.SpecialFolder | путь |
---|---|
ApplicationData | INTERNAL_STORAGEи .config |
Desktop | INTERNAL_STORAGE/Desktop |
LocalApplicationData | INTERNAL_STORAGE/.local/share |
MyDocuments | INTERNAL_STORAGE |
MyMusic | INTERNAL_STORAGE/Мусик |
MyPictures | INTERNAL_STORAGE/пиктурес |
MyVideos | INTERNAL_STORAGE/видеос |
Personal | INTERNAL_STORAGE |
Fonts | INTERNAL_STORAGE/.Фонтс |
Templates | INTERNAL_STORAGE/темплатес |
CommonApplicationData | /usr/share |
CommonApplicationData | /usr/share |
Чтение или запись в файлы во внутреннем хранилище
Можно использовать любой API C# для записи в файл. Достаточно просто получить путь к файлу, который находится в каталоге, выделенном для приложения. Настоятельно рекомендуется использовать асинхронные версии API .NET, чтобы возникало меньше проблем с блокировкой основного потока в связи с доступом к файлу.
Этот фрагмент кода представляет один из примеров записи целого числа в текстовый файл в кодировке UTF-8 в каталоге внутреннего хранилища приложения:
Следующий фрагмент кода предоставляет один из способов чтения целочисленного значения, хранящегося в текстовом файле:
Использование Xamarin. Essentials — вспомогательные средства файловой системы
Xamarin.Essentials — это набор API для написания кода, совместимого с разными платформами. Вспомогательные функции файловой системы — это класс, который содержит ряд вспомогательных функций для упрощения поиска каталогов кэша и данных приложения. В этом фрагменте кода приведен пример того, как найти каталог внутреннего хранилища и каталог кэша для приложения:
Скрытие файлов из MediaStore
MediaStore — это компонент Android, который собирает метаданные о файлах мультимедиа (видео, музыка, изображения) на устройстве Android. Его цель — упростить совместное использование этих файлов во всех приложениях Android на устройстве.
Закрытые файлы не будут отображаться как общие мультимедиа. Например, если приложение сохраняет изображение в закрытом внешнем хранилище, сканер мультимедиа ( MediaStore ) не получит этот файл.
Общедоступные файлы будут доступны для MediaStore . Каталоги, имеющие нулевое имя файла в байтах . НОСИТЕЛЬ не будет проверяться .
Источник