Єдина Країна!

Головне меню

Наша кнопка

Українські уроки про ІТ

Друзі

Підтримка української армії


Головна Програмування - Java Файловий менеджер на основі Java ME (частина 2)

Файловий менеджер на основі Java ME (частина 2)
Написав admin   
Субота, 01 вересня 2012 15:14
Переглядів: 5698

Продовження статті Рудницького Мирослава про створення менеджера на Java ME.

Початок читайте Файловий менеджер на основі Java ME (частина 1).

 

Проектування

Наш браузер – доволі складна програма, тому необхідно розділити її на декілька підсистем. Це полегшить супровід коду, зробить його зручним для читання, пошуку та змін. Тому пропоную створити 3 пакети: browser, core та utils. Їх назви говорять самі за себе: перший вміщує класи, що забезпечують роботу з файловою системою, наступний – класи ядра додатку і мідлет, а останній – клас утиліт, що надають додаткову функціональність.

 

Тепер розглянемо класи нашого додатку.

Ø Main. – це клас мідлету, своєрідна точка входу в браузер. В його обов’язки входить управління додатком: формування виводу, реакція на команди;

Ø Resources. – клас містить в собі всі ресурси для програми: рядки та зображення і надає доступ до них;

Ø ErrorsManager. – цей клас вміє обробляти помилки, що виникають під час роботи додатку;

Ø Browser. – клас виконує інкапсуляцію роботи з файловою системою;

Ø FileProperties. – це просто контейнер для інформації про властивості файлу і своєрідний “місток” для передачі даних між підсистемами;

Ø Utils. – як вже зазначалося вище, клас надає додаткову функціональність.

Тепер лишилося лише розглянути ці класи ще детальніше, на рівні реалізації, чим ми зараз і займемось. Перед розбором браузера “по гвинтиках” лише зазначу, що весь код читач знайде в супровідних файлах до статті, а ми розглянемо лише найцікавіше, тому лістинги не будуть повними.

Нарешті код

Почнемо огляд з Main. Це конкретний нащадок класу MIDlet, тому він реалізує його абстрактні методи: startApp(), destroyApp(boolean b) та pauseApp(). А оскільки він реалізує інтерфейс CommandListener, то має і метод commandAction(Command c, Displayable d), що виступає як обробник команд. Звернемося до лістингу 7:

Лістинг 7.

public class Main extends MIDlet implements CommandListener {
	private ErrorsManager exceptions = new ErrorsManager(this);
	private Browser browser = new Browser(Resources.MEGA_ROOT, Resources.MEGA_ROOT);
	private Command exit = new Command(Resources.COMMANDS_EXIT, Command.EXIT, 1);
	// another commands
	private TextField nameInput;
	private ChoiceGroup typeInput;
	private ChoiceGroup encodingInput;
	private String encoding;
	private TextBox viewer;
	protected void startApp() {
		try {
			if (System.getProperty(
				"microedition.io.file.FileConnection.version") == null) {
				ErrorsManager.handleException(Resources.ERRORS_NO_FC);
				destroyApp(false);
			}
			showCurrentFolder();
		} catch (SecurityException e) {
			ErrorsManager.handleException(Resources.ERRORS_SECURITY);
		} catch (Exception e) {
			ErrorsManager.handleException(e.getMessage());
		}
	}
	protected void destroyApp(boolean condition) {
		notifyDestroyed();
		}
	public void commandAction(Command command, Displayable display) {
		if (command == view) {
			setCurrentFile(display);
			String file = browser.getCurrentFile();
			if (file.endsWith(Resources.SEPARATOR_STRING) ||
            	file.equals(Resources.UPPER_FOLDER)) {
				traverseFolder();
			} else {
				show();
			}
		} 
		// another if blocks        
		if (command == encodingConfirm) {
			encoding =  Resources.ENCODINGS[encodingInput.getSelectedIndex()];
			try {
				viewer = new TextBox(Resources.FORMS_VIEW_TITLE + 
r
				browser.getCurrentFile(), null, 8192, TextField.ANY);
				viewer.addCommand(back);
				viewer.addCommand(save);
				viewer.addCommand(exit);
				viewer.setCommandListener(this);
				viewer.setString(browser.openFile(encoding));
				Display.getDisplay(this).setCurrent(viewer);                
			} catch (IOException e) {
				ErrorsManager.handleException(Resources.ERRORS_ACCESS + " '" +
				browser.getCurrentFile() + "'!");
			}
		}
	}

В цьому шматку – кістяк класу Main. Спочатку ми створюємо обробник помилок ErrorsManager, передаючи йому посилання на цей мідлет, потім створюємо браузер, що поки що не вказує на будь-який файл.

Зверніть увагу на команди (для економії місця приведена лише одна). Для їх ініціалізації використовується конструктор Command(String name, int type, int priority). Параметр name люб’язно надає нам клас Resources, в той час як type вибирається з констант, оголошених в класі Command (BACK, CANCEL, EXIT, HELP, ITEM, SCREEN, STOP). Типи команд залежать від виконуваних дій і означають відповідно:

Ø повернення до попереднього екрану;

Ø відміна дій;

Ø вихід з додатку;

Ø виклик довідки;

Ø вибір елемента з групи;

Ø поява нового екрану;

Ø зупинка дій.

Нарешті priority визначає пріоритет команди відносно інших, що вплине на порядок шикування команд в меню.

Поле nameInput використовується для збереження компонента для введення імені створюваного файлу, а typeInput зберігає компонент для вирішення дилеми “Що створити? Файл чи папку?”. Поля encoding та encodingInput використовуються при відкритті файлу. Вони зберігають ім’я кодування та компонент для його вибору відповідно. Нарешті viewer – це компонент для відображення вмісту нашого файлу.

В методі startApp() ми перевіряємо чи може телефон працювати з FC API і ловимо різні помилки статичним методом ErrorsManager.handleException(String s). Метод pauseApp() має пусте тіло і використовувати його ми не будемо. Натомість destroyApp(boolean b) не пустий – він сповіщає світ, що наш мідлет завершив роботу.

Нерозглянутим лишився лише commandAction(Command c, Displayable d). Він має не дуже миловидну драбинку if для визначення дій для відданої йому на розтерзання команди. Розглянемо лише найскладніші для розуміння блоки.

Наприклад, блок обробки view аналізує чи є файл, на який вказує browser папкою чи ні, і приймає рішення про відображення файлу чи відкриття папки. Інший приклад – блок обробки encodingConfirm. В ньому отримується ім’я вибраного кодування і створюється TextBox – компонент для відображення тексту.

Для цього служить конструктор TextBox(String title, String text, int maxSize, int constrains). Параметри зрозумілі – заголовок (видираємо з ресурсів), текст для відображення (завантажуємо пізніше методом setText(String t)), максимальна кількість символів тексту (бажано побільше) і обмеження тексту. Про останній варто сказати більше. Клас TextField (схожий на TextBox, оскільки представляє рядок тексту) визначає константи, що визначають введений текст:

Ø ANY – без обмежень;

Ø EMAILADDR – адреса електронної пошти;

Ø NUMERIC – цілі числа;

Ø PHONENUMBER – телефонний номер;

Ø URL – адреса сайту;

Ø DECIMAL – дробові числа;

Ø PASSWORD – пароль.

Потім в створений таким чином TextBox завантажується вміст файлу, на який вказує browser, додаються посилання на команди, що будуть відображені (addCommand(Command c)) і все це щастя виводиться на екран методом setCurrent(Displayable d) класу Display. Зверніть увагу, що створити об’єкт Display неможливо за допомогою new, для цього призначений метод-фабрика Display.getDisplay(MIDlet m).

Наступним нашим кроком буле розгляд інших методів класу Main. Лістинг 8 у Вашому розпорядженні:

Лістинг 8.

// another methods
    protected void showCurrentFolder() {
	Enumeration e;
	List browserList = new List(null, List.IMPLICIT);
	String folder = browser.getCurrentFolder();
	if (Resources.MEGA_ROOT.equals(folder)) {
		    e = FileSystemRegistry.listRoots();
	} else {
		    e = browser.getFolderList();
		    browserList.append(Resources.UPPER_FOLDER,
		    	Resources.FOLDER);
	}
	browserList.setTicker(new Ticker(folder));
	while (e.hasMoreElements()) {
		    String fileName = (String) e.nextElement();
		    if (fileName.charAt(fileName.length() - 1) == 
			Resources.SEPARATOR_CHAR) {
			browserList.append(fileName, Resources.FOLDER);
		} else {
			browserList.append(fileName, Resources.FILE);
		}
	}
	browserList.setSelectCommand(view);
	if (!Resources.MEGA_ROOT.equals(folder)) {
		    browserList.addCommand(create);
		    browserList.addCommand(delete);
		    browserList.addCommand(properties);
	}
	browserList.addCommand(exit);
	browserList.setCommandListener(this);
	Display.getDisplay(this).setCurrent(browserList);
	}    
    protected void showProperties() {
	try {
		if (browser.getCurrentFile().equals(Resources.UPPER_FOLDER)) {
			return;
		}
		FileProperties fp = browser.getFileProperties();
		Form props = new Form(Resources.FORMS_PROPERTIES_TITLE + 
	browser.getCurrentFile());
		ChoiceGroup attrs = new ChoiceGroup(
	Resources.FORMS_PROPERTIES_ATTRIBUTES, Choice.MULTIPLE,
 	Resources.ATTRIBUTES, null);
		attrs.setSelectedFlags(new boolean[] {fp.isReadable(), 
	fp.isWritable(), fp.isHidden()});
		props.append(new StringItem(Resources.FORMS_PROPERTIES_FOLDER,
	fp.getFolder()));
		props.append(new StringItem(Resources.FORMS_PROPERTIES_TYPES, 
	fp.isFolder() ? Resources.TYPES[1] : Resources.TYPES[0]));
		props.append(new StringItem(Resources.FORMS_PROPERTIES_DATE, 
	Utils.convertDate(fp.getLastModifiedDate())));
		props.append(new StringItem(Resources.FORMS_PROPERTIES_SIZE, 
	Utils.toString(new Long(fp.getSize())) + " " + 
	Resources.BYTE));
		props.append(attrs);
		props.addCommand(back);
		props.addCommand(exit);
		props.setCommandListener(this);
		Display.getDisplay(this).setCurrent(props);
	} catch (Exception e) {
		ErrorsManager.handleException(Resources.ERRORS_ACCESS + 
	browser.getCurrentFolder() + browser.getCurrentFile() + 
	"." + e.getMessage());
	}
}
    private void setCurrentFile(Displayable display) 
	throws NullPointerException {
		Utils.needNonNull(display, Resources.ERRORS_NULL_POINTER);
		List current = (List) display;
		String file = current.getString(current.getSelectedIndex());
		browser.setCurrentFile(file);
	}
}

Розбір польотів почнемо з методу setCurrentFile(Displayable d). Він призначений для того, щоб перетворювати вибраний користувачем елемент списку файлів на шлях до конкретного файлу в телефоні. До речі, цим він і поганий, адже щоразу при зверненні до браузера, його необхідно конфігурувати файлом, інакше можливо зловити купу помилок.

Солодка парочка методів addCommands(Command[] c) та removeCommands(Command[] c) додає на дисплей або видаляє з нього команди, упаковані в масив, переданий як параметр. Просто, правда?

Наступною нашою жертвою буде метод create(). В ньому теж нічого особливого – створюємо форму для введення імені новонародженого файлу і його типу (так все-таки файл чи папка?). Конструктор TextField аналогічний до конструктора TextBox, а от ChoiceGroup розглянемо детальніше.

Цей компонент призначений для представлення групи елементів. Конструктор – ChoiceGroup(String label, int choiceType, String[] stringElements, Image[] imageElements), де label – пояснюючий текст, stringElements – кандидати на додавання в групу та imageElements – зображення для цих кандидатів. Про choiceType поговоримо окремо. Клас ChoiceGroup має в собі такі константи:

Ø POPUP – група виконана як спливаюче меню;

Ø MULTIPLY – визначає групу, що допускає вибір багатьох елементів;

Ø EXCLUSIVE – визначає групу, що допускає вибір одного елемента.

З необхідних нам методів назву лише getSelectedIndex(), що повертає індекс вибраного елемента та setSelectedFlags(boolean[] b), що встановлює стан вибраних елементів. Все інше у Вас, надіюся, не викличе труднощів, тому йдемо далі.

Метод createConfirm(String name, boolean isFolder) детально розглядати не будемо, адже він лише викликає методи браузера для створення файлу чи папки. З тієї ж причини упускаємо розгляд traverseFolder() та delete(). Метод show() теж навряд чи нас зацікавить – він лише створює форму для вибору кодування файлу.

Трохи цікавіше на їх фоні виглядає метод showProperties(). Він відображає властивості вибраного файлу чи папки. Спершу browser створює об’єкт FileProperties для цікавого нам файлу. Після цього створюємо форму, на яку методом append(Item i) ліпимо купу StringItem. А це ще що за звір?

Клас StringItem призначений для додавання на форму тексту, що не можна редагувати. Зручно використовувати для різних написів, посилань та іншої всячини. За традицією розглянемо конструктор: StringItem(String label, String text), де параметрами виступають мітка для тексту і сам текст.

І прощаючись з класом Main, наостанок розглянемо метод showCurrentFolder(). Він створений для відображення вмісту папки на екрані телефону. Відразу звертаю Вашу увагу на те, що список файлів та папок представлений компонентом List. List – список елементів, на відміну від Form, що представляє екранний контейнер. Конструктор – List(String name, int type) створює список, використовуючи назву та тип, при чому останній може бути константою інтерфейсу Choice:

Ø IMPLICIT – список допускає вибір одного елементу;

Ø MULTIPLE – список допускає вибір багатьох елементів;

Ø EXCLUSIVE – список допускає ексклюзивний вибір елемента.

Клас List має кілька цікавих методів, що не можна оминати увагою, от як append(String strPart, Image imgPart). Метод додає до списку новий елемент, використавши посилання на нього та на його зображення. Зверніть увагу, що сортування відбувається по імені, тому папки та файли виводяться перемішано, а не як ми звикли: спочатку папки по алфавіту, за ними – файли. Наступний метод – setSelectCommand(Command c) дозволяє дізнатись, на якому елементі сфокусував свою увагу користувач.

Список допускає додавання до нього об’єкту класу Ticker, що представляє біжучу доріжку. Створюється ця доріжка дуже просто – Ticker(String text), де єдиний параметр – це текст, що має мозолити користувачу очі.

Також звертаю увагу читача на використання інтерфейсу Enumeration для обходу і виклик статичного методу FileSystemRegistry.listRoots(), що повертає всі кореневі папки Вашого телефону.

Ну нарешті ми покінчили з цим класом! Пропоную розглянути тепер набагато простіший Resources. Лістинг в студію!

Лістинг 9.

public class Resources {
	public static final String UPPER_FOLDER = "..";
	public static final String MEGA_ROOT = "/";
	public static final String SEPARATOR_STRING = "/";
	public static final String[] ENCODINGS = {"UTF-8", 
		System.getProperty("microedition.encoding")};
   // another constants and fields
	public static Image FOLDER = null;
		static {
			try {
				FOLDER = Image.createImage("/folder.png");
				FILE = Image.
createImage("/file.png");
		} catch (IOException e) {}
	}
}

Клас просто переповнений різними константами типу String, які тут не вказані для економії місця. Розглянемо лише найважливіші з них, а про інші скажу, що префікс означає, що константа:

Ø ERRORS_ є повідомленням про помилку;

Ø COMMANDS_ є назвою команди;

Ø FORMS_ відноситься до певної форми, вказаної в назві.

Константа UPPER_FOLDER представляє посилання на вищу в ієрархії папку. А MEGA_ROOT – це текстове представлення віртуальної папки, що стоїть на чолі всієї їхньої ієрархії. Константи SEPARATOR визначають розділювач назв папок, а ENCODINGS – кодування, доступні для цього телефону. Наприклад, системна властивість “microedition.encoding” зберігає кодування за замовчуванням, зазвичай це ISO-8859-1.

Поля FOLDER і FILE вміщують зображення папки і файлу відповідно. Їх завантаження відбувається в статичному ініціалізаторі, що буде викликаний при першому будь-якому зверненні до статичних членів класу Resources. Зверніть увагу, що при помилках поля лишатимуться null.

А тепер щодо помилок. Як Ви вже знаєте, ними в нас займається клас ErrorsManager, його і розглянемо:

Лістинг 10.

public class ErrorsManager {
	private static MIDlet midlet;
	public ErrorsManager(MIDlet midlet) throws NullPointerException {
		super();
		setMidlet(midlet);
	}
	public static void handleException(String message) throws 
	NullPointerException {
		Utils.needNonNull(midlet, Resources.MIDLET
		+ Resources.ERRORS_NULL_POINTER);
		Alert alert = new Alert(Resources.FORMS_ERROR_TITLE,
 message, null, AlertType.ERROR);
		alert.setTimeout(Alert.FOREVER);
		Display.getDisplay(midlet).setCurrent(alert);
		}
}

Клас, як бачите, дуже простий, але це зовсім не означає, що не потрібний! Обробка помилок здійснюється викликом статичного методу handleException(String s), де параметром виступає рядок, що описує зловлену помилку. Зверніть увагу, що аби правильно працювати, методу необхідно мати посилання на дисплей, на який виводиться повідомлення. Тому наш мідлет перш за все створював обробника помилок, передаючи йому посилання на себе.

Тут буде доречним сказати кілька слів про клас Alert, що використовується для створення екрану, що повідомляє користувача про певну подію. Конструктор – Alert(String title, String message, Image image, int type), де параметрами виступають заголовок вікна, повідомлення для виводу, зображення та тип повідомлення. Типи визначаються такими константами, оголошеними в тому ж таки Alert:

Ø ALARM – тривога;

Ø CONFIRMATION – підтвердження виконуваних користувачем дій;

Ø ERROR – помилка;

Ø INFO – інформаційне повідомлення;

Ø WARNING – попередження.

Метод setTimeout(int time), що використовується в коді, потрібний для задавання часу, протягом якого об’єкт Alert буде відображатись на екрані. Завдяки константі FOREVER, ми добиваємося постійного представлення, доки користувач не закриє його.

 

Завершальна частини статті - Файловий менеджер на основі Java ME (частина 3)

 


( 3 Проголосувало )
Коментарі
Добавити новий
Залишити коментар
Ім`я:
e-mail:
 
Тема:
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Введіть цей настирливий код
Русская редакция: www.freedom-ru.net & www.joobb.ru

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

 

Підписка

Хто онлайн?

Немає
На даний момент 8 гостей на сайті

Український рейтинг
TOP.TOPUA.NET