Розробка програм для мобільного пристрою

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

Факультет "Інформатика та системи управління"
Методичні вказівки до лабораторної роботи
за курсом "Розподілені системи обробки інформації"
Розробка програм для мобільного пристрою.
Москва, 2009

Зміст

Мета роботи

Завдання до самостійної роботи

Завдання до лабораторної роботи

Створення звіту

Контрольні питання

1. Структура MIDP програми

2. Основи створення мідлетів

Додаток 1.Прімери створення MIDP додатків

Література


Мета роботи

Отримати знання про основи створення MIDP додатків для мобільних пристроїв на мові Java. Ознайомитись з бібліотеками javax.microedition. Застосувати отримані знання для створення MIDP додатків.

Завдання до самостійної роботи

Ознайомитися з теоретичним матеріалом, представленим у додатках до даних методичних вказівок і прикладами програм. Ознайомитися з текстом завдання до лабораторної роботи.

Завдання до лабораторної роботи

Завдання 1. Створити гру, реалізовану як MIDP додаток.
1. Створити меню гри, що містить пункти:
1.1. запуск гри
1.2. рівень складності та інші настройки.
2. У грі повинні обчислюватись набрані очки і кращий результат зберігається протягом гри.
Гра вибирається самим студентом.
Завдання 2.
Створити сервер обміну текстовими повідомленнями.
1. Створити сервер, які буде отримувати дані від клієнта у вигляді рядків і виводити на екран мідлета.
2. Сервер повинен бути багатопотоковий, тобто обслуговувати одночасно з декілька клієнтів.
3. Для завершення роботи клієнт повинен надіслати рядок «exit».
Створити клієнта для сервера обміну повідомленнями.
1. Клієнтський додаток має мати поле для введення даних для відправки.
За вибором студента програма може одночасно виконувати функції і сервера, і клієнта одночасно, або можуть бути реалізовані, як два окремих додатки.

Створення звіту

Звіт повинен містити:
1. Постановку задачі, розв'язуваної налагодженої програмою.
2. Керівництво користувача налагодженої програми, що містить опис інтерфейсів всіх функцій програми.
3. Лістинг програми з необхідними коментарями.

Контрольні питання.

1. Що таке MIDP?
2. Структура MIDP?
3. Для чого потрібен клас MIDlet та його методи?
4. Яким чином здійснюється взаємодія MIDP програми з користувачем?
5. Для чого потрібен клас Canvas та його методи?

1. Структура MIDP програми

MIDP програма має сувору структуру, яка описана нижче. Додаток, який може бути запущено на телефоні, називається мідлетом (midlet). Мідлети обов'язково запаковуються в JAR архів, причому в одному JAR - архіві можуть знаходиться відразу кілька мідлетів. Архів з мідлетам (і) називається MidletSuite (набір мідлетів)
Набір мідлетів складається з JAR - архів, що містить мідлет (и), допоміжні класи і ресурси (наприклад файли з картинками і т.п.); JAR - маніфесту (JAR Manifest), який представляє собою файл, що знаходиться в JAR - архіві (файл manifest.mf в папці META-INF в корені архіву); дескриптора додатки (Application Descriptor) - це файл з тим же ім'ям, що і JAR - архів і розширенням JAD.
Маніфест і дескриптор містять атрибути програми у форматі імя_атрібута: значеніе_атрібута.
Деякі з атрибутів повинні бути присутнім обов'язково і при цьому збігатися в дескрипторі і маніфесті. Якщо ця умова не буде виконана, то програма не запуститься і навіть не встановиться на приладі, для якого воно призначене.
Заповнення обов'язкових атрибутів бере на себе програмний засіб, призначений для розробки MIDP додатків (KToolbar з J2MEWTK і Forte for Java CE). Крім того, цей засіб надає можливість додавання і редагування атрибутів.
Мідлет може отримати значення будь-якого атрибуту за допомогою методу мідлета:
getAppProperty (String key)
Нижче наведені деякі атрибути, які можуть бути корисні розробнику.
· MIDlet-<n>: <name>, <icon>, <class>-опис n-ого мідлета в наборі. Тут name - ім'я мідлета, icon - «іконка" (файл у форматі PNG), class - файл класу, що розширює (extends) клас MIDlet (фактично той клас, який буде «виконуватися»). При відкритті на приладі набору мідлетів, на екрані висвічується список мідлетів в ньому, в якому представлені імена мідлетів з відповідними іконками.
Приклад: MIDlet-1: worm, / liqWorm / worm.png, liqWorm.worm
· MIDlet-Version: <version>-версія набору мідлетів у форматі xx.yy.zz.
Приклад: MIDlet-Version: 0.1.0
· MIDlet-Info-URL: <URL>-URL, за яким можна знайти інформацію про набір мідлетів.
Приклад: MIDlet-Info-URL: xdimas@yahoo.com
· MIDlet-Description: <description>-опис набору мідлетів.
Приклад: MIDlet-Description: My first MIDlet!
· MIDlet-Vendor: <vendor>-інформація про розробника мідлета.
Приклад: MIDlet-Vendor: xDimas
Необхідно відзначити, що способи установки набору мідлетів на прилад, для якого той призначений, не обмовляється в рамках стандарту J2ME.
Для створення та тестування мідлетів необхідно сказати останню версію J 2 ME _ wireless _ toolkit з сайту розробника: http: / / java. Sun. Com / j 2 me / index. Jsp

2. Основи створення мідлетів

Необхідно відзначити, що MIDP є не просто урізаним варіантом J2SE (Java2 Standard Edition). Тут з'являються свої особливості, продиктовані особливостями пристроїв, для яких мидлети призначені.
Клас, який буде мідлетом, повинен розширювати (extends) клас MIDlet (аналогічно класу Applet при розробці аплетов). Цей клас повинен мати конструктор без параметрів. Клас MIDlet має методи, призначені для управління життєвим циклом мідлета. Так для того, щоб повідомити віртуальній машині (ВМ) про те, що мідлет завершується (фактично завершує виконання мідлета) використовується метод: notifyDestroyed (), а щоб повідомити мідлета про те, що він буде завершений, ВМ викликає метод: destroyApp (bolean uconditional ).
Мідлет, на відміну від аплета, може знаходиться в стані паузи (paused - наприклад, коли дисплей зайнятий яким-небудь сполученням тощо). Щоб повідомити мідлета про те, що він переходить в режим паузи, ВМ викликає метод мідлета: pauseApp (), а щоб увійти в режим паузи, мідлет використовує метод: notifyPaused ().
Коли мідлет входить в активний стан (вихід з паузи і початок роботи мідлета), викликається його метод: startApp ().
Важливо пам'ятати, що цей метод може викликатися кілька разів за час виконання мідлета.
Клас, що розширює MIDlet може оголошувати (implements) різні інтерфейси, наприклад інтерфейс Runnable.
Для взаємодії з користувачем в MIDP присутні класи Display і Displayable (точніше його спадкоємці).
Об'єкт класу Display створюється ВМ і за весь час роботи мідлета для нього є тільки один об'єкт цього класу. Отримати його можна за допомогою статичного методу:
static Display Dispaly.getDisplay (MIDlet m)
Об'єкт класу Display оперує з об'єктами класу Displayable. Об'єкти класу Displayable призначені безпосередньо для взаємодії з користувачем (тобто для виводу на екран, обробки натискань клавіш і т.п.). Для роботи з цими об'єктами в класі Displayесть два методи:
void setCurrent (Displayable d)
Displayable getCurrent ()
Сам клас Displayable оголошений як абстрактний, так що працювати можна тільки з його нащадками. Їх два - це класи Canvas і Screen.
Нащадки класу Screen визначають набір візуальних компонент для високоуровнего взаємодії з користувачем (форми, поля введення, списки і т.п.). Треба відзначити, що цей набір доволі примітивний і надає мінімум (проте достатній) можливостей для взаємодії з користувачем. Використовувати цей набір в додатках, що вимагають інтерактивності (наприклад в іграх), не представляється можливим, але деякі компоненти все ж зручно використовувати в допоміжних цілях (наприклад поле вводу для введення імені гравця в таблицю рекордів, меню і т.п.). Детально розглядати цей набір тут не будемо.
Клас Canvas призначений для низкоуровнего взаємодії з користувачем. У ньому визначено набір методів для забезпечення перемальовування вмісту екрана, отримання інформації про натиснення кнопок і т.п. Зупинимося докладніше на деяких особливостях використання класу Canvas.
Необхідно пам'ятати про те, що на різних приладах, на яких може бути запущений мідлет, можуть бути різні розміри дисплея. Для їх отримання використовуються методи:
int getHeight ()
int getWidth ()

Перемальовування вмісту екрану здійснюється ВМ самостійно і коли вона буде виконана, точно сказати не можна. Можна лише повідомити ВМ про те, що необхідно відновити вміст екрану викликом методу:
void repaint ()
або
void repaint (int x, int y, int width, int height)
Можна примусити ВМ до негайного виконання перемальовування викликом методу: void serviceRepaints ()
Коли ВМ здійснює перемальовування вмісту екрана, викликається метод: void paint (Graphics g)
Об'єкт g пов'язаний із зображенням, яке буде виведено на екран. Використання об'єктів класу Graphics відбувається так само, як і при роботі з аплетами.
Необхідно зауважити, що метод paint оголошений як абстрактний і тому для роботи з об'єктом класу Canvas розробник повинен створити клас, який розширює Canvas і визначальний метод paint.
Отримати об'єкт класу Graphics, який відповідає за перемальовування екрану, як це можна зробити для аплета методом: Graphics Applet.getGraphics (), для нащадків класу MIDlet прямим способом неможливо. Можна спробувати зберегти об'єкт, що надходить в якості параметра в метод paint, але робити це не рекомендується.
MIDP надає елегантний метод для синхронізації перемальовування екрану з ходом виконання основної програми. У класі Display присутній метод:
callSerially (Runnable r)

Виклик цього методу змушує ВМ викликати метод run () об'єкта r відразу після закінчення перемальовування екрану. Виклик здійснюється тільки один раз.
Об'єкти класу Canvas можуть реагувати на натискання кнопок за допомогою методів:
keyPressed (int key)
keyReleased (int key)
keyRepeated (int key)
Використовувати коди кнопок безпосередньо не рекомендується. Для отримання дії, пов'язаного з тим або іншим кодом кнопки, використовується метод:
int getGameAction (int key)
Він повертає код дії (коди визначені як константи в класі Canvas на приклад FIRE). Є і зворотний йому метод:
int getKeyCode (int gameAction)
Для кожного об'єкта класу Displayable може бути заданий набір команд, визначених користувачем. Кожна команда є об'єктом класу Command і створюється за допомогою конструктора:
Command (String command, int type, int priority)

Для додавання і видалення команд у класі Displayable передбачені методи:
void addCommand (Command c)
void removeCommand (Command c)
Команди, в залежності від їх типу, можуть закріплюватися за кнопками під екраном телефону або заноситися в екранне меню (це робиться автоматично). При цьому над відповідною кнопкою відображається ім'я команди.
Для того, щоб мідлет міг обробляти команди, він повинен оголошувати (implements) інтерфейс CommandListener. У цього інтерфейсу є єдиний метод: void commandAction (Command c, Displayable d), який викликається після того, як користувач вибере команду c.
Для того, щоб оголосити в об'єкті класу Displayable обробник команд listener, використовується метод цього класу:
void addListener (CommandListener listener)

Додаток 1. Приклади створення MIDP додатків

Давайте створимо найпростіше MIDP додаток-заготовку для нашої гри, на основі гри «черв'як».
package example.wormgame;
import java.lang.Thread;
/ / Підключаємо необхідні нам компоненти
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
/ **
* Основний клас нашого мідлета
* /
public class WormMain extends MIDlet implements CommandListener {
/ ** Клас описує "черв'яка" * /
private WormPit theGame;
/ ** Кнопка виходу з гри. * /
private Command exitCmd = new Command ("Exit", Command.EXIT, 3);
/ ** Елемент меню, поміняти рівень складності. * /
private Command levelCmd = new Command ("Change Level", Command.SCREEN, 2);
/ ** Елемент меню, почати нову гру. * /
private Command startCmd = new Command ("Start", Command.SCREEN, 1);
/ ** Елемент меню, перезапустити гру. * /
private Command restartCmd = new Command ("Restart", Command.SCREEN, 1);
/ ** Елемент меню, повернуться в гру без вибачення. * /
private Command cancelCmd = new Command ("Cancel", Command.ITEM, 1);
/ ** Елемент меню, для подтвержжденія вибраних установок. * /
private Command OKCmd = new Command ("OK", Command.OK, 1);
/ **
* Конструктор за умовчанням, в якому створюються графічні вомпоненти і
* Встановлюється command listener.
* /
public WormMain () {
theGame = new WormPit ();
theGame.addCommand (exitCmd);
theGame.addCommand (levelCmd);
theGame.addCommand (startCmd);
theGame.addCommand (audioOnCmd);
theGame.setCommandListener (this);
}
/ **
* Деструктор для очищення пам'яті зайнятої додатком.
* /
protected void destroyApp (boolean unconditional) {
theGame.destroyGame ();
Display.getDisplay (this). SetCurrent ((Displayable) null);
}
/ **
* Припинення роботи програми
* /
protected void pauseApp () {
}
/ **
* Запуск програми
* /
protected void startApp () {
Display.getDisplay (this). SetCurrent (theGame);
try {
/ / Запуск гри в окремому потоці
Thread myThread = new Thread (theGame); / / створюємо новий потік
myThread.start (); / / запуск потоку
} Catch (Error e) {
destroyApp (false);
notifyDestroyed ();
}
}
/ **
* Виконання функцій програми у відповідь на дії користувача.
* /
public void commandAction (Command c, Displayable d) {
if (c == restartCmd) {
theGame.restart ();
} Else if (c == levelCmd) {
Item [] levelItem = {
new Gauge ("Level", true, 9, theGame.getLevel ())};
Form f = new Form ("Change Level", levelItem);
f.addCommand (OKCmd);
f.addCommand (cancelCmd);
f.setCommandListener (this);
Display.getDisplay (this). SetCurrent (f);
} Else if (c == exitCmd) {
destroyApp (false);
notifyDestroyed ();
} Else if (c == startCmd) {
theGame.removeCommand (startCmd);
theGame.addCommand (restartCmd);
theGame.restart ();
} Else if (c == OKCmd) {
Form f = (Form) d;
Gauge g = (Gauge) f.get (0);
theGame.setLevel (g.getValue ());
Display.getDisplay (this). SetCurrent (theGame);
} Else if (c == cancelCmd) {
Display.getDisplay (this). SetCurrent (theGame);
}
}
Тепер необхідно створити меню та інші графічні компоненти на екрані мобільного пристрою.
public class WormPit extends Canvas implements Runnable {
/ ** Окуляри в грі. * /
private int score = 0;
/ ** Рівень складності. * /
private int level = 5;
/ ** Ширина екрану в пікселях. * /
static int CellWidth;
/ ** Довжина екрану в пікселях. * /
static int CellHeight;
/ ** Висота шрифту для виводу на екран рахунку. * /
private static final int SCORE_CHAR_HEIGHT;
/ ** Ширина шрифту для виводу на екран рахунку. * /
private static final int SCORE_CHAR_WIDTH;
/ ** Час за замовчуванням між перемальовуванням хробака (400 milliseconds) * /
private static final int DEFAULT_WAIT = 400;
/ ** Колір шрифту. (0xff0000) * /
static final int TEXT_COLOUR = 0x00ff0000;
/ ** Розмір клітини хробака. * /
public static final int CELL_SIZE = 5;
/ / Встановлення розміру шрифту
static {
Font defaultFont = Font.getDefaultFont (); / / взяти шрифт за замовчуванням
SCORE_CHAR_WIDTH = defaultFont.charWidth ('S');
SCORE_CHAR_HEIGHT = defaultFont.getHeight ();
SCORE_HEIGHT = SCORE_CHAR_HEIGHT * 2;
}
/ **
* Конструктор. Завдання ширини і висоти хробака.
* /
public WormPit () {
width = round (getWidth ());
height = round (getHeight ()-SCORE_HEIGHT);
WormPit.CellWidth = (width-(START_POS * 2)) / WormPit.CELL_SIZE;
WormPit.CellHeight = (height-(START_POS * 2)) / WormPit.CELL_SIZE;
myWorm = new Worm (this);
/ **
* Обробник подій від натискання клавишь на мобільному пристрої.
* Стрілки (джойстик) на мобільному пристрої (UP, DOWN, LEFT, RIGHT)
* /
public void keyPressed (int keyCode) {
switch (getGameAction (keyCode)) {
case Canvas.UP:
myWorm.setDirection (Worm.UP);
break;
case Canvas.DOWN:
myWorm.setDirection (Worm.DOWN);
break;
case Canvas.LEFT:
myWorm.setDirection (Worm.LEFT);
break;
case Canvas.RIGHT:
myWorm.setDirection (Worm.RIGHT);
break;
case 0:
/ / Можна використовувати клавіші з номерами 2,4,6,8
switch (keyCode) {
case Canvas.KEY_NUM2:
myWorm.setDirection (Worm.UP);
break;
case Canvas.KEY_NUM8:
myWorm.setDirection (Worm.DOWN);
break;
case Canvas.KEY_NUM4:
myWorm.setDirection (Worm.LEFT);
break;
case Canvas.KEY_NUM6:
myWorm.setDirection (Worm.RIGHT);
break;
}
break;
}
}
/ **
* Перемальовування екрану і всіх об'єктів.
* /
private void paintPitContents (Graphics g) {
try {
myWorm.update (g); / / update worm position

/ * Логіка перевірки з'їв чи черв'як об'єкт чи ні і подсчсет очок
для виводу на екран * /

g.setColor (WormPit.ERASE_COLOUR);
g.fillRect ((width - (SCORE_CHAR_WIDTH * 3))-START_POS,
height-START_POS,
(SCORE_CHAR_WIDTH * 3),
SCORE_CHAR_HEIGHT);
g.setColor (WormPit.DRAW_COLOUR);
/ / Відобразити новий рахунок
g.drawString ("" + score,
width - (SCORE_CHAR_WIDTH * 3) - START_POS,
height - START_POS, g.TOP | g.LEFT);
} Catch (WormException se) {
gameOver = true;
}
}
/ **
* Виведення на екран всіх компонентів
* /
public void paint (Graphics g) {
if (forceRedraw) {
/ / Перемалювати весь екран
forceRedraw = false;
/ / Очистити задній план
g.setColor (WormPit.ERASE_COLOUR);
g.fillRect (0, 0, getWidth (),
getHeight ());
/ / Намалювати межі поля
g.setColor (WormPit.DRAW_COLOUR);
g.drawRect (1, 1, (width - START_POS), (height - START_POS));
/ / Відобразити поточний рахунок
g.drawString ("L:" + level, START_POS, height, g.TOP | g.LEFT);
g.drawString ("" + score,
(Width - (SCORE_CHAR_WIDTH * 3)),
height, g.TOP | g.LEFT);
/ / Відобразити найвищий рахунок на цьому рівні
g.drawString ("H:",
(Width - (SCORE_CHAR_WIDTH * 4)),
(Height + SCORE_CHAR_HEIGHT),
g.TOP | g.RIGHT);
g.drawString ("" + WormScore.getHighScore (level),
(Width - (SCORE_CHAR_WIDTH * 3)),
(Height + SCORE_CHAR_HEIGHT),
g.TOP | g.LEFT);
/ / Намалювати хробака і їжу
g.translate (START_POS, START_POS);
g.setClip (0, 0, CellWidth * CELL_SIZE, CellHeight * CELL_SIZE);
myWorm.paint (g);
myFood.paint (g);
} Else {
/ / Намалювати хробака і їжу
g.translate (START_POS, START_POS);
}
/ **
* Викликає перемальовування екрану і компонентів при зніманні паузи
* /
protected void hideNotify () {
super.hideNotify ();
forceRedraw = true;
if (! gameOver) {
gamePaused = true;
}
}
/ **
* Основний цикл виконання MIDP програми
* /
public void run () {
while (! gameDestroyed) {
try {
synchronized (myWorm) {

/ * Логіка обчислень очок двіденія черв'яка і дій користувача * /
repaint ();
}
}
} Catch (java.lang.InterruptedException ie) {
}
}
}
/ **
* Викликає подія знищення додатка
* /
public void destroyGame () {
synchronized (myWorm) {
gameDestroyed = true;
/ / MyWorm.notifyAll ();
myWorm.notifyAll ();
}
}
}
Додаток 2. Приклади створення MIDP додатків
Для виконання завдання номер 2 буде потрібно створити TCP з'єднання за допомогою сокетів і форму введення значень, що передаються.
Для початку створимо MIDP додаток.
/ **
* Основний клас MIDP програми
* /
public class SocketMIDlet extends MIDlet implements CommandListener {
private final static String SERVER = "Server";
private final static String CLIENT = "Client";
private static String [] names = {SERVER, CLIENT};
private static Display display; / / дисплей
private Form f; / / форма
private ChoiceGroup cg;
private boolean isPaused;
private Server server;
private Client client;
/ / Ліва функціональна кнопка на мобільному пристрої
private Command exitCommand = new Command ("Exit", Command.EXIT, 1);
/ / Права функціональна кнопка на мобільному пристрої
private Command startCommand = new Command ("Start", Command.ITEM, 1);

/ **
* Конструктор. створює графічні компоненти на екрані.
* І встановлює обробники подій.
* /
public SocketMIDlet () {
display = Display.getDisplay (this);
f = new Form ("Socket Demo");
cg = new ChoiceGroup ("Please select peer",
Choice.EXCLUSIVE, names, null);
f.append (cg);
f.addCommand (exitCommand);
f.addCommand (startCommand);
f.setCommandListener (this);
display.setCurrent (f);
}
public boolean isPaused () {
return isPaused;
}

/ **
* Запуск програми
* /
public void startApp () {
isPaused = false;
}
/ **
* Призупинення програми
* /
public void pauseApp () {
isPaused = true;
}

/ **
* Зупинка програми
* /
public void destroyApp (boolean unconditional) {
if (server! = null) {
server.stop ();
}
if (client! = null) {
client.stop ();
}
}
/ **
* Обробник подій.
* /
public void commandAction (Command c, Displayable s) {
if (c == exitCommand) {
destroyApp (true);
notifyDestroyed ();
} Else if (c == startCommand) {
String name = cg.getString (cg.getSelectedIndex ());
if (name.equals (SERVER)) {
server = new Server (this);
server.start ();
} Else {
client = new Client (this);
client.start ();
}
}
}
}
Для створення з'єднання з сервером за допомогою сокетів буде потрібно наступна конструкція:
/ / Встановити сокет з'єднання на 5000 порту з localhost
SocketConnection sc = (SocketConnection) Connector.open ("socket: / / localhost: 5000");
/ / Вхідний потік для запису інформацию в сокет
InputStream is = sc.openInputStream ();
/ / Вихідний потік для читання інформації з сокета
OutputStream os = sc.openOutputStream ();
Для відкриття з'єднання для очікування з'єднання буде потрібно наступна конструкція:
/ / Встановити сокет на 5000 порту
ServerSocketConnection scn = (ServerSocketConnection) Connector.open ("socket: / /: 5000");
/ / Очікувати з'єднання від інших машин
SocketConnection sc = (SocketConnection) scn.acceptAndOpen ();

Література.

1. Кен Арнольд, Джеймс Гослінг, Девід Холмс. Мова програмування Java ™.
2. Офіційний сайт Java - http://java.sun.com/ (є розділ російською мовою з підручником).
3. Java ™ 2 SDK, Micro Edition Documentation - http://java.sun.com/products/midp/index.jsp
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Методичка
39.5кб. | скачати


Схожі роботи:
Розробка пристрою сполучення для персонального комп`ютера типу IBM PC
Розробка схеми блоку арифметико-логічного пристрою для множення двох двійкових чисел
Розробка пакета прикладних програм для обчислення визначника матриці
Створення бази даних функціональних аналогів Windows-програм для ОС Linux і розробка методики
Розробка зарядного пристрою
Розробка обчислювального пристрою
Розробка пристрою узгодження
Розробка математичної моделі електронного пристрою
Розробка топково-пальникового пристрою котла
© Усі права захищені
написати до нас