Нажмите "Enter", чтобы перейти к содержанию

Android работа с файлами: Java и Android | Работа с файловой системой

Android: Хранение данных и файлов

Статья проплачена кошками — всемирно известными производителями котят.

Если статья вам понравилась, то можете поддержать проект.

Внешняя карта памяти
Состояние на текущий момент (Android 10 Q)

Устройство на Android содержит в себе набор приложений.

Хранение файлов и данных можно условно разделить на две группы: во внутреннем или внешнем хранилище.

Каждое приложение хранит свой набор файлов, например, файлы базы данных или файлы настроек. Обычно файлы хранятся во внутреннем хранилище устройства и доступны только самому приложению.

Приложение может также иметь собственные документы, картинки, музыку. Они занимают больше места, поэтому для приложения выделяется место во внешнем хранилище. Но доступ к файлам остаётся прежним — только самому приложению.

При деинсталляции приложения все файлы из хранилищ будут удалены.

Но изолированные файлы не всегда удобны для пользователя.

Ведь мы хотим взаимодействовать с ними. Например, поделиться фотографией своего кота через месседжер. Поэтому на устройстве есть особое хранилище — Shared storage (разделяемое хранилище).

Android поддерживает различные варианты хранения данных и файлов.

  • Специфичные для приложения файлы. Доступ к файлам имеет только приложение, их создавшее. Файлы могут находиться во внутреннем и внешнем хранилище. У других приложений нет доступа (кроме случаев, когда файлы хранятся на внешнем хранилище). Методы getFilesDir(), getCacheDir(), getExternalFilesDir(), getExternalCacheDir(). Разрешений на доступ не требуется. Файлы удаляются, когда приложение удаляется пользователем.
  • Разделяемое хранилище. Приложение может создавать файлы, которыми готово поделиться с другими приложениями — медиафайлы (картинки, видео, аудио), документы. Для медифайлов требуется разрешение READ_EXTERNAL_STORAGE или WRITE_EXTERNAL_STORAGE
    .
  • Настройки. Хранение простых данных по принципу ключ-значение. Доступно внутри приложения. Реализовано через Jetpack Preferences. Настройки удаляются, когда приложение удаляется пользователем.
  • Базы данных. Хранение данных в SQLite. На данный момент реализовано через библиотеку Room. Доступ только у родного приложения.

В зависимости от ваших потребностей, нужно выбрать нужный вариант хранения данных.

Следует быть осторожным при работе с внутренним и внешним хранилищем. Внутренне хранилище всегда есть в системе, но оно может быть не слишком большим по объёму. Вдобавок к внутреннему хранилищу, устройство может иметь внешнее хранилище. В старых моделях таким хранилищем выступала съёмная SD-карта. Сейчас чаще используют встроенную и недоступную для извлечения флеш-память. Если ваше приложение слишком большое, можно попросить систему устанавливать программу во внешнее хранилище, указав просьбу в манифесте.


<manifest 
    ...
    android:installLocation="preferExternal">
    . ..
</manifest>

В разных версиях Android требования к разрешению для работы с внешним хранилищем постоянно менялись. На данный момент (Android 10, API 29) требования выглядят следующим образом.

Приложение может иметь доступ к собственным файлам, которые находятся во внешнем хранилище. Также может получить доступ к определённым общим файлам на внешнем хранилище.

Доступ к общим файлам достигается через FileProvider API или контент-провайдеры.

Для просмотра файлов через студию используйте инструмент Device File Explorer.

Внешняя карта памяти

Когда появились первые устройства на Android, то практически у всех были внешние карточки памяти, которые вставлялись в телефон. Обычно там хранили фотки, видео и свои файлы. Всё было понятно — были различные методы для доступа к файловой системе. А потом началась чехарда. В телефонах также была и собственная «внешняя» память. Она вроде как и внешняя, но вставлена на заводе и вытащить её пользователь не мог, т.

е. практически внутренняя. Затем пошла мода на телефоны, у которых была только такая внутреннее-внешняя карта. Пользователи поворчали, но привыкли. Сейчас встречаются оба варианта. Как правило, у телефонов с спрятанной картой больше памяти и выше степень водонепроницаемости.

Подобные фокусы с картой породили и другую проблему — Гугл озаботился безопасностью файлов и стала думать, как осложнить жизнь разработчику. С выходом каждой новой версии системы компания то давала добро на полный доступ к карточке, то ограничивала, то давала права с ограничениями, то откатывала свои решения назад. Короче, запутались сами и запутали всех.

Попробуем немного разобраться с этим зоопарком. Но помните, что процесс путаницы продолжается.

При подготовке материала я опирался на письма некоторых читателей сайта, которые присылали свои мысли по этому поводу. Спасибо им за структуризацию материала.

От читателя:

Вот что я (кажется) понял, попытавшись загрузить картинку с внешней SD карточки.

External это не External
«EXTERNAL_STORAGE» называется так не потому, что это внешняя память по отношению к устройству, а потому что она выглядит как внешняя память для компьютера, если устройство подключить кабелем к компьютеру. Причём именно выглядит, потому что обмен идёт по протоколу MTP – устройство только показывает компьютеру список папок и файлов, а при необходимости открыть или скопировать файл он специально загружается на компьютер, в отличие от настоящей флешки, файлы которой становятся файлами в файловой системе самого компьютера. Обмен по MTP позволяет устройству продолжать работать, когда оно подключено к компьютеру.

Emulated это не Emulated
Сначала я пытался прочесть файл с карточки на эмуляторе (из этого так ничего и не вышло). Функция getExternalStorageDirectory() давала мне /storage/emulated/0, и я думал, что «emulated» – это потому что на эмуляторе. Но когда я подцепил реальный планшет, слово «emulated» никуда не исчезло. Я стал рыться в интернете и обнаружил, что «Emulated storage is provided by exposing a portion of internal storage through an emulation layer and has been available since Android 3.0.» – то есть это просто кусок внутренней памяти, которая путём какой-то эмуляции делается доступной для пользователя, в отличие от собственно внутренней памяти.

При этом с точки зрения системы доступная для пользователя папка называется /storage/emulated/0, а при подключении к компьютеру по USB это просто одна из двух главных папок устройства – у меня в Windows Explorer она называется Tablet. Вторая папка у меня называется Card, и это и есть настоящая внешняя карточка.

Нет стандартных средств добраться из приложения до файлов на внешней карточке. Все попытки добраться до настоящей внешней карточки делаются с помощью неких трюков. Самое интересное, что я нашел, это статья на http://futurewithdreams.blogspot.com/2014/01/get-external-sdcard-location-in-android.html — парень читает таблицу смонтированных устройств /proc/mounts, таблицу volume daemons /system/etc/vold. fstab, сравнивает их и выбирает те тома, которые оказываются съёмными (с помощью

Environment.isExternalStorageRemovable()).

Оказалось, что несистемным приложениям в принципе запрещено напрямую обращаться к съёмной карточке! Похоже, что это было так всегда, но вот начиная с версии Android 6 Marshmallow написано: внешняя карточка может быть определена как Portable либо Adoptable. Adoptable – это как бы «усыновляемая» память которая может быть «adopted», то есть взята в систему (примерно как кот с улицы в дом – это тоже называется to adopt) и использована как внутренняя. Для этого ее надо особым образом отформатировать и не вынимать, иначе не факт, что система продолжит нормально работать.

Portable – это нормальная съёмная карточка, но несистемным приложениям запрещено обращаться из программ к файлам на ней! Вот что написано в https://source.android.com/devices/storage/traditional.html:

Android 6.0 supports portable storage devices which are only connected to the device for a short period of time, like USB flash drives.

When a user inserts a new portable device, the platform shows a notification to let them copy or manage the contents of that device. In Android 6.0, any device that is not adopted is considered portable. Because portable storage is connected for only a short time, the platform avoids heavy operations such as media scanning. Third-party apps must go through the Storage Access Framework to interact with files on portable storage; direct access is explicitly blocked for privacy and security reasons.

Если я правильно понял, этот самый Storage Access Framework позволяет работать с документом на карточке через диалог (открыть файл/сохранить файл), а вот прочитать или записать файл на карточке непосредственно из программы невозможно.

Общий вывод – реально из программы можно работать только с файлами на предоставляемой пользователю части встроенной памяти устройства, а на съёмной карточке – нет.

Это напоминает войну Microsoft с пользователями и разработчиками по поводу диска C:, компания уговаривала не устраивать беспорядок в корне этого диска, а ещё лучше — перенести свои файлы на другой диск. Но явных запретов не было.

Состояние на текущий момент

Гугл утверждает, что с версии Android 10 Q стандартный доступ к файлам будет прекращён. Ещё в Android 4.4 появился Storage Access Framework, который и должен стать заменой для работы с файлами.

Методы Environment.getExternalStorageDirectory() и Environment.getExternalStoragePublicDirectory() признаны устаревшими и будут недоступны. Даже если они будут возвращать корректные значения, ими вы не сможете воспользоваться.

В Android 7.0 добавили исключение FileUriExposedException, чтобы разработчики перестали использовать схему file://Uri.

Можно создавать файлы в корневой папке карточки при помощи Environment.getExternalStorageDirectory(), а также папки с вложенными файлами. Если папка уже существует, то у вас не будет доступа на запись (если это не ваша папка).

Если вы что-то записали, то сможете и прочитать. Чужое читать нельзя.

Кстати, разрешения на чтение и запись файлов не требуются, а READ_EXTERNAL_STORAGE и WRITE_EXTERNAL_STORAGE объявлены устаревшими.

Другие приложения не могут получить доступ к файлам вашего приложения. Файлы, которые вы создали через getExternalFilesDir(), доступны через Storage Access Framework, кроме файлов, созданных в корне карточки (что-то я совсем запутался). Ещё можно дать доступ через FileProvider.

При подключении USB-кабеля через getExternalFilesDir(), вы можете увидеть свои файлы и папки, а также файлы и папки пользователя. При этом файлы и папки пользователя на корневой папке вы не увидите. Вам не поможет даже adb или Device File Explorer студии.

Что делать?

Пользуйтесь методами класса Context, типа getExternalFilesDir(), getExternalCacheDir(), getExternalMediaDirs(), getObbDir() и им подобными, чтобы найти место для записи.

Используйте Storage Access Framework.

Используйте MediaStore для мультимедийных файлов.

Используйте FileProvider, чтобы файлы были видимы другим приложениям через ACTION_VIEW/ACTION_SEND.

Android 10: Появился новый флаг android:allowExternalStorageSandbox=»false» и метод Environment.isExternalStorageSandboxed() для работы с песочницей. Флаг android:requestLegacyExternalStorage=»true» для приложений, которые ещё используют старую модель доступа к файлам.

Как временное решение можно добавить в блок манифеста application атрибут android:requestLegacyExternalStorage=»true», чтобы доступ к файлам был как раньше в Android 4.4-9.0.

Android 11

Если вы создаёте файловый менеджер, то ему нужны возможности для просмотра файлов. Для этого следует установить разрешение MANAGE_EXTERNAL_STORAGE или использовать атрибут android:requestLegacyExternalStorage=»true» (см. выше).

Дополнительное чтение

Обсуждение на Reddit

Реклама

Работа с файлами (External Storage)

В этой статье мы поговорим как в Kotlin работать с External Storage файлами. Рассмотрим следующие вопросы: как записать файл в Kotlin External Storage, как прочитать файл в Kotlin External Storage, как фильтровать и найти файл в Kotlin External Storage директории, в том числе и рекурсивный поиск файлов.

Разрешение на запись в External Storage

Для того, чтобы работать с внешней памятью на Android устройствах нужно получить разрешение на запись, для этого необходимо сделать несколько шагов.

  1. Добавим разрешение в AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

И для Android устройств ниже версии 10, в AndroidManifest.xml пропишем авто получение разрешения.

<application
        android:requestLegacyExternalStorage="true"
...

2. Проверим наличие разрешения на запись следующей функцией:

// Получить разрешение на ЗАПИСЬ
fun  checkWritePermissions(){
   when{
       ContextCompat. checkSelfPermission(APP, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED -> {
          //РАЗРЕШЕНИЕ УЖЕ ПОЛУЧЕНО
       }
       else -> {
           //РАЗРЕШЕНИЕ НЕ ПОЛУЧЕНО
           // Запрашиваем разрешение у пользователя
           permisLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
       }
   }
}

3. Установим слушатель разрешения на запись следующей функцией:

// Слушатель разрешения
fun  registerPermissionListener(){
    permisLauncher = APP.registerForActivityResult(ActivityResultContracts.RequestPermission()){
        if(it) {
            //РАЗРЕШЕНИЕ ПОЛУЧЕНО
        }else{
            //ПОЛЬЗОВАТЕЛЬ ОТКАЗАЛ В РАЗРЕШЕНИИ
            // Запустим диалог поясняющий пользователю, зачем нужно это разрешение
            showDialog()
        }
    }
}

4. Запустим диалог поясняющий пользователю, зачем нужно это разрешение

// Диалог поясняющий необходимость разрешения
fun showDialog() {
   AlertDialog.Builder(APP)
      .setTitle("Разрешение на запись")
      .setMessage("Дайте разрешение на запись. В противном случае приложение работать не будет!")
      .setPositiveButton("Разрешить") { dialog, which ->
          // Снова запрашиваем разрешение
          checkWritePermissions()
      }
      .setNegativeButton("Отклонить") { dialog, which ->
          // Закрываем приложение
          APP.finish()
      }
      .show()
}

5. Теперь в MainActivity в методе onCreate вызовем методы созданные ранее:

. ..
override fun onCreate(savedInstanceState: Bundle?) {
...
        registerPermissionListener()
        checkWritePermissions()
...

Теперь при старте, приложение будет проверять и при необходимости запрашивать разрешение на запись в External Storage. Можно приступать к работе с файлами.

Запись файла

Задача
Создадим метод, который создает файл “hello.txt” и записывает в него текст “Запись 1“.

Решение
Входными параметрами функции будут: путь (filePath), имя файла (fileName), текст (text). Все действия обернём в try catch для исключения ошибок.

    // Записать файл
    fun writeFile(filePath: String, fileName: String, text: String) {
        try {
            //Создается объект файла, при этом путь к файлу находиться методом Environment
            val myFile = File(Environment. getExternalStorageDirectory().toString() + "/" + filePath + fileName)
            // Создается файл, если он не был создан
            myFile.createNewFile()
            // После чего создаем поток для записи
            val outputStream = FileOutputStream(myFile)
            // Производим непосредственно запись
            outputStream.write(text.toByteArray())
            // Закрываем поток
            outputStream.close()
            // Просто для удобства визуального контроля исполнения метода в приложении
            Toast.makeText(this, "File is write", Toast.LENGTH_SHORT).show()
        } catch (e: Exception) {
            e.printStackTrace()
            Toast.makeText(this, "File is not write", Toast.LENGTH_SHORT).show()
        }
    }

Вызвать функцию можно следующим образом:

writeFile("download/", "hello. txt", "Запись 1")

Эта функция создаст файл “hello.txt” в папке Download и запишет в него следующий текст “Запись 1“.

Чтение файла

Теперь получим текст из ранее созданного файла.

Входными параметрами функции будут: путь (filePath), имя файла (fileName). Выходной параметр типа String. То есть на выходи функции получим строку с текстом из файла.

    // Чтение файла
    fun readFile(filePath: String, fileName: String): String {
        // Аналогично создается объект файла
        val myFile = File(Environment.getExternalStorageDirectory().toString() + "/" + filePath + fileName)
        try {
            val inputStream = FileInputStream(myFile)
            // Буферизируем данные из выходного потока файла
            val bufferedReader = BufferedReader(InputStreamReader(inputStream))
            // Класс для создания строк из последовательностей символов
            val stringBuilder = StringBuilder()
            var line: String?
            try {
                // Производим построчное считывание данных из файла в конструктор строки,
                while (bufferedReader. readLine().also { line = it } != null) {
                    stringBuilder.append(line)
                }
                return stringBuilder.toString()
            } catch (e: IOException) {
                e.printStackTrace()
                return ""
            }
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
            return ""
        }
    }

Вызвать функцию можно следующим образом:

val text = readFile("download/", "hello.txt")

Находим файлы в директории с нужным расширением

Создадим функцию для поиска фалов в главной директории с расширением “.txt” рекурсивно (то есть включая все подкаталоги)

Входными параметрами функции будут: путь (filePath), фильтр (filter). Выходной параметр типа ArrayList<File>. То есть на выходи функции получим список файлов.

fun allFilesInDir(filePath: String, filter: String): ArrayList<File>{
    var filesFromDir = ArrayList<File>()
    val path = Environment.getExternalStorageDirectory().toString() + "/" + filePath
    val directory = File(path)
    val files = directory.walkTopDown()
    // Перебираем все файлы
    for (file in files) {
       // Отсеиваем файлы подходящие под фильтр
       if(file.name.endsWith(filter)) {
          filesFromDir.add(file)
       }
    }
        return filesFromDir
}

Вызовем эту функцию и получим результат её работы:

val text = allFilesInDir("", ". txt").map { it.name }.toString()

Заключение

Работа с External Storage файлами в Kotlin очень лаконичная и удобная. С типом данных File вы можете делать много операций, таких как: удалить, переименовать, получить имя, расширение, размер файла и многое другое.

Поделись с друзьями:

Управление всеми файлами на устройстве хранения

Большинство приложений, которым требуется доступ к общему хранилищу, могут следовать лучшим практика обмена медиа файлы и совместное использование файлы. Однако некоторые приложения имеют основной вариант использования, который требует широкого доступа к файлам на устройстве, но не может сделать это эффективно, используя передовые методы хранения, обеспечивающие конфиденциальность. Android предоставляет специальный доступ к приложению под названием Доступ ко всем файлам для этих ситуации.

Например, для основного варианта использования антивирусного приложения может потребоваться регулярное сканирование множества файлов в разных каталогах. Если это сканирование требует повторного взаимодействия с пользователем для выбора каталогов с помощью системного средства выбора файлов, это может обеспечить плохой пользовательский опыт. Другие варианты использования, такие как приложения для управления файлами, приложения для резервного копирования и восстановления, а также приложения для управления документами — могут потребоваться аналогичные соображения.

Запросить доступ ко всем файлам

Приложение может запросить доступ ко всем файлам у пользователя, выполнив следующие действия:

  1. Объявить УПРАВЛЕНИЕ_ВНЕШНИМ_ХРАНИЛИЩЕМ разрешение в манифесте.
  2. Используйте ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION намеренное действие, чтобы направить пользователей на страницу системных настроек, где они могут включить следующий параметр для вашего приложения: Разрешить доступ для управления всеми файлами .

Чтобы определить, предоставлено ли вашему приложению УПРАВЛЕНИЕ_ВНЕШНИМ_ХРАНИЛИЩЕМ разрешение, звоните Environment.isExternalStorageManager() .

Операции, разрешенные MANAGE_EXTERNAL_STORAGE

Разрешение MANAGE_EXTERNAL_STORAGE предоставляет следующее:

  • Доступ для чтения и записи ко всем файлам в общем хранилище.

    Примечание: Каталог /sdcard/Android/media ⁠ является частью общего хранилища.
  • Доступ к содержимому MediaStore.Files табл.

  • Доступ к корневому каталогу USB-накопителя (OTG) и SD карта.

  • Доступ для записи ко всем каталогам внутренней памяти⁠, кроме /Android/data/ , /sdcard/Android и большинство подкаталогов /sdcard/Android . Этот доступ для записи включает прямой доступ к файлу доступ к пути.

    Приложения, которым предоставлено это разрешение, по-прежнему не могут получить доступ к каталоги, принадлежащие другим приложениям потому что эти каталоги отображаются как подкаталоги Android/data/ на объем хранилища.

Когда приложение имеет разрешение MANAGE_EXTERNAL_STORAGE , оно может получить доступ к этим дополнительные файлы и каталоги с помощью MediaStore API или прямой файл пути. Когда вы используете Платформа доступа к хранилищу, однако вы можете получить доступ к файлу или каталогу только в том случае, если вы можете сделать это без с разрешением MANAGE_EXTERNAL_STORAGE .

Вызов действия по управлению хранилищем другого приложения

В Android 12 (уровень API 31) и более поздних версиях приложения, УПРАВЛЕНИЕ_ВНЕШНИМ_ХРАНИЛИЩЕМ разрешение и QUERY_ALL_PACKAGES разрешение — например, приложения для управления файлами — могут использовать getManageSpaceActivityIntent() для отправки пользователей в настраиваемое управление пространством другого приложения активность.

Метод getManageSpaceActivityIntent() принимает имя пакета и код запроса и возвращает одно из следующих значений:

  • A PendingIntent , если приложение с указанное имя пакета определило пользовательское действие «управление пространством». Файл приложение управления, вызвавшее метод getManageSpaceActivityIntent() , может затем вызвать возвращенное намерение для отправки пользователей в настраиваемую активность.
  • null , если приложение с указанным именем пакета не определяет «управление космическая деятельность.

Включить MANAGE_EXTERNAL_STORAGE для тестирования

Чтобы узнать, как MANAGE_EXTERNAL_STORAGE 9Разрешение 0015 влияет на ваше приложение, вы можно включить разрешение для целей тестирования. Для этого выполните следующее команда на компьютере, подключенном к вашему тестовому устройству:

набор приложений оболочки adb --uid  PACKAGE_NAME  MANAGE_EXTERNAL_STORAGE разрешить
 

Уведомление Google Play

В этом разделе содержится уведомление для разработчиков, публикующих приложения в Google Play.

Чтобы ограничить широкий доступ к общему хранилищу, магазин Google Play обновил свой политика для оценки приложений, предназначенных для Android 11 (уровень API 30) или выше, и запроса "Доступ ко всем файлам" через MANAGE_EXTERNAL_STORAGE разрешение. Эта политика вступает в силу в мае 2021 г.

Если ваше приложение предназначено для Android 11 или более поздней версии и объявляет MANAGE_EXTERNAL_STORAGE разрешение, Android Studio показывает предупреждение о том, что появляется на рисунке 1. Это предупреждение напоминает вам, что «в магазине Google Play есть политика, ограничивающая использование разрешения.

Рисунок 1. Предупреждение Lint в Android Studio, которое напоминает вам о Политика Google Play в отношении УПРАВЛЕНИЕ_ВНЕШНИМ_ХРАНИЛИЩЕМ разрешение.

Вы должны запрашивать разрешение MANAGE_EXTERNAL_STORAGE только тогда, когда ваше приложение не может эффективно использовать более безопасные для конфиденциальности API, такие как Storage Access Framework или медиа API магазина. Кроме того, использование приложения разрешения должны подпадать под разрешенное использование и должны быть непосредственно связаны с основной функционал приложения. Если ваше приложение включает вариант использования, как и в следующих примерах, скорее всего, будет разрешено запрашивать MANAGE_EXTERNAL_STORAGE разрешение:

  • Файловые менеджеры
  • Резервное копирование и восстановление приложений
  • Антивирусные приложения
  • Приложения для управления документами
  • Поиск файлов на устройстве
  • Шифрование дисков и файлов
  • Миграция данных с одного устройства на другое

Внутренняя память в Android с примером

xml версия = "1. 0" encoding = "utf-8" ?>

< androidx.constraintlayout.widget.ConstraintLayout

     xmlns:android = "http://schemas .android.com/apk/res/android"

     xmlns:app = "http://schemas.android.com/apk/res-auto"

     xmlns: инструменты = "http://schemas.android.com/tools"

     android:layout_width = "match_parent"

     android:layout_height = "match_parent"

     tools:context = ". MainActivity" >

 

     < TextView

         android:id = "@+id/textView2"

         android:layout_width = "337dp"

         android:layout_height = "28dp "

Android: Текст = " Содержание файла "

Android: TextAlenment = " = "9 = " = " .0005

         android:textColor = "#000"

         android:textSize = "24sp"

         android:textStyle = "bold "

Приложение: Layout_constraintbottom_tobottomof = " Parent "

App: Layout_Constraintleftf_tolef_toleof . 0015 = "parent"

         app:layout_constraintRight_toRightOf = "parent"

         app:layout_constraintTop_toTopOf = "parent"

         app: layout_constraintVertical_bias = "0,52" />

 

     < Кнопка

         android:id = "@+id/write_button"

         android:layout_width = "wrap_content"

         android:layout_height = "48DP"

Android: Layout_marginstart = "160DP"

и LAYLIDGINGINGINGER: LAYDINGIRIDGINGIRING_MALIRIDGERIDINGIRIP0015 = "159dp"

         android:layout_marginBottom = "16dp"

         android:text = "Write"

         app: layout_constraintBottom_toTopOf = "@+id/read_button"

         9015

         app:layout_constraintHorizontal_bias = "0. 0"

         app:layout_constraintStart_toStartOf = "parent"

         app:layout_constraintTop_toTopOf = "parent"

         app:layout_constraintVertical_bias = "0,904" />

 

     < Button

         android:id = "@+id/read_button"

         android:layout_width = "wrap_content"

         android:layout_height = "wrap_content"

         Start05 android:layout0015 "160dp"

         android:layout_marginEnd = "158dp"

         android:layout_marginBottom = "48dp"

         android:text = "Чтение"

         app:layout_constraintBottom_toTopOf = "@+id/textView2" 5 0 5 50015 app:layout_constraintEnd_toEndOf = "parent"

         app:layout_constraintHorizontal_bias = "0. 0"

         app:layout_constraintStart_toStartOf = "parent" / >

 

     < EditText

         android:id 5= "@+id/userInput"

         android:layout_width = "319dp"

         android:layout_height = "50dp"

         Android: Mayout_Marginstart = "46DP"

Android: Layout_Margintop = "91DP"

9999999998888888888888888888888888888888888888888888888889

888888888888999999159 9015 "0015 android:layout_marginEnd = "46dp"

         android:ems = "10"

         android:inputType = "textPersonName"

Android: текст = "Имя"

Приложение: Layout_constraindend_toendof = " = " = " = "0005

         app:layout_constraintStart_toStartOf = "parent"

         app:layout_constraintTop_toTopOf = "parent" />

 

     < TextView

         android:id = "@+id/content"

         android:layout_width0015 = "332dp"

         android:layout_height = "306dp"

         android:layout_marginStart = "33dp"

         android: layout_marginTop = "21dp"

         android:layout_marginEnd = "33dp"

         android:layout_marginBottom = "6dp"

         android:text = ""

         android:textAlignment = "center"

android:textColor = "#000"

         app:layout_constraintBottom_toBottomOf = 900" 9parent0015

         app:layout_constraintEnd_toEndOf = "parent"

         app:layout_constraintHorizontal_bias = "0.

Ваш комментарий будет первым

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    © 2019 iApple-59.ru