- Создание удобного OpenFileDialog для Android
- Scorch Works Blog
- Always Working on Something
- Simple File Dialog For Android Applications
- Bare Bones Application Using the Simple File Dialog
- Related
- 2 thoughts on “ Simple File Dialog For Android Applications ”
- Android select file dialog
- About
- Осуществление выбора файлов в Android и копирование выбранного файла в другое место
- EDIT (текущий код)
- редактировать с помощью кода работа благодаря @Ю. С., @Lukas Knuth и @CommonsWare.
- 5 ответов
Создание удобного OpenFileDialog для Android
Наверное, как и многие разработчики под Android, столкнулся на днях с необходимостью реализовать в своем приложении выбор файла пользователем. Так как изначально в Android такого функционала нет, обратился к великому и ужасному. Это показалось мне странным, но из вороха вопросов на stackoverflow и небольшого числа отечественных форумов можно выделить всего три основных источника:
- Android File Dialog – почти все ссылки из stackoverflow ведут сюда. В принципе, неплохое решение, но реализовано через отдельную activity, а хотелось чего-то в духе OpenFileDialog’а из .Net.
- В данной статье речь идет вообще об отдельном файл-менеджере, и почерпнуть какие-то идеи из неё не удалось.
- Идея же отсюда очень понравилась, однако, как мне показалось реализовать все это можно несколько красивее.
В результате, начав реализовывать своё решение, я столкнулся с некоторыми трудностями решать которые показалось очень интересно. А посему, решил описать в данной статье не просто готовое решение, а все шаги, которые к нему привели. Желающие пройти их вместе –
Итак, приступим! В любой привычной среде (я использую IntelliJ IDEA) создадим новое приложение. На главной activity расположим одну единственную кнопку и напишем к ней, пока пустой, обработчик нажатия:
Создадим новый класс с конструктором:
а в обработчике кнопки вызовем диалог:
Кнопки показались, теперь надо бы и сами файлы найти. Начнем поиск с корня sdcard, для чего определим поле:
и реализуем следующий метод:
(так как главное требование к классу – работать сразу у любого разработчика, без подключения дополнительных библиотек, — то никаких google-collections использовать не будем, и с массивами приходится работать по старинке), а в конструкторе к вызову setNegativeButton добавим .setItems(getFiles(currentPath), null).
Что же, неплохо, однако файлы не отсортированы. Реализуем для этого дела Adapter как внутренний класс, заменим setItems на setAdapter и немного перепишем getFiles:
Еще лучше, но нам надо по клику на папке идти внутрь. Можно достучаться до встроенного listview, но я просто подменил его собственным (это потом пригодится). Плюс, изменения adapter’а внутри обработчика listview вызывало exception, и список файлов пришлось вынести в отдельное поле:
Отлично, вот только нажав на папку Android мы получаем список всего из одного каталога data, и наше окно тут же уменьшается в размере.
Возможно это нормально, но мне это не понравилось, и я стал искать возможности размер сохранить. Единственный найденный мною вариант – это установка setMinimumHeight. Установка этого свойства для listview вызвала дополнительные проблемы, но они решились оберткой его в LinearLayout:
Результат, все равно получился немного не таким, каким хотелось бы: при старте диалог развернут на весь экран, а после перехода в каталог Android – уменьшается до 750px. Да еще и экраны разных устройств имеют разную высоту. Решим сразу обе этих проблемы, установив setMinimumHeight в максимально возможную для текущего экрана:
Не нужно пугаться того, что мы устанавливаем в setMinimumHeight полный размер экрана, сама система уменьшит значение до максимально допустимого.
Теперь появляется проблема понимания пользователя, в каком каталоге он сейчас находится, и возврата вверх. Давайте разберемся с первой. Вроде все легко — установить значение title в currentPath и менять его при изменении последнего. Добавим в конструктор и в метод RebuildFiles вызов setTitle(currentPath).
А нет – заголовок не изменился. Почему не срабатывает setTitle после показа диалога, документация молчит. Однако мы может это исправить, создав свой заголовок и подменив им стандартный:
И снова не все ладно: если пройти достаточно далеко, то строка в заголовок влезать не будет
Решение с установкой setMaximumWidth не верно, так как пользователь будет видеть только начало длинного пути. Не знаю, насколько верно мое решение, но я сделал так:
Решим теперь проблему с возвратом. Это достаточно легко, учитывая, что у нас есть LinearLayout. Добавим в него еще один TextView и немного отрефракторим код:
Возможность возвращаться на шаг вверх, может привести пользователя в каталоги, к которым ему доступ запрещен, поэтому изменим функцию RebuildFiles:
(cообщение пока не очень информативное, но вскоре мы добавим разработчику возможность исправить это).
Ни один OpenFileDialog не обходится без фильтра. Добавим и его:
Обратите внимание — фильтр принимает регулярное выражение. Казалось бы – все хорошо, но первая выборка файлов сработает в конструкторе, до присвоения фильтра. Перенесем её в переопределенный метод show:
Осталось совсем чуть-чуть: вернуть выбранный файл. Опять же, я так и не понял зачем нужно устанавливать CHOICE_MODE_SINGLE, а потом все равно писать лишний код для подсветки выбранного элемента, когда он (код) и так будет работать без CHOICE_MODE_SINGLE, а потому обойдемся без него:
Источник
Scorch Works Blog
Always Working on Something
Simple File Dialog For Android Applications
Since there isn’t a built in file dialog interface for android development I have been searching for one that I could use without starting from scratch. I did eventually find a Simple Directory Chooser with a very lenient license (The Code Project Open License (CPOL) 1.02). The directory chooser I found uses a dialog interface so there is no need to create an additional activity to use it.
The directory chooser was great but I needed a file dialog for choosing files for opening and saving not a directory chooser. To get the file dialog I needed I modified the original directory chooser adding to it as needed to create a Simple File Dialog for my own use. I thought I would post my modified version here for others to use or build on.
The file dialog code consists of a single file and uses standard Android resources. This file dialog code should be very portable and easily inserted into any project to add menu driven file selection within Android. Screen shots of the three file dialog modes (Open, Save, and Folder Select) are shown below. The “Save” and “Folder Select” modes include a button for adding a new folder to the file structure.
Bare Bones Application Using the Simple File Dialog
This is a very bare bones application with three buttons that call the Simple File Dialog in all three modes (Save, Open and Folder Select). To make this application I just started a new Android Application Project in Eclipse. Edited the Layout to add three buttons and edited the MainActivity.java file. The finished MainActivity.java file is shown below.
For the New Folder button to actually create a new folder in the demo you need to include the following line in the Manifest file to give the app permission to write to the SD Card.
None of this code would have been possible without the jump start I got from the Simple Directory Chooser
Related
2 thoughts on “ Simple File Dialog For Android Applications ”
After a lot of search on net, finally hooked onto exact code.
Gr8 Man.
Thanks, just what I needed and it worked immediatly.
Источник
Android select file dialog
Show a dialog in your android app that allows the user to select a file or folder from his phones memory or SD card.
###1. Gradle dependency (JCenter) Add the following to your build.gradle:
###2. Maven dependency (JCenter) Add the following to your pom.xml:
###Don’t forget Your app needs the according permissions to acces the phones memory or an sd card. See [Using External Storage] (http://developer.android.com/guide/topics/data/data-storage.html#filesExternal) and Requesting Permissions at Runtime or the implementation in the example app (line 63ff).
Copyright (c) 2016 Sebastian Dombrowski
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the «Software»), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
About
Show a dialog in your android app that allows the user to select a file or folder from his phones memory or SD card.
Источник
Осуществление выбора файлов в Android и копирование выбранного файла в другое место
я пытаюсь реализовать средство выбора файлов в своем проекте Android. Что я смог сделать до сих пор-это :
а затем в onActivityResult()
это открытие выбора файла, но это не то, что я хочу. Например, я хочу выбрать файл (.txt), а затем сделать что File и затем использовать его. С этим кодом я думал, что получу полный путь но этого не происходит; например я: /document/5318/ . Но с этим путем я не могу получить . файл. Я создал метод под названием PathToFile() что возвращает File :
что я пытаюсь сделать, это позволить пользователю выбрать File из любого места означает DropBox , Drive , SDCard , Mega , etc. И я не нахожу способ сделать это правильно, я попытался получить Path затем получить File этой Path . но это не работает, поэтому я думаю, что лучше получить , а потом с этим File программно я Copy этот и Delete .
EDIT (текущий код)
там у меня есть вопрос, потому что я не знаю, что поддерживается как text/plain , но я собираюсь расследовать это, но на данный момент это не имеет значения.
на onActivityResult() я использовал то же самое, что @Lukas Knuth ответ, но я не знаю, смогу ли с ним Copy этой File в другую часть моего SDcard я waitting для его ответ.
редактировать с помощью кода работа благодаря @Ю. С., @Lukas Knuth и @CommonsWare.
это Intent где я принимаю только файлы text/plain .
на onActivityResult() создать URI где я получаю данные Intent я создаю File где я сохранить абсолютный путь делаешь content_describer.getPath(); , а затем я сохраняю имя пути, чтобы использовать его в TextView С content_describer.getLastPathSegment(); (это было потрясающе @Y. S. Не знал об этой функции), и я создаю второй File который я назвал destination и я пошлю AbsolutePath чтобы создать этот File .
также я создал функцию, которую вы должны отправить source file и destination file что мы создали ранее, чтобы скопировать в новую папку.
также я создал функцию, которая говорит Мне, существует ли эта папка или нет (я должен отправить destination file , если он не существует, я создаю эту папку, и если это произойдет не я ничего не делаю.
еще раз спасибо за вашу помощь, надеюсь, вам понравится этот код, сделанный со всеми вами, ребята:)
5 ответов
Шаг 1-Используйте неявное Intent :
выбрать файл из устройства, вы должны использовать неявный Intent
Шаг 2 — получить абсолютный путь к файлу:
чтобы получить путь к файлу из Uri , сначала попробуйте использовать
здесь data — это Intent вернулся в onActivityResult() .
если это не работает, используйте следующий метод:
At хотя бы один из этих двух методов должен дать вам правильный, полный путь.
Шаг 3-скопируйте файл:
что вы хотите, я считаю, это скопировать файл из одного места в другое.
для этого абсолютно необходимо иметь абсолютный путь к файлу как источника и места назначения.
во-первых, получить абсолютный путь к файлу, используя либо getPath() способ или uri.getPath() :
затем создайте два File объекты следующим образом:
здесь CustomFolder — каталог на внешнем диске, куда вы хотите скопировать файл.
затем используйте следующий метод для копирования файла из одного места в другое:
попробуйте это. Это должно сработать.
Примечание: Vis-a-vis Lukas’ ответ — то, что он сделал, это использовать метод под названием openInputStream() возвращает контент of a Uri , ли Uri представляет файл или URL-адрес.
еще один перспективный подход — FileProvider :
есть еще один способ, с помощью которого можно получить файл из другого приложения. Если приложение делится своими файлами через FileProvider , тогда можно достать FileDescriptor объект, который содержит конкретную информацию об этом файл.
для этого используйте следующее Intent :
и в onActivityResult() :
здесь mInputPFD это ParcelFileDescriptor .
ссылки:
Я сделал то же самое, чтобы позволить пользователю выбрать изображение из папки :
1) есть кнопка Открыть:
2) Функция открыть папку изображений:
3) результат деятельности, где я получаю путь к файлу изображения и делаю все, что хочу с путем изображения:
4) и теперь самая важная часть, класс W_ImgFilePathUtil, код не от меня, но он позволяет вам получить полный путь любого выбранного файла, будь то на sd-карте, Google drive.
открытый класс W_ImgFilePathUtil <
заключение: код работает с путем изображения, но уверен, работает с любым типом файла.
надеюсь, что это поможет решить вашу проблему.
As @CommonsWare уже отмечалось, Android возвращает вам Uri , что является более абстрактным понятием, чем путь к файлу.
он также может описать простой путь к файлу, но он также может описать ресурс, к которому обращаются через приложения (например, content://media/external/audio/media/710 ).
если вы хотите, чтобы ваш пользователь выбрал любой файл с телефона, чтобы прочитать его из вашего приложения, вы можете сделать это, попросив файл (как вы сделали правильно) , а затем использовать ContentResolver для получения InputStream на Uri это возвращается сборщиком.
важно: некоторые поставщики (например, Dropbox) хранят/кэшируют свои данные на внешнем хранилище. Вам нужно будет иметь android.permission.READ_EXTERNAL_STORAGE -разрешение объявлено в вашем манифесте, иначе вы получите FileNotFoundException , хотя файл есть.
обновление: Да, вы можете скопировать файл, прочитав его из одного потока и пишу другому:
удаление файла, вероятно, невозможно, так как файл не принадлежат для вас он принадлежит приложению, которое поделилось им с вашим. Таким образом, приложение-владелец отвечает за удаление файла.
A Uri не является файлом. А Uri ближе к URL веб-сервера. Это непрозрачный адрес, который имеет значение только для » сервера «(или в этом случае ContentProvider ).
так же, как вы используете InputStream для чтения в байтах, представленных веб-URL, вы используете InputStream для чтения в байтах, представленных Uri . Вы получаете такой поток, позвонив openInputStream() на ContentResolver .
передайте URI, возвращенный в onActivityResult в этом методе
Источник