Файловий менеджер на основі Java ME (частина 3) |
Написав admin | |||||
Вівторок, 04 вересня 2012 10:48 Переглядів: 5733
|
|||||
Заключна частина статті Рудницького Мирослава про створення менеджера для телефону на Java ME. В даній частині будуть показані скріншоти роботи програми,а також доступна для завантаження вихідні коди програми. Попередня частина - Файловий менеджер на основі Java ME (частина 2)
Наступним нашим піддослідним буде клас Browser. Лістинг 11. public class Browser { private String currentFolder; private String currentFile; public Browser(String folder, String file) throws NullPointerException { super(); setCurrentFolder(folder); setCurrentFile(file); } // another methods public void createFile(String name) throws NullPointerException { Utils.needNonNull(name, Resources.TYPES[0] + " " + Resources.ERRORS_NULL_POINTER); try { FileConnection fc = (FileConnection) Connector.open("file:///" + getCurrentFolder() + name); fc.create(); fc.close(); } catch (IOException e) { String s = Resources.ERRORS_CAN_NOT_CREATE + " '" + name + "'"; if ((e.getMessage() != null) && (e.getMessage().length() > 0)) { s += ("\n" + e); } ErrorsManager.handleException(s); } } public void deleteFile() { try { FileConnection fc = (FileConnection) Connector.open( "file:///" + getCurrentFolder() + getCurrentFile()); fc.delete(); fc.close(); } catch (Exception e) { ErrorsManager.handleException(Resources.ERRORS_ACCESS + getCurrentFolder() + getCurrentFile() + "." + e.getMessage()); } } public void deleteFolder() { try { FileConnection fc = (FileConnection) Connector.open( "file://localhost/" + getCurrentFolder() + getCurrentFile()); Enumeration content = fc.list("*", true); if (!content.hasMoreElements()) { fc.delete(); fc.close(); } else { ErrorsManager.handleException( Resources.ERRORS_DELETE_NOT_EMPTY_FOLDER + " '" + getCurrentFile() + "'"); } } catch (IOException e) { ErrorsManager.handleException( e.getMessage() + " " + getCurrentFolder() + getCurrentFile()); } } public void goToUpperFolder() { if (getCurrentFolder().equals(Resources.MEGA_ROOT)) { if (getCurrentFile().equals(Resources.UPPER_FOLDER)) { return; } setCurrentFolder(getCurrentFile()); } else { if (getCurrentFile().equals(Resources.UPPER_FOLDER)) { int index = getCurrentFolder().lastIndexOf( Resources.SEPARATOR_CHAR, getCurrentFolder().length() - 2); if (index != -1) { setCurrentFolder( getCurrentFolder().substring(0, index + 1)); } else { setCurrentFolder(Resources.MEGA_ROOT); } } else { setCurrentFolder(getCurrentFolder() + getCurrentFile()); } } } public Enumeration getFolderList() { Enumeration enumeration = null; try { FileConnection fc = (FileConnection) Connector.open( "file://localhost/" + getCurrentFolder()); enumeration = fc.list(); fc.close(); } catch (IOException e) { ErrorsManager.handleException( Resources.ERRORS_ACCESS + " '" + getCurrentFolder() + "'" + " " + e.getMessage()); } return enumeration; } public FileProperties getFileProperties() { FileProperties fp = new FileProperties(getCurrentFile(), getCurrentFolder()); try { if (getCurrentFile().equals(Resources.UPPER_FOLDER)) { return null; } FileConnection fc = (FileConnection) Connector.open( "file://localhost/" + getCurrentFolder() + getCurrentFile()); if (!fc.exists()) { throw new IOException( Resources.ERRORS_FILE_DOES_NOT_EXIST); } fp.setReadable(fc.canRead()); fp.setWritable(fc. canWrite()); fp.setHidden(fc.isHidden()); boolean isFolder = fc.isDirectory(); fp.setIsFolder(isFolder); fp.setLastModifiedDate(fc.lastModified()); if (isFolder) { fp.setSize(fc.directorySize(true)); } else { fp.setSize(fc.fileSize()); } fc.close(); } catch (IOException e) { ErrorsManager.handleException(Resources.ERRORS_ACCESS + " '" + getCurrentFile() + "' " + e.getMessage()); } return fp; } } Браузер містить в собі поля, що зберігають назву файлу та папки, з якими ми зараз працюємо. Конструктор класу вимагає вказування їх не null значень. Також клас вміщує методи доступу до полів та роботи з FC API. Так як на початку статті ми розглянули основи роботи з цим пакетом, тому детально розглядати ці методи ми не будемо, обмежимося поверхневим описом: Ø createFile(String name) – створює файл з іменем name в папці, на яку вказує браузер; Ø createFolder(String name) – аналогічний попередньому, за виключенням того, що створює папку; Ø deleteFile() – видаляє файл; Ø deleteFolder() – видаляє пусту папку, інакше виводить повідомлення про помилку; Ø goToUpperFolder() – переходить до вищої в ієрархії папки. Фактично метод просто обрізає шлях до поточної папки так, щоб він вказував на батьківську; Ø getFolderList() – отримує вміст папки та повертає його у вигляді перерахування Enumeration; Ø getFileProperties() – повертає запаковані в об’єкт FileProperties властивості файлу; Ø openFile(String encoding) – повертає вміст файлу в форматі String, прочитаний з кодуванням encoding. При виняткових ситуаціях кидає UnsupportedEncodingException, що є підкласом IOException; Ø saveFile(String data, String encoding) – записує у файл символи з параметру data в заданому кодуванні encoding. При виняткових ситуаціях кидає UnsupportedEncodingException. Зверніть увагу на особливості реалізації методів – вони не вимагають вказування файлу (папки) для роботи і самі обробляють помилки вводу/виводу. Тепер настала черга класу FileProperties відкрити свої секрети. Це він робить у лістингу 12. Лістинг 12. public class FileProperties { private String name; private String folder; private boolean readable = true; private boolean writable = true; private boolean hidden = false; private boolean isFolder = false; private long lastModifiedDate = 0; private long size = 0; public FileProperties(String file, String folder) throws NullPointerException { super(); setName(file); setFolder(folder); } // another methods } Але секретів як таких-то і нема. Для нашого браузера властивості файлу – це його ім’я, розміщення, тип (файл/папка), дата останньої модифікації, розмір та параметри “для читання”, “для запису”, “схований”. Щоб задати ці властивості використовується конструктор та купа методів доступу, що перевіряють, чи не підсунули їм некоректні дані, наприклад від’ємний розмір. Тепер пропоную зайнятись утилітами з класу Utils. Признаюсь чесно – ідею підглянув з JDK 7, де є клас Objects. Тому вони вийшли доволі схожими… От тільки погляньте на лістинг 13: Лістинг 13. public class Utils { private Utils() { super(); } public static void needNonNull(Object object, String message) { if (object == null) { throw new NullPointerException(message); } } public static String convertDate(long time) { Calendar calendar = Calendar. getInstance(); calendar.setTime(new Date(time)); StringBuffer sb = new StringBuffer(); sb.append(calendar.get(Calendar.HOUR_OF_DAY)); sb.append(':'); sb.append(calendar.get(Calendar.MINUTE)); sb.append(':'); sb.append(calendar.get(Calendar.SECOND)); sb.append(','); sb.append(' '); sb.append(calendar.get(Calendar.DAY_OF_MONTH)); sb.append(' '); sb.append(Resources.MONTH[calendar.get(Calendar.MONTH)]); sb.append(' '); sb.append(calendar.get(Calendar.YEAR)); return sb.toString(); } // another methods } Зверніть увагу на конструктор, оголошений private – аби ніхто (й ніщо) не насмілився створювати екземпляр цього класу. До речі це безглуздо, адже всі методи оголошені статичними і є доступними без створення об’єкта. До речі, щодо методів. Цікавими для нас є needNonNull(Object o, String s) і його брат з одним параметром та needNonNegative(long v, String s) також з братом. Вони корисні для використання в конструкторах і методах-сеттерах, де перевіряють коректність переданих даних. А от convertDate(long l) просто необхідний при відображенні дати в звичному для людини форматі. Справа в тому, що Java представляє час певною кількістю мілісекунд, що пройшли від 1 січня 1970 року. Для їх збереження використовується тип long, оскільки переповнення наступить лише в 292280995 році. Для переведення ми створюємо об’єкт Date, що представляє конкретний момент часу і передаємо його календарю, що виконує за нас всю роботу. Нам лише залишається отримати результати методом get(int i), параметрами якого будуть константи, оголошені в Calendar. Ну от і все – фінал! Ми розглянули весь браузер, обійшли підводні камені і, надіюсь, чомусь навчились :) Фотогалерея Кілька знімків нашого браузера, зроблених на емуляторі телефону GT-S3600i:
Вихідні коди програми Завантажити архів з файлами програми на JavaME Що далі? А це вже залежить від Вас. Створений нами додаток повністю функціональний і може використовуватися в будь-якому телефоні з підтримкою FC API. Проте для довершеності немає кордонів, тож Ви можете продовжити розвиток в таких напрямках: Ø задокументувати проект. Якщо ви надалі працюватимете з цим кодом, то це просто необхідно! Автор свідомо не робив цього, щоб не відволікати читача на другорядний матеріал та не нав’язувати йому власний стиль коментарів. Не забувайте, що наш браузер створюється у навчальних цілях, тому проект має бути максимально “легким”. Ø додати функціональність. Можливо варто було б додати різну смакоту типу передавання файлу через Bluetooth або SMS. Проте не варто захоплюватись, пам’ятайте про “бритву Оккама”. Ø покращити редагування. Деякі телефони не вміють копіювати/вставляти дані, виділяти текст. Ø змінити сортування так, щоб спочатку відображались папки в алфавітному порядку, а за ними – файли. Ø додати себе як автора :). Замість післямови В цій статті будо детально розглянуто створення файлового браузера для мобільного телефону. Наостанок варто зазначити, що продукт тестувався на девайсах від Samsung: SGH-D900i та GT-S3600i. Надіюся стаття привабила увагу читача до важливої теми роботи з файловою системою та усунула можливі “білі плями”. Чтиво по темі 1) http://jcp.org/en/jsr/detail?id=75 Специфікація JSR-75. 2) http://j2mesamples.blogspot.com/2009/02/file-connection-using-j2me-api-jsr-75.html Приклад використання FC API. 3) http://innovator.samsungmobile.com/ Сайт з хорошою базою знань, можна юзати не тільки під Samsung. ( 2 Проголосувало ) Новіші матеріали:
3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved." |