Лекция по программированию под мобильные устройства. Современные средства связи обладают достаточно высокой производительностью. Например, некоторые коммуникаторы на windows mobile имеют 400 мгц тактовую частоту процессора и 64 Мбайт озу.
Вид материала | Лекция |
- О проведении государственных закупок озу (оперативного запоминающего устройства) ddr, 22.56kb.
- Языкознание, 38.16kb.
- Реферат на тему: «Подсистема памяти современных компьютеров», 491.05kb.
- Естественные науки, 143.25kb.
- Для сотовых сетей связи (мобильные телефоны, а также модемы, применяемые в сотовых, 307.64kb.
- Реферат на тему «Современные средства связи», 196.43kb.
- Финансовая академия при правительстве российской федерации, 234.72kb.
- Реферат на тему: Теория и практика производства накопителей на гибких магнитных дисках, 231.07kb.
- Анальгетики, то есть обезболивающие средства (анальгезирующие средства), 393.4kb.
- Звуковые устройства Звук, 450.41kb.
Лекция по программированию под мобильные устройства.
Современные средства связи обладают достаточно высокой производительностью. Например, некоторые коммуникаторы на windows mobile имеют 400 МГц тактовую частоту процессора и 64 Мбайт ОЗУ. Все несколько лет назад такой производительностью обладали лучшие стационарные компьютеры. Естественно, эту вычислительную способность можно использовать.
Существует 2 подхода к программированию под эти платформы:
1.Использование интерпретируемых языков программирования .К примеру, есть интерпретатор питона для платформы Symbian 8+.
2.Использование языка java и виртуальной машины . По производительности, этот вариант лучше, чем интерпретируемые языки программирования, но хуже по производительности, чем написание программы на C++ с компиляцией под конкретный телефон. Но j2me обеспечивает переносимость между телефонами различных моделей и производителей, тогда как C++ только между одинаковыми моделями.В отличие от интерпретируемых языков,j2me ,как правило, часть предустановленного ПО телефона, поэтому не требует специальной установки на телефон, в отличие от интерпретируемых языков,которые нужно устанавливать специально.
3.Использование компилируемых языков. Однако, второй подход применим только к сотовым телефонам следующего поколения (смартфонам).Написание native программ для смартфонов значительно сложнее, чем для PC.(это не относится к win mobile смартфонам в силу того, что архитектура win mobile похожа на архитектуру windows NT 4.0)
В лекции будет рассмотрено программирование под j2me и под ОС Symbian.
J2me.
Спецификация j2me была предложена компанией Sun для производителей телевизионных приставок и мобильных телефонов. При создании этой спецификации учитывались такие особенности мобильных устройств, как процессор с низкой производительностью, очень малый объем оперативной памяти, малый объем системной памяти.
j2me ,в отличие от j2se не предусматривает возможности расширения библиотек, используемых программой. Все версии j2me имеют 2 основные библиотеки: CLDC и MID profile. Производители устройств могут также добавлять в j2me библиотеки расширения.
Мидлет.
Любое j2me приложение должно иметь класс, унаследованный, от javax.microedition.midlet.MIDlet .
Этот класс обязательно должен иметь 3 метода:
protected void startApp() throws MIDletStateChangeException
protected void pauseApp()
protected void destroyApp(boolean b) throws MIDletStateChangeException
Метод startApp() вызывается при первом запуске программы. Этот метод может также вызываться после возобновления работы программы, если ранее выполнение программы было приостановлено.
Метод pauseApp() вызывается, если приложение поставили на паузу.
Метод destroyApp(boolean b) будет вызван перед тем, как программа завершит работу.
Программирование интерфейса пользователя.
Для разработки интерфейса пользователя используется пакет javax.microedition.lcdui .
Основой для построения пользовательского интерфейса является класс Display. Особенностью мобильной платформы является малый размер экрана, поэтому приложение одновременно может отображать только одно рабочее окно. Для установки текущего отображаемого окна используется метод Display.setCurrent(Displayable) .В j2me не используется стандартная модель обработки событий, используемая в j2se. Вместо этого, обработкой события занимается компонент, которому событие было адресовано. Для стандартных компонентов необходимо устанавливать класс-обработчик событий.
В j2me существует 2 уровня API.
В случае высокоуровневого API расположением компонентов ввода и обработкой низкоуровневых событий управляет реализация j2me.В этом случае обеспечивается максимальная совместимость с устройствами.
Существует также низкоуровневое API ,позволяющее производить низкоуровневую обработку и рисовать собственный интерфейс приложения. Но совместимость обеспечивает в этом случае сам программист.
Высокоуровневое API.
Высокоуровневое API используется для бизнес приложений, клиентская часть которой исполняется в j2me.В этом случае необходима максимальная совместимость с j2me устройствами. Чтобы это обеспечить,API обеспечивает высокий уровень абстракции ,но обеспечивает очень малый контроль над UI и управлением.
Абстракция над параметрами дисплея обеспечивается:
1.Рисование содержимого дисплея обеспечивается реализацией. Приложение не может изменять параметры выводимого изображения, такие как цвет, шрифт и т.п.
2. Навигация, прокрутка и прочие примитивные операции обеспечивается реализацией, приложение не получает уведомления об этих операциях.
3. Приложения не могут получить доступ к конкретным устройствам ввода, например, к конкретным клавишам клавиатуры.
Некоторые классы для построения высокоуровневого API.
Form.
Отображаемый компонент-окно, которое используется в качестве контейнера для компонентов редактирования. Необходим, когда нужно показать пользователю диалог, в котором требуется вветси несколько параметров. В форму добавляются компоненты другие компоненты ввода: текстовые поля TextField, компоненты выбора ChoiceGroup, кнопки StringItem.
Alert.
Информационное окно, необходимое, чтобы показать пользователю некоторое информационное сообщение.
TextBox.
Окно для ввода длинного текста(аналогично диалогу для ввода СМС в меню вашего телефона).
Пример интефейса пользователя с высокоуровневым API.
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.*;
public class HelloWorldRunner1 extends MIDlet implements CommandListener
{
boolean firstRun=true;
private Form helloWorldForm;
private String helloWorld2;
private Display display = Display.getDisplay(this);
protected void startApp() throws MIDletStateChangeException
{
if(firstRun)
{
firstRun=false;
Alert alert = new Alert("hello");
TextBox textbox = new TextBox("enter hello text", "", 200, TextField.ANY);
textbox.addCommand(new Command("ok",Command.ITEM,1));
textbox.setCommandListener(new HelloWorldListener2(alert, textbox,helloWorldForm));
helloWorldForm=new Form("hello world");
StringItem stringItem=new StringItem("do hello","",Item.BUTTON);
Command command2= new Command("Command2",Command.ITEM, 2)
stringItem.addCommand(command2);
stringItem.addCommand(new Command("Command3",Command.ITEM,3));
stringItem.setDefaultCommand(command2);
stringItem.setItemCommandListener(new HelloWorldListener1(alert, textbox));
helloWorldForm.append(stringItem);
helloWorldForm.addCommand(new Command("exit",Command.EXIT,0));
helloWorldForm.setCommandListener(this);
}
display.setCurrent(helloWorldForm);
}
protected void pauseApp()
{
}
protected void destroyApp(boolean b) throws MIDletStateChangeException
{
notifyDestroyed();
}
private class HelloWorldListener1 implements ItemCommandListener
{
private Alert alert;
private TextBox sourceDataBox;
public HelloWorldListener1(Alert alert, TextBox sourceDataBox)
{
this.alert = alert;
this.sourceDataBox = sourceDataBox;
}
public void commandAction(Command command, Item item)
{
String label=command.getLabel();
if(command.getLabel().equals("Command2"))
{
display.setCurrent(sourceDataBox);
}
if(command.getLabel().equals("Command3"))
{
alert.setString(helloWorld2);
display.setCurrent(alert);
}
}
}
private class HelloWorldListener2 implements CommandListener
{
private Alert alert;
private TextBox sourceDataBox;
private Form main;
public HelloWorldListener2(Alert alert, TextBox sourceDataBox, Form main)
{
this.alert = alert;
this.sourceDataBox = sourceDataBox;
}
public void commandAction(Command command, Displayable displayable)
{
helloWorld2=sourceDataBox.getString();
display.setCurrent(helloWorldForm);
}
}
public void commandAction(Command command, Displayable displayable)
{
if (command.getCommandType() == Command.EXIT)
{
try
{
destroyApp(true);
Display.getDisplay(this).setCurrent(null);
} catch (MIDletStateChangeException e)
{
}
}
}
}
Низкоуровневое API.
Применяется в том случае, когда необходимо отобразить информацию, которую невозможно отобразить стандартными средствами. Для того,чтобы использовать возможности низкоуровневого API,нужно создать свой класс,унаследованный от класса Canvas.Обработка ввода пользователем осуществляется в пределах этого же класса,для этого нужно переопределить метод,в который посылается события пользовательского ввода(например, в методе protected void keyPressed(int keyCode) осуществляется обработка ввода с клавиатуры ).Рисование осуществляется в методе Paint.
Пример низкоуровневого API.
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.*;
public class HelloWorldRunner2 extends MIDlet implements CommandListener
{
protected void startApp() throws MIDletStateChangeException
{
HelloLowLevelApiCompenent manager=new HelloLowLevelApiCompenent();
Display display=Display.getDisplay(this);
display.setCurrent(manager);
manager.addCommand(new Command("Exit",Command.EXIT,0));
manager.setCommandListener(this);
}
protected void pauseApp()
{
notifyPaused();
}
protected void destroyApp(boolean b) throws MIDletStateChangeException
{
notifyDestroyed();
}
boolean pressed=false;
public void commandAction(Command command, Displayable displayable)
{
if(command.getLabel().equals("Exit"))
{
try
{
destroyApp(true);
Display.getDisplay(this).setCurrent(null);
} catch (MIDletStateChangeException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
}
public class HelloLowLevelApiCompenent extends Canvas
{
protected void paint(Graphics graphics)
{
int width = getWidth(), height = getHeight();
graphics.setColor(255, 255, 255);
graphics.fillRect(0, 0, width, height);
graphics.setColor(0, 0, 0);
graphics.drawRect(0, 0, width, height);
if(pressed)
{
graphics.fillRect(0,0,width,height);
graphics.setColor(255,0,0);
}
graphics.setColor(255,0,0);
graphics.drawRect(width/4,height/4,width/2,height/2);
}
protected void keyPressed(int keyCode)
{
int action=getGameAction(keyCode);
if(action==FIRE)
{
pressed=!pressed;
repaint();
}
}
}
}
Работа с хранилищем (замена полноценной файловой системы в MIDP 1.0)
Пакет javax.microedition.rms содержит классы для работы с хранилищем.
Создание хранилища.
Запись в хранилище.
RecordStore rs= RecordStore.openRecordStore("test",true);
int recordId=rs.addRecord(new byte[]{1,2,3,4,5,6},0,6);
rs.closeRecordStore();
Чтение данных,сохраненных в хранилище.
RecordStore rs= RecordStore.openRecordStore("test",true);
int numRecord=rs.getNumRecords()+1;
for(int j=1;j
{
byte[] record= rs.getRecord(j);
for(int i=0;i
{
System.out.println(record[i]);
}
}
rs.closeRecordStore();
Работа с файловой системой(jsr75)
Пример кода.
try
{
Enumeration e = FileSystemRegistry.listRoots();
String directory="";
while(e.hasMoreElements())
{
directory= (String) e.nextElement();
System.out.println(directory);
}
FileConnection fc= (FileConnection) Connector.open("file://storage/"+directory+"/test.txt");
if(!fc.exists())
{
fc.create();
}
OutputStream out=fc.openOutputStream();
out.write(10);
out.close();
fc= (FileConnection) Connector.open("file://storage/"+directory+"/test.txt");
InputStream fis = fc.openInputStream();
byte[] b = new byte[1024];
int length = fis.read(b, 0, 1024);
System.out.println( length);
for(int i=0;i
{
System.out.println(b[i]);
}
fis.close();
} catch (IOException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
ОС symbian.
Операционная система Symbian — одно из наиболее интересных явлений в мире ОС за последние годы. Успешно противостоя натиску Microsoft на мобильном рынке, эта система сегодня стала едва ли не самой распространенной в смартфонах и коммуникаторах.
Symbian — далекий потомок операционной системы EPOC, изначально создававшейся для карманных компьютеров Psion. Компактная, быстрая и надежная ОС пережила несколько инкарнаций, в конце концов превратившись в современную Symbian. Платформа Symbian — уникальный пример системы, совместившей в себе как академические традиции с их тщательностью проработки базовых концепций, так и прагматичность, свойственную коммерческим проектам.
Ядро
Symbian OS —пример распространенной микроядерной (если говорить о версии ядра EKA2, то и наноядерной) операционной системы.. Более того, если говорить о ядре, то одной из основных особенностей версии Symbian 9.0 стал переход на технологию «наноядра» (ЕКА 2, EPOC Kernel Architecture 2). EKA2 — многопоточное ядро с высоким уровнем реентерабельности и атомарности операций (например, допускается вызов обработчика прерывания даже во время процедуры переключения контекста). Оно также обеспечивает возможность работы в режиме реального времени (изначально это делалось, чтобы разработчики аппаратных средств могли отказаться от GSM-модулей, функционирующих под управлением специализированных ОС, переложив эту задачу на центральный процессор).
Будучи микроядерной операционной системой, Symbian «выносит» практически все прикладные (т. е. выходящие за пределы компетенции ядра) задачи в модули-серверы, функционирующие в пользовательском адресном пространстве. Это, правда, не избавляет от регулярных сбоев в смартфонах с этой ОС, но позволяет предотвратить потерю пользовательских данных.
Основные API
Возможности Symbian OS весьма обширны — в отличие от j2me,Symbian полноценная операционная система. К ним относятся стандартные средства (планирование процессов и управление ресурсами, запуск программ и связывание динамических библиотек, вывод графики и работа с сетью), а также инструментарий для трехмерной графики (даже акселерированной посредством Open GS ES), работы с мультимедийными потоками в реальном времени (это не только музыка, но и VoIP), Location API (для подключения источников географической информации) и пр.
Все возможности Symbian OS распределены по компонентам, независимым от остальной системы (при этом допускается удаление одного из них без ущерба для всего комплекса). Назначение базового API (модуль Base) очевидно, стоит только отметить, что вместо многих стандартных решений, таких, как, скажем, стандартная библиотека Си++, используются собственные решения, более эффективные в рамках идеологии этой ОС. Подсистема безопасности отвечает за реализацию криптографических алгоритмов, управление сертификатами, инсталляцию ПО и пр. Графический модуль содержит API для отрисовки графики и текста, управления шрифтами, вставки картинок и др. В него также входит клиентский API Window Server и подсистема анимации.
Подсистема «прикладных каркасов» (application framework) — решение, специфичное для Symbian OS. Идеология Symbian OS предполагает разнесение прикладной логики программы и пользовательского интерфейса(ГИП). Базовые структуры и принципы работы (например, предположение о том, что у всякой программы-редактора есть документ, с которым она работает) или средства обработки клавиатурного ввода заложены и частично реализованы в «каркасе». Фактически именно эта подсистема предоставляет реальным прикладным программам универсальный механизм для решения типовых задач. ГИП может отличаться от устройства к устройству, но принципы его работы неизменны.
Программные «движки» (engines) инкапсулируют логику прикладных программ. Они независимы от ГИП и при необходимости их можно использовать напрямую (скажем, при доступе к данным календаря для его «движка» не важно, чей вызов обслуживается: собственного пользовательского интерфейса или сторонней программы). На этом же уровне функционируют подсистемы обработки мультимедиа и сервисные библиотеки. Наконец, стек протоколов содержит сетевые и коммуникационные компоненты, а также средства синхронизации и телефонии (подсистема расширяема, процесс подключения модулей, реализующих новые стандарты, прост).
Подсистема безопасности (начиная с Symbian v9.x) предполагает предотвращение доступа к структуре каталогов (для «неподписанных» программ, например, запрещен доступ к каталогам других утилит, системному каталогу), доступ к некоторым данным возможен в режиме «только чтение». Самое же неприятное — так называемая «модель возможностей» (capabilities), определяющая доступность тех или иных API. Открытые API составляют около 60% от всех функций ОС, «базовые» включают в себя коммуникационные подсистемы (Интернет, Bluetooth, сотовая связь и др.) и PIM. Они тоже доступны, но попытка вызвать, скажем, функцию отсылки SMS со стороны несертифицированной программы приводит к появлению запроса на разрешение этого действия, тогда как сертифицированная сможет сделать это прозрачно и незаметно для пользователя. В «расширенные» API входят функции, позволяющие манипулировать системной информацией, а «права изготовителя» — предоставляют самый полный контроль над устройством.
Уникальные идентификаторы
Уникальный идентификатор (UID) — фундаментальная, хотя и небесспорная концепция Symbian OS. Наличие схемы сквозной идентификации объектов полезно, но в ряде случаев создает неудобства. Впрочем, UID — это «реальность, данная нам», и любой, кто задумывается о разработке для Symbian OS, должен понимать, для чего они используются. В целом UID состоит из трех 32-бит значений: UID1, UID2 и UID3. UID1 — глобальный идентификатор системного уровня. В частности, он назначается исполнимым модулям и определяет их тип (программа, библиотека, и др.). UID2 задает тип программы (скажем, наличие или отсутствие ГИП). UID3 определяет принадлежность всех компонентов, имеющих отношение к заданной сущности.
Идентификаторы UID, в частности, используются и для сопоставления файлов данных и обрабатывающих их программ. Объект может и не иметь UID (например, если файл был получен извне, то система пытается определить тип файла по таблице соответствий MIME-типов). UID3 — наиболее важный из идентификаторов, при появлении в ОС разных программ с одним идентификатором блокируются все (возникает системная ошибка). Существует также идентификатор платформы (Platform UID), который используется для обозначения совместимости прикладной программы с той или иной редакцией Symbian OS.
Уникальность UID предполагает одну особенность, которая не всегда очевидна для начинающих разработчиков: UID действительно должны быть уникальными. На этапе разработки допускается использование «нелицензируемых» UID в диапазоне 0x01000000 — 0x0fffffff. Чтобы избежать накладок при выпуске программы, принята схема запроса UID у разработчика ОС, обычно для этого достаточно послать письмо по электронной почте (на адрес id@symbiandevnet.com), в ответ на которое выдается несколько (обычно 10) идентификаторов.
Соглашения об именах
При разработке для Symbian OS приняты определенные правила именования классов и других структур (подробно они изложены в документации).
Структура программы
Symbian — объектная операционная система. Все реализовано в виде объектов и классов. Вызов функции — действие, выходящее за пределы идеологии ОС. Учитывая, что в состав системы входят сотни классов и тысячи функций, такой подход можно только приветствовать.
Де-факто типичная прикладная программа есть не что иное, как DLL, предоставляющая функции, которые вызываются системными объектами ГИП. Есть и другие варианты, но они встречаются реже (в частности, службы). В версии 9.x от этой практики отказались, программа может быть и полноценным исполнимым модулем (важное следствие — возможность размещения статических данных и обработка исключений в стиле Си++). Но среднестатистическая программа (файл с расширением .app) представляет собой исполнимый модуль, зависящий от «каркаса» (предоставленного ОС). Утрируя, можно сказать, что не программа, совершая действия, заложенные в нее разработчиком, время от времени обращается к ОС с целью выполнения каких-то действий, скажем отрисовки диалогового окна, а, наоборот, ОС запускает подсистему ГИП, а та «дергает» функции, возвращающие данные (точнее, объекты), которые отрисовываются системными средствами. Это, кстати, целиком вписывается в концепцию разделения прикладного ядра (engine) и интерфейса, а также убирает зависимость от конкретной графической библиотеки и теоретически (на практике, разумеется, хватает подводных камней) упрощает перенос ПО между системами с разными типами ГИП.
Прикладная программа должна использовать четыре основных класса: системное ядро (Application), «документ» (Document), реализацию ГИП (App UI) и «графическое поле» (View). В классе «ядро» необходимо реализовать базовые функции, минимум — две (обе вызываются сразу после загрузки прикладной DLL). NewApplication() создает объект, и E32Main() определяет точку входа. Как таковой, этот объект отвечает за базовое взаимодействие программы с ОС. В прикладном классе, созданном посредством NewApplication(), могут быть определены свойства, общие для всех экземпляров данной программы. Объекты, разумеется, зависят от используемой редакции Symbian OS, — скажем, при работе с Series 60 ядро будет порождаться от класса CAknApplication.
Далее необходимо создать «документ» (даже если он не нужен и впоследствии будет проигнорирован; вообще, «документ» — это довольно удобное структурированное хранилище информации, так что имеет смысл его использовать, раз уж создан). Здесь же системе сообщается UID (поскольку функция генерации экземпляра должна возвращать UID2). Необходимость создания документа обусловлена тем, что в ходе этого процесса инициализируются также системные компоненты ГИП. В целом эта схема похожа на атавизм времен EPOC с ее документно-ориентированной идеологией, но в действительности не лишена изящества и к ней довольно быстро привыкаешь. Как бы то ни было, стоит запомнить: даже если разрабатывается «Hello, World», необходим документ.
Интерфейсный класс задает базовые элементы управления, запускает цикл обработки сообщений и т. д.
Еще одно фундаментальное понятие практически для любой программы Symbian OS — вид (View). Это базовый элемент управления, с которым работает программа, выводя информацию. С некоторыми упрощениями можно назвать его «экранной формой», на которой размещаются прочие составные части ГИП. Логика работы с ним (как и вся архитектура и использование объектов управления в Symbian OS) — предмет, требующий отдельной статьи.
Инструментарий и разработка
Разработка для Symbian OS (если говорить о Си++) обычно ведется на ПК. Среда разработки — привычная многим программистам Visual Studio, это также могут быть IDE Metrowerks CodeWarrior Development Studio, Borland C++BuilderX Mobile Edition, Carbide.C++ (относительно новая IDE, созданная компанией Nokia на базе Eclipse), снабженная дополнительными инструментальными пакетами (SDK). Разработчику доступны практически все привычные возможности в отношении как создания ПО, так и отладки (трассировка, просмотр переменных, стека вызовов, структур классов и др.).
В
Отлаживаемая программа запускается в эмуляторе Symbian OS.
SDK Symbian определенно оценить довольно сложно. Он неплох — но непривычен.
Многие, наверное, уже догадались, что «SDK для Symbian OS» — вещь довольно расплывчатая при наличии такого количества редакций базовой системы. Несмотря на общую принадлежность к Symbian OS, конкретные SDK сильно различаются.
Проекты для Symbian OS сохраняются в файлах .mmp (аналог привычных файлов make), которые содержат ссылки и команды, необходимые для обработки программных модулей, ресурсов и пр.
Программа с ГИП должна иметь не менее двух ресурсных файлов. В первом записывается пиктограмма изображения, во втором — параметры регистрации (записывается в каталоге \private\10003a3f\apps; так называемое «централизованное хранилище», на первый взгляд похожее на реестр Windows, но в то же время существенно от него отличное). Аналогично задаются библиотеки (как минимум необходима euser.lib). Впрочем, большинство IDE успешно скрадывают сложности этого процесса (или способны импортировать файлы .mmp, записывая информацию в собственных структурах).
Эмулятор
После инсталляции SDK в подкаталоге создается развесистое дерево каталогов (в подкаталоге epoc32\). Фактически существует две версии эмулятора — с отладочными средствами в системных библиотеках и без них.
Инсталляция и распространение
Инсталляция и распространение — процессы, которые в Symbian OS за последнее время стали менее удобными в основном из-за злоумышленников, которые избрали смартфоны своей очередной мишенью. Проблема вирусов как таковых в Symbian отсутствует (впрочем, классических вирусов сегодня вообще немного), куда больше проблем доставляют разного рода «троянские кони», маскирующиеся под прикладное ПО (и даже под антивирусы). Устанавливая такую программу, пользователь может считать, что имеет дело с благонамеренной утилитой или игрой, но получит «троянский модуль» (возможностей навредить много: чаще всего со смартфона похищается личная информация или же «троян» пытается использовать разного рода платные услуги, например основанные на SMS).Это выливается в ужесточение политики разработчиков ОС и изготовителей аппаратных средств, когда на смартфон допускается инсталляция только ПО, имеющего соответствующую цифровую подпись и прошедшего испытания в их лабораториях. Этот процесс оплачивается (250–600 долл. за попытку сертификации, которую программа не обязательно пройдет; отметим, что для создателей бесплатных программ предлагается и бесплатная сертификация, но на довольно жестких условиях), он занимает определенное время и требует дополнительных усилий.
На этапе разработки автор может использовать «самоподписанные» программы или «сертификат разработчика» (он привязывается к серийному номеру самого телефона). Это упрощает процесс, но и накладывает ряд ограничений, — в частности, некоторые API доступны только сертифицированным партнерам. Список таких подсистем постоянно расширяется (на сегодня туда входят, например, низкоуровневая обработка нажатий клавиш, доступ к файловой системе и др.).
Как бы то ни было, подготовленная для распространения программа должна быть запакована в архивный файл специального формата (с расширением .sis). Это основная форма существования дистрибутивных модулей для Symbian OS.. Этот файл должен быть скопирован в память телефона (или напрямую, или посредством коммуникационных утилит, обычно пакета PC Suite) и запущен там. Если цифровая подпись отсутствует, при попытке инсталляции выдается предупреждение о ее отсутствии. В большинстве современных моделей пользователь может инсталлировать программу на свой страх и риск, но, учитывая описанные выше тенденции, есть основания полагать, что в недалеком будущем установка несертифицированных модулей будет заблокирована (впрочем, здесь все зависит от политики изготовителя устройства).
Формат SIS предоставляет довольно много возможностей для организации интеллектуального процесса установки. В частности, можно запросить выдачу текста (скажем, лицензионного соглашения), определить модули, от которых зависит данный пакет, задать выбор места инсталляции (в памяти телефона или на карте памяти), запустить программу и пр. Дистрибутивные файлы могут быть вложенными. С учетом требования цифровой подписи процесс формирования файла SIS — многоступенчатый, с отдельными этапами создания, подписи, генерации ключей и др. Сценарий процесса создания собственно дистрибутивного пакета описывается в файле PKG (синтаксис его вполне прост).
Программирование под OS Symbian.
Hello world.
Заголовочные файлы.
helloWorldApplication.h
/*
============================================================================
Name : helloWorldApplication.h
Author :
Copyright : Your copyright notice
Description : Declares main application class.
============================================================================
*/
#ifndef __HELLOWORLDAPPLICATION_H__
#define __HELLOWORLDAPPLICATION_H__
// INCLUDES
#include
// CLASS DECLARATION
/**
* ChelloWorldApplication application class.
* Provides factory to create concrete document object.
* An instance of ChelloWorldApplication is the application part of the
* AVKON application framework for the helloWorld example application.
*/
class ChelloWorldApplication : public CAknApplication
{
public: // Functions from base classes
/**
* From CApaApplication, AppDllUid.
* @return Application's UID (KUidhelloWorldApp).
*/
TUid AppDllUid() const;
protected: // Functions from base classes
/**
* From CApaApplication, CreateDocumentL.
* Creates ChelloWorldDocument document object. The returned
* pointer in not owned by the ChelloWorldApplication object.
* @return A pointer to the created document object.
*/
CApaDocument* CreateDocumentL();
};
#endif // __HELLOWORLDAPPLICATION_H__
// End of File
helloWorldAppUi.h
/*
============================================================================
Name : helloWorldAppUi.h
Author :
Copyright : Your copyright notice
Description : Declares UI class for application.
============================================================================
*/
#ifndef __HELLOWORLDAPPUI_h__
#define __HELLOWORLDAPPUI_h__
// INCLUDES
#include
// FORWARD DECLARATIONS
class ChelloWorldAppView;
// CLASS DECLARATION
/**
* ChelloWorldAppUi application UI class.
* Interacts with the user through the UI and request message processing
* from the handler class
*/
class ChelloWorldAppUi : public CAknAppUi
{
public: // Constructors and destructor
/**
* ConstructL.
* 2nd phase constructor.
*/
void ConstructL();
/**
* ChelloWorldAppUi.
* C++ default constructor. This needs to be public due to
* the way the framework constructs the AppUi
*/
ChelloWorldAppUi();
/**
* ~ChelloWorldAppUi.
* Virtual Destructor.
*/
virtual ~ChelloWorldAppUi();
private: // Functions from base classes
/**
* From CEikAppUi, HandleCommandL.
* Takes care of command handling.
* @param aCommand Command to be handled.
*/
void HandleCommandL( TInt aCommand );
/**
* HandleStatusPaneSizeChange.
* Called by the framework when the application status pane
* size is changed.
*/
void HandleStatusPaneSizeChange();
private: // Data
/**
* The application view
* Owned by ChelloWorldAppUi
*/
ChelloWorldAppView* iAppView;
};
#endif // __HELLOWORLDAPPUI_h__
// End of File
helloWorldAppView.h
/*
============================================================================
Name : helloWorldAppView.h
Author :
Copyright : Your copyright notice
Description : Declares view class for application.
============================================================================
*/
#ifndef __HELLOWORLDAPPVIEW_h__
#define __HELLOWORLDAPPVIEW_h__
// INCLUDES
#include
// CLASS DECLARATION
class ChelloWorldAppView : public CCoeControl
{
public: // New methods
/**
* NewL.
* Two-phased constructor.
* Create a ChelloWorldAppView object, which will draw itself to aRect.
* @param aRect The rectangle this view will be drawn to.
* @return a pointer to the created instance of ChelloWorldAppView.
*/
static ChelloWorldAppView* NewL( const TRect& aRect );
/**
* NewLC.
* Two-phased constructor.
* Create a ChelloWorldAppView object, which will draw itself
* to aRect.
* @param aRect Rectangle this view will be drawn to.
* @return A pointer to the created instance of ChelloWorldAppView.
*/
static ChelloWorldAppView* NewLC( const TRect& aRect );
/**
* ~ChelloWorldAppView
* Virtual Destructor.
*/
virtual ~ChelloWorldAppView();
public: // Functions from base classes
/**
* From CCoeControl, Draw
* Draw this ChelloWorldAppView to the screen.
* @param aRect the rectangle of this view that needs updating
*/
void Draw( const TRect& aRect ) const;
/**
* From CoeControl, SizeChanged.
* Called by framework when the view size is changed.
*/
virtual void SizeChanged();
private: // Constructors
/**
* ConstructL
* 2nd phase constructor.
* Perform the second phase construction of a
* ChelloWorldAppView object.
* @param aRect The rectangle this view will be drawn to.
*/
void ConstructL(const TRect& aRect);
/**
* ChelloWorldAppView.
* C++ default constructor.
*/
ChelloWorldAppView();
};
#endif // __HELLOWORLDAPPVIEW_h__
// End of File
helloWorldDocument.h
/*
============================================================================
Name : helloWorldDocument.h
Author :
Copyright : Your copyright notice
Description : Declares document class for application.
============================================================================
*/
#ifndef __HELLOWORLDDOCUMENT_h__
#define __HELLOWORLDDOCUMENT_h__
// INCLUDES
#include
// FORWARD DECLARATIONS
class ChelloWorldAppUi;
class CEikApplication;
// CLASS DECLARATION
/**
* ChelloWorldDocument application class.
* An instance of class ChelloWorldDocument is the Document part of the
* AVKON application framework for the helloWorld example application.
*/
class ChelloWorldDocument : public CAknDocument
{
public: // Constructors and destructor
/**
* NewL.
* Two-phased constructor.
* Construct a ChelloWorldDocument for the AVKON application aApp
* using two phase construction, and return a pointer
* to the created object.
* @param aApp Application creating this document.
* @return A pointer to the created instance of ChelloWorldDocument.
*/
static ChelloWorldDocument* NewL( CEikApplication& aApp );
/**
* NewLC.
* Two-phased constructor.
* Construct a ChelloWorldDocument for the AVKON application aApp
* using two phase construction, and return a pointer
* to the created object.
* @param aApp Application creating this document.
* @return A pointer to the created instance of ChelloWorldDocument.
*/
static ChelloWorldDocument* NewLC( CEikApplication& aApp );
/**
* ~ChelloWorldDocument
* Virtual Destructor.
*/
virtual ~ChelloWorldDocument();
public: // Functions from base classes
/**
* CreateAppUiL
* From CEikDocument, CreateAppUiL.
* Create a ChelloWorldAppUi object and return a pointer to it.
* The object returned is owned by the Uikon framework.
* @return Pointer to created instance of AppUi.
*/
CEikAppUi* CreateAppUiL();
private: // Constructors
/**
* ConstructL
* 2nd phase constructor.
*/
void ConstructL();
/**
* ChelloWorldDocument.
* C++ default constructor.
* @param aApp Application creating this document.
*/
ChelloWorldDocument( CEikApplication& aApp );
};
#endif // __HELLOWORLDDOCUMENT_h__
// End of File
Исходный код.
helloWorld.cpp
/*
============================================================================
Name : helloWorld.cpp
Author :
Copyright : Your copyright notice
Description : Main application class
============================================================================
*/
// INCLUDE FILES
#include
#include "helloWorldApplication.h"
LOCAL_C CApaApplication* NewApplication()
{
return new ChelloWorldApplication;
}
GLDEF_C TInt E32Main()
{
return EikStart::RunApplication( NewApplication );
}
helloWorldApplication.cpp
/*
============================================================================
Name : helloWorldApplication.cpp
Author :
Copyright : Your copyright notice
Description : Main application class
============================================================================
*/
// INCLUDE FILES
#include "helloWorld.hrh"
#include "helloWorldDocument.h"
#include "helloWorldApplication.h"
// ============================ MEMBER FUNCTIONS ===============================
// UID for the application;
// this should correspond to the uid defined in the mmp file
const TUid KUidhelloWorldApp = { _UID3 };
// -----------------------------------------------------------------------------
// ChelloWorldApplication::CreateDocumentL()
// Creates CApaDocument object
// -----------------------------------------------------------------------------
//
CApaDocument* ChelloWorldApplication::CreateDocumentL()
{
// Create an helloWorld document, and return a pointer to it
return (static_cast
( ChelloWorldDocument::NewL( *this ) ) );
}
// -----------------------------------------------------------------------------
// ChelloWorldApplication::AppDllUid()
// Returns application UID
// -----------------------------------------------------------------------------
//
TUid ChelloWorldApplication::AppDllUid() const
{
// Return the UID for the helloWorld application
return KUidhelloWorldApp;
}
// End of File
helloWorldAppUi.cpp
/*
============================================================================
Name : helloWorldAppUi.cpp
Author :
Copyright : Your copyright notice
Description : ChelloWorldAppUi implementation
============================================================================
*/
// INCLUDE FILES
#include
#include
#include
#include
#include
#include
#include "helloWorld.pan"
#include "helloWorldAppUi.h"
#include "helloWorldAppView.h"
#include "helloWorld.hrh"
_LIT( KFileName, "C:\\private\\E58BBDBA\\helloWorld.txt" );
_LIT( KText, "Hello World!");
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// ChelloWorldAppUi::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void ChelloWorldAppUi::ConstructL()
{
// Initialise app UI with standard value.
BaseConstructL();
// Create view object
iAppView = ChelloWorldAppView::NewL( ClientRect() );
// Create a file to write the text to
RFs fsSession;
User::LeaveIfError(fsSession.Connect());
CleanupClosePushL( fsSession );
TInt err = fsSession.MkDirAll(KFileName);
if ( (KErrNone != err) && (KErrAlreadyExists != err) )
{
CleanupStack::PopAndDestroy(1); // fsSession
return;
}
RFile file;
err = file.Replace(fsSession, KFileName, EFileWrite );
CleanupClosePushL( file );
if ( KErrNone != err )
{
CleanupStack::PopAndDestroy(2); // file, fsSession
return;
}
RFileWriteStream outputFileStream( file );
CleanupClosePushL( outputFileStream );
outputFileStream << KText;
CleanupStack::PopAndDestroy(3); // outputFileStream, file, fsSession
}
// -----------------------------------------------------------------------------
// ChelloWorldAppUi::ChelloWorldAppUi()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
ChelloWorldAppUi::ChelloWorldAppUi()
{
// No implementation required
}
// -----------------------------------------------------------------------------
// ChelloWorldAppUi::~ChelloWorldAppUi()
// Destructor.
// -----------------------------------------------------------------------------
//
ChelloWorldAppUi::~ChelloWorldAppUi()
{
if ( iAppView )
{
delete iAppView;
iAppView = NULL;
}
}
// -----------------------------------------------------------------------------
// ChelloWorldAppUi::HandleCommandL()
// Takes care of command handling.
// -----------------------------------------------------------------------------
//
void ChelloWorldAppUi::HandleCommandL( TInt aCommand )
{
switch( aCommand )
{
case EEikCmdExit:
case EAknSoftkeyExit:
Exit();
break;
case ECommand1:
{
// Load a string from the resource file and display it
HBufC* textResource = StringLoader::LoadLC( R_COMMAND1_TEXT );
CAknInformationNote* informationNote;
informationNote = new ( ELeave ) CAknInformationNote;
// Show the information Note with
// textResource loaded with StringLoader.
informationNote->ExecuteLD( *textResource);
// Pop HBuf from CleanUpStack and Destroy it.
CleanupStack::PopAndDestroy( textResource );
}
break;
case ECommand2:
{
RFs fsSession;
RFile rFile;
// Connects a client process to the fileserver
User::LeaveIfError(fsSession.Connect());
CleanupClosePushL(fsSession);
//Open file where the stream text is
User::LeaveIfError(rFile.Open(fsSession,KFileName, EFileStreamText));//EFileShareReadersOnly));// EFileStreamText));
CleanupClosePushL(rFile);
// copy stream from file to RFileStream object
RFileReadStream inputFileStream(rFile);
CleanupClosePushL(inputFileStream);
// HBufC descriptor is created from the RFileStream object.
HBufC* fileData = HBufC::NewLC(inputFileStream, 32);
CAknInformationNote* informationNote;
informationNote = new ( ELeave ) CAknInformationNote;
// Show the information Note
informationNote->ExecuteLD( *fileData);
// Pop loaded resources from the cleanup stack
CleanupStack::PopAndDestroy(4); // filedata, inputFileStream, rFile, fsSession
fsSession.Close();
}
break;
default:
Panic( EhelloWorldUi );
break;
}
}
// -----------------------------------------------------------------------------
// Called by the framework when the application status pane
// size is changed. Passes the new client rectangle to the
// AppView
// -----------------------------------------------------------------------------
//
void ChelloWorldAppUi::HandleStatusPaneSizeChange()
{
iAppView->SetRect( ClientRect() );
}
// End of File
helloWorldAppView.cpp
/*
============================================================================
Name : helloWorldAppView.cpp
Author :
Copyright : Your copyright notice
Description : Application view implementation
============================================================================
*/
// INCLUDE FILES
#include
#include "helloWorldAppView.h"
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// ChelloWorldAppView::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
ChelloWorldAppView* ChelloWorldAppView::NewL( const TRect& aRect )
{
ChelloWorldAppView* self = ChelloWorldAppView::NewLC( aRect );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
ChelloWorldAppView* ChelloWorldAppView::NewLC( const TRect& aRect )
{
ChelloWorldAppView* self = new ( ELeave ) ChelloWorldAppView;
CleanupStack::PushL( self );
self->ConstructL( aRect );
return self;
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void ChelloWorldAppView::ConstructL( const TRect& aRect )
{
// Create a window for this application view
CreateWindowL();
// Set the windows size
SetRect( aRect );
// Activate the window, which makes it ready to be drawn
ActivateL();
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::ChelloWorldAppView()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
ChelloWorldAppView::ChelloWorldAppView()
{
// No implementation required
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::~ChelloWorldAppView()
// Destructor.
// -----------------------------------------------------------------------------
//
ChelloWorldAppView::~ChelloWorldAppView()
{
// No implementation required
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::Draw()
// Draws the display.
// -----------------------------------------------------------------------------
//
void ChelloWorldAppView::Draw( const TRect& /*aRect*/ ) const
{
// Get the standard graphics context
CWindowGc& gc = SystemGc();
// Gets the control's extent
TRect drawRect( Rect());
// Clears the screen
gc.Clear( drawRect );
}
// -----------------------------------------------------------------------------
// ChelloWorldAppView::SizeChanged()
// Called by framework when the view size is changed.
// -----------------------------------------------------------------------------
//
void ChelloWorldAppView::SizeChanged()
{
DrawNow();
}
// End of File
helloWorldDocument.cpp
/*
============================================================================
Name : helloWorldDocument.cpp
Author :
Copyright : Your copyright notice
Description : ChelloWorldDocument implementation
============================================================================
*/
// INCLUDE FILES
#include "helloWorldAppUi.h"
#include "helloWorldDocument.h"
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// ChelloWorldDocument::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
ChelloWorldDocument* ChelloWorldDocument::NewL( CEikApplication&
aApp )
{
ChelloWorldDocument* self = NewLC( aApp );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// ChelloWorldDocument::NewLC()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
ChelloWorldDocument* ChelloWorldDocument::NewLC( CEikApplication&
aApp )
{
ChelloWorldDocument* self =
new ( ELeave ) ChelloWorldDocument( aApp );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// -----------------------------------------------------------------------------
// ChelloWorldDocument::ConstructL()
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void ChelloWorldDocument::ConstructL()
{
// No implementation required
}
// -----------------------------------------------------------------------------
// ChelloWorldDocument::ChelloWorldDocument()
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
ChelloWorldDocument::ChelloWorldDocument( CEikApplication& aApp )
: CAknDocument( aApp )
{
// No implementation required
}
// ---------------------------------------------------------------------------
// ChelloWorldDocument::~ChelloWorldDocument()
// Destructor.
// ---------------------------------------------------------------------------
//
ChelloWorldDocument::~ChelloWorldDocument()
{
// No implementation required
}
// ---------------------------------------------------------------------------
// ChelloWorldDocument::CreateAppUiL()
// Constructs CreateAppUi.
// ---------------------------------------------------------------------------
//
CEikAppUi* ChelloWorldDocument::CreateAppUiL()
{
// Create the application user interface, and return a pointer to it;
// the framework takes ownership of this object
return ( static_cast
ChelloWorldAppUi ) );
}
// End of File