Programmation avancée avec MIDlet Pascal

krachik

Ce tutoriel aborde les concepts avancés de la programmation avec MIDlet Pascal.

Commentez

- Titre : Programmation avancée avec MIDlet Pascal

- Auteur : krachik

- Parution : 2 mars 2010

- Mise à jour : 11 mars 2010

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2010 AKAKPO-TOULAN Jules. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Introduction

- Les chaînes de caractères

- Les fonctions mathématiques

- Gestion des dates

- L'audio

- Les fichiers textes

- Gestion des touches

- getKeyClicked

- getKeyPressed

- keyToAction

- Comment dessiner à l'écran ?

- Fonctions de dessin

- Les couleurs

- Les images

- Comment créer une interface utilisateur ?

- Les menus

- Les formulaires

- Envoi de messages

- Connexion http

- Accès mémoire

- Librairies externes

- Le mode débogage

- Nouveautés de MIDlet Pascal 3

- Conclusion

Introduction

Nous aborderons dans ce tutoriel les spécificités de MIDlet Pascal. Le langage utilisé est proche du Pascal standard.

Notez que ce tutoriel n'aborde pas les concepts de base du langage Pascal, nécessaires tout de même à l'utilisation et la compréhension de certains thèmes.
Si vous débutez en Pascal, je vous propose une série de cours.

- Le langage Pascal

- Tutoriel sur Turbo Pascal, avec exercices.

Si vous avez déjà des notions du langage Pascal, je vous conseille de consulter le tutoriel Introduction au MIDlet Pascal 2.02 pour vous familiariser avec MIDlet Pascal. Nous n'aborderons donc que les possibilités qu'offre MIDlet Pascal pour faire vos applications, il vous revient après de construire les algorithmes sur lesquels seront bâtis vos programmes.

Le langage MIDlet Pascal ne respecte également pas la casse comme en Pascal standard.

Les chaînes de caractères

La gestion des chaînes de caractères avec MIDlet Pascal est légèrement différente de celle du Pascal standard. Ici une chaîne de caractère commencera à l'indice 0 au lieu de 1.

- copy est une fonction qui renvoie une sous-chaîne commençant à debut et finissant à fin - 1.

function copy(chaine: string; debut, fin: integer): string;

Cette fonction copy (de MIDlet Pascal) est différente de la fonction standarde du langage Pascal.

- length permet d'obtenir la longueur d'une chaîne de caractères.

function length(chaine: string): integer;

- pos : renvoie la position de la première occurrence de chaine2 dans chaine1. Si aucune occurrence n'est trouvée alors la fonction renvoie 0.

function pos(chaine1, chaine2: string): integer;

- upCase renvoie une copie en lettres capitales de la chaîne passée en paramètre. Elle crée donc une copie de la chaîne passée en paramètre en majuscule.

function upCase(chaine: string): string;

- loCase renvoie une copie de la chaîne passée en paramètre mettant toutes les lettres en minuscules.

function loCase(chaine: string): string;

- getChar retourne le caractère situé à une position donnée dans la chaîne.

function getChar(chaine: string; position:integer): char;

- setChar renvoie une copie de la chaîne passée comme 1er paramètre en remplaçant le caractère initial à la position choisie par le caractère passé comme second paramètre. La fonction retournera la même chaîne passée en paramètre si la position dépasse sa longueur.

function setChar(chaine: string; car: char; position:integer): string;

- stringToInteger effectue la conversion de la chaîne passée en paramètre en entier en base décimale, elle renvoie 0 si la conversion s'est mal passée.

function stringToInteger(chaine:string):integer;

- stringToReal convertit la chaîne en réel, dans la base passée en paramètre.

function stringToReal(str:string; base:integer):real;

- integerToString convertit un entier en chaîne de caractères.

function integerToString(val: integer): string;

Les cas les plus fréquents d'utilisation de integerToString, sont les cas où vous aurez besoin par exemple d'afficher un entier avec drawText.

var i: integer;
begin
{1 er cas d'affichage d'un entier avec drawText}
i := 3;
drawText(integerToString(i),0,0);
{2ème cas d'affichage d'un entier avec drawText}
drawText(''+i,0,0);
{vous verrez l'utilisation de drawText dans la suite du tutoriel}
repaint;
delay (2000);
end;

L'exemple ci-dessous illustre l'utilisation des différentes fonctions.

var chaine, result : String;
len,position, nombre :integer;
r :real;
begin
chaine :='MIDlet Pascal';
result := copy(chaine, 5, 10);
drawText(result, 0,0);{affichera 't Pas'}
len := length(result); {contient 5}
result := upCase (result); {mettre en majuscule toutes les lettres}
result := loCase (result); {mettre en miniscule toutes les lettres}
position := pos (result, 'asc'); {retournera -1}
drawText(''+ getChar(result, 2),0,0); {affichera P}
result := setChar (result, 'J', 3); {result ='t PJs'}
nombre := stringToInteger('1234'); {nombre =1234}
r := stringToReal('123.1',10); {r='123.1000'}
repaint;
delay(2000);
end.

Les fonctions mathématiques

abs
function abs(n: integer): integer;

Retourne la valeur absolue de l'entier passé en paramètre

acos
function acos(num: real):real;

Retourne l'arc cosinus d'un réel, le rendu est en radian compris entre 0 et 3.14 (pi)

asin
function asin(num: real):real;

Retourne l'arc sinus d'un réel, le rendu est en radian compris entre -pi/2 et pi/2

atan
function atan(num: real):real;

Retourne l'arc tangente d'un réel, le rendu est en radian compris entre -pi/2 et pi/2

atan2
function atan2(y,x: real):real;

Permet le passage des coordonnées cartésiennes en coordonnées polaires (r, theta), la fonction retourne donc theta en faisant l'arctan de y/x. Ensuite par exemple appliquez x/cos(theta) pour trouver r

cos
function cos(num: real):real;

Retourne le cosinus d'un réel représenté enradian

exp
function exp(num: real):real;

Retourne l'exponentiel de 1 élevé à la puissance num

frac
function frac(num: real):real;

Retourne la partie décimale du réel passé en paramètre

log
function log(num: real):real;

Retourne le logarithme d'un réel

log10
function log10(num: real):real;

Retourne le logarithme en base 10 d'un réel

pow
function pow(a, b: real):real;

Retourne la valeur de a élevé à la puissance b

rAbs
function rAbs(num:real):real;

Retourne la valeur absolue d'un réel

sin
function sin(num: real):real;

Retourne le sinus d'un réel représenté en radian

sqr
function sqr(n: integer): integer;

Retourne le carré d'un entier

sqrt
function sqrt(num: real):real;

retourne la racine carrée d'un réel

tan
function tan(num: real):real;

Retourne la tangente d'un angle représenté en radian

toDegree
function toDegrees(num: real):real;

Convertit un angle (radian) en degré

toRadian
function toRadians(num: real):real;

Convertit un angle (degré) en radian

trunc
function Trunc(num: real):integer;

Arrondit un nombre réel et renvoie sa partie entière

Gestion des dates

- getCurrentTime retourne le nombre de secondes écoulées depuis le 1er Janvier 1970.

function getCurrentTime: integer;

Une fois que vous avez récupéré le temps avec getCurrentTime, vous pouvez récupérer également l'heure du jour, la minute courante et le mois courant.

var temps: integer;
aff: string;
begin
time := GetCurrentTime;
aff := ' '+ GetYear(temps);
aff :=aff + ' '+ GetMonth(temps);
aff :=aff +  ' ' + GetDay(temps);
aff :=aff + '   ' + GetHour(temps);
aff := aff + ':'+ GetMinute(temps);
aff := aff + ':' + GetSecond(temps);
drawText(aff, 0, 0);
repaint;
delay(1000);
end.

- getHour retourne l'heure du temps passé en paramètre, la valeur retournée est comprise entre 0 et 23

function getHour(time: integer): integer;

- getMinute retourne les minutes du temps passé en paramètre, la valeur retournée est comprise entre 0 et 59

function getMinute(time: integer): integer;

- getSecond retourne les secondes du temps passé en paramètre, la valeur retournée est comprise entre 0 et 59

function getSecond(time: integer): integer;

- getDay retourne le jour du temps passé en paramètre, la valeur retournée est comprise entre 1 et 31

function getDay(time: integer): integer;

- getWeekDay retourne le jour de la semaine du temps passé en paramètre, la valeur retournée est comprise entre 1 et 7, le premier jour de la semaine étant Dimanche

function getWeekDay(time: integer): integer;

- getMonth retourne le mois du temps passé en paramètre, la valeur retournée est comprise entre 1 et 12

function getMonth(time: integer): integer;

- getYear retourne l'année du temps passé en paramètre

function getYear(time: integer): integer;

- getYearDay retourne le jour de l'année du temps passé en paramètre, la valeur retournée est comprise entre 1 et 366

function getYearDay(time: integer): integer;

L'audio

Quand vous programmez des applications pour téléphones mobiles, il est parfois intéressant d'y ajouter des effets sonores.
Pour lire un son, il faut commencer par le charger tout en précisant son type. Pour charger le fichier audio, il faut utiliser openPlayer.

function openPlayer(resource:string; mimetype:string):boolean;

Cette fonction retourne false si l'opération n'a pas réussi.
Exemple

if not openPlayer('/son.mid', 'audio/midi') then halt;

La version MIDlet Pascal 2.02 ne supporte que les sons MIDI. Notez également que tous les autres formats (audio/x-wav pour les sons waves, audio/mpeg pour les sons mp3 ) ne sont pas supportés par tous les téléphones mobiles. Vous pouvez toutefois jouer des sons avec voix sur des téléphones compatibles MIDP-2.0.

Il peut arriver que vous ayez envie de jouer un son un certain nombre de fois, pour ce cas d'utilisation il existe la fonction setPlayerCount.

function setPlayerCount(tourDeBoucle:integer):boolean;

tourDeBoucle est le nombre de fois que sera joué le son; cette fonction ne doit être appelée qu'après que le fichier son ait été chargé avec openPlayer. Donnez la valeur de -1 à tourDeBoucle si vous voulez jouer indéfiniment le son.
Exemple

if not openPlayer('/son.mid', 'audio/midi') then halt;
if not setPlayerCount(10) then halt;

Maintenant que nous savons comment charger le fichier son, comment fixer le nombre de fois qu'il sera joué, voyons comment démarrer sa lecture. Pour ce faire il faut utiliser startPlayer.

function startPlayer:boolean;

Cette fonction retourne false si la lecture du son n'a pas démarré.
Exemple

if not openPlayer('/son.mid', 'audio/midi') then halt;
if not setPlayerCount(10) then halt;
if not startPlayer then halt;

Notez l'ordre d'appel à ces fonctions.

Il existe d'autres fonctions comme :

- getPlayerDuration qui permet de connaître la durée en millisecondes d'un son

function getPlayerDuration:integer;

- stopPlayer qui permet d'arrêter un son en cours de lecture

procedure stopPlayer;

Exemple

if not openPlayer('/son.mid', 'audio/midi') then halt;
if not setPlayerCount(10) then halt;
if not startPlayer then halt;
duree := getPlayerDuration;
{Arrêter apres 2 secondes de lecture}
if (duree = 2000) then
stopPlayer;

Les fichiers textes

MIDlet Pascal permet de gérer plusieurs types de ressources fichiers: les fichiers sons et les fichiers images. Sont également gérés les fichiers textes, qui peuvent s'avérer utiles dans certaines applications.
Les ressources seront accessibles dans les applications depuis le jar.
Pour ouvrir un fichier il faut utiliser openResource. Je vous conseille, après avoir utilisé openResource, de tester si le fichier à bien été ouvert ou si le fichier est disponible avant toute autre opération. La fonction permettant de faire ceci est resourceAvailable.

ReadLine permet de lire une ligne du fichier.

Prenons un cas pratique simple : lire une ligne dans un fichier texte et l'afficher à l'écran.
Créons un fichier texte monfichier.txt avec comme contenu 'Ceci est une ligne de monfichier.txt'.

var
res   : resource;
ligne  : string;
begin
res := openResource('/monfichier.txt');
if (resourceAvailable(res)) then
begin
ligne := readLine(res);

closeResource(res);
end;

drawText(ligne, 0, 0);
repaint;

delay(5000);
end.

Gestion des touches

L'une des parties importantes, quand on programme des applications pour téléphones mobiles, est la gestion des touches du téléphone.

getKeyClicked

function getKeyClicked: integer;

Elle renvoie le code de la dernière touche appuyée.
Exemple

.....
begin
key:=getKeyClicked; {Récupérer la touche appuyée}
.....
if (key=KE_STAR  ) then {test si touche étoile}
begin
.....
end;
.....
end;

getKeyPressed

function GetKeyPressed: integer;

Elle retourne le code la touche pressée.

Voila la liste de constantes prédéfinies, valables aussi bien pour getKeyPressed que getKeyPressed :

- KE_KEY0

- KE_KEY1

- KE_KEY2

- KE_KEY3

- KE_KEY4

- KE_KEY5

- KE_KEY6

- KE_KEY7

- KE_KEY8

- KE_KEY9

- KE_STAR

- KE_POUND

keyToAction

Nous venons de voir comment renvoyer le code d'une touche, mais il peut arriver que les codes diffèrent suivant les téléphones. Ainsi le code d'une touche peut donner 20 sur un téléphone, cette même touche sur un autre téléphone peut également donner par exemple 30.
Pour régler ce problème il est donc conseillé d'utiliser keyToAction.

function KeyToAction(keyCode: integer): integer;

Exemple

key:=GetKeyClicked;
if( (KeyToAction(key)=GA_RIGHT ))  then bougerADroite;
else if( (KeyToAction(key)=GA_LEFT ))  then bougerAGauche;

Comme vu dans l'exemple, il existe une liste de constantes prédéfinies :

- GA_NONE

- GA_UP

- GA_DOWN

- GA_LEFT

- GA_RIGHT

- GA_FIRE

- GA_GAMEA

- GA_GAMEB

- GA_GAMEC

- GA_GAMED

Comment dessiner à l'écran ?

Fonctions de dessin

Nous savons déjà comment dessiner un texte à l'écran en utilisant drawText.
Pour rappel :

procedure drawText(text: string, xPos, yPos: integer);

Vous pouvez dessiner du texte à l'écran avec différentes polices.

procedure setFont(fontFace, fontStyle, fontSize);

Il est également possible de dessiner des formes :

- drawArc dessine un arc couvrant un rectangle, débutant de startAngle et allant à arcAngle

Exemple

procedure drawArc(x, y, width, height, startAngle, arcAngle: integer);
begin
drawArc(0, 0, 20, 20, 0, 90);
repaint;
Delay(1000);
end.

- drawEllipse dessine une ellipse sur l'écran.

procedure drawEllipse(x, y, width, height: integer);
begin
drawEllipse(0, 0, 20, 20);
repaint;
delay(1000);
end.

- fillEllipse dessine une ellipse remplie d'un fond uni, vous pouvez choisir la couleur de fond en utilisant setColor

procedure fillEllipse(x, y, width, height: integer);
begin
fillEllipse(0, 0, 20, 20);
repaint;
delay(1000);
end.

- drawLine dessine une ligne entre le point de coordonnées (x1, y1) et le point de coordonnées (x2, y2)

procedure drawLine(x1, y1, x2, y2: integer);

- drawRect dessine un rectangle

procedure drawRect(x, y, width, height: integer);

- fillRect dessine un rectangle plein, vous pouvez également choisir la couleur de fond avec setColor

procedure fillRect(x, y, width, height: integer);

- drawRoundRect dessine un rectangle avec des bords arrondis

procedure drawRoundRect(x, y, width, height, arcWidth, arcHeight: integer);

- fillRoundRect dessine un rectangle plein avec des bords arrondis

procedure fillRoundRect(x, y, width, height, arcWidth, arcHeight: integer);

Concernant l'utilisation de la procédure repaint : après chaque procédure (drawLine, drawText, etc) repaint effectue la copie sur l'écran de ce qui est dessiné dans le buffer par (drawText, drawLine, etc) sur l'écran.

Les couleurs

Une des questions qu'on aura tendance à se poser est : comment afficher un texte avec une certaine couleur?
Il existe différentes procédures ou fonctions pour manipuler et utiliser les couleurs avec MIDlet Pascal.

setColor qui permet de définir la couleur à utiliser pour dessiner sur l'écran. Le principe utilisé est la notation RGB (Red Green Blue)

procedure setColor(red, green, blue:integer);

Les couleurs peuvent prendre des valeurs comprises entre 0 et 255. Par exemple pour représenter la couleur noire, on fera setColor(0, 0, 0);.
Exemple

begin
setColor(0, 0, 255);
drawText('Hello world', 0, 0);
repaint;
delay(1000);
end.

Il peut arriver de se demander si le téléphone cible d'une application peut afficher les couleurs utilisées dans l'application. La fonction isColorDisplay permet de le savoir.

function isColorDisplay:boolean;

Elle retourne true si l'écran peut afficher les couleurs et false sinon.
Une fois que nous savons que nous pouvons afficher les couleurs, il est possible de connaître le nombre couleurs que peut afficher l'écran avec la fonction getColorsNum.

function getColorsNum:integer;

Exemple

begin
drawText (integerToString(getColorsNum), 0, 0);
{affiche 4096 sur l'émulateur}
repaint;
delay(1000);
end;

Les images

Pour charger une image utilisez le menu import ressource file ou créez-en avec new image ressource. Vous ne pouvez afficher une image sans l'avoir chargée au préalable; la fonction à utiliser à cet effet est loadImage.

function loadImage(resource: string): image

Cette fonction charge une image et renvoie un objet image.

Quand vous allez déployer une application sur un téléphone portable, quand vous exécutez un code avec un émulateur ce sont les fichiers jar et jad qui sont appelés; le chargement d'une image a donc lieu à partir du jar, veillez donc à précéder le nom de fichier image du caractère slash /.

Exemple

begin
drawImage(loadImage('/icon.png'), 0, 0);
repaint;
end.

Une fois l'image chargée comme vu dans l'exemple ci-dessus, affichez-la avec drawImage

procedure drawImage(img: image; x, y: integer);

Les propriétés que vous pouvez utiliser sur une image sont :

- getImageHeight qui retourne la hauteur d'une image

function getImageHeight(img: image): integer;

- getImageWidth qui retourne la largeur d'une image

function getImageWidth(img: image): integer;

Autres fonctions

- getWidth qui retourne la taille en largeur de l'écran.

function getWidth: integer;

- getHeight qui retourne la taille en hauteur de l'écran

function getHeight: integer;

Exemple

begin
drawRec(0, 0, getWidth, getHeight);
Repaint;
Delay(1000);
end.

- imageFromImage permet de créer une partie d'une autre image chargée.

function imageFromImage(sourceImg: image; x: integer; y: integer; width: integer;height: integer ): image ;

Exemple

begin
drawImage(imageFromImage ( loadImage('/icon.png'),0 ,0, 5, 5), 0, 0);
repaint;
delay(1000);
end.

Maintenant que nous savons gérer l'appui des touches, dessiner sur l'écran, nous pouvons faire un exemple simple de menu.

Const nbMenus=5;

var
choix   :array[1..nbMenus] of String;
choixPos:integer;
y       :integer;

procedure choixMenus;
var
x   :integer;
key :integer;

begin
key:=GetKeyClicked; {Récupérer la touche appuyée}

if (KeyToAction(key)=GA_RIGHT )  then {Si touche de direction droite appuyée}
begin
if ( (choixPos + 1) =6) then
choixPos:=0;{position de l'index sur le 0}
{Il s'agit de parcourir le tableau de chaînes représentant les menus}
choixPos:=choixPos + 1 ;  {Incrémenter l'index du tableau}
{On décide de dessiner le texte au milieu l'écran
getStringWidth permet d'avoir la largeur de la chaîne dessinée }
x:=(getWidth - getStringWidth(choix[choixPos]))/2;

setcolor(255,255,255);
DrawText(choix[choixPos],x,y);
{Faire semblant d'effacer l'ancien texte dessiné}
fillrect(0,y,getWidth,getStringHeight(choix[choixPos]));

setcolor(0,0,0);
DrawText(choix[choixPos],x,y);

repaint
end
{Les explications précédentes sont les mêmes sauf qu'ici les opérations
s'effectuent lors de l'appui sur la touche de direction gauche}
else if( (KeyToAction(key)=GA_LEFT ))  then
begin
if ( (choixPos - 1) =0) then
choixPos:=6;

choixPos:=choixPos - 1 ;
x:=(getWidth - getStringWidth(choix[choixPos]))/2;

setcolor(255,255,255);
DrawText(choix[choixPos],x,y);
fillrect(0,y,getWidth,getStringHeight(choix[choixPos]));

setcolor(0,0,0);
DrawText(choix[choixPos],x,y);
repaint

end

if (KeyToAction(key)=GA_FIRE ) then
begin
{ACTION}
end

end;

//procedure pour quitter
function quitter :boolean ;
begin
quitter:=((choixPos=5) and (KeyToAction(GetKeyPressed)=GA_FIRE ));
end;

begin
//Initialisations
choix[1]:='< Jouer >';
choix[2]:='< Options >';
choix[3]:='< Aide >';
choix[4]:='< A propos >';
choix[5]:='< Quitter >';
choixPos:=1;
y := getHeight / 2;{milieu de l'écran sur la longueur}

SetFont(FONT_FACE_SYSTEM, FONT_STYLE_BOLD , FONT_SIZE_LARGE);
drawText(choix[choixPos],(getWidth - getStringWidth(choix[choixPos]))/2,y);
repaint;

repeat
choixMenus;
until quitter;
end.

Comment créer une interface utilisateur ?

Les menus

Nous avons vu dans l'exemple de la partie précédente comment faire un menu de navigation en dessinant, et en gérant les appuis sur certaines touches. Notez qu'on peut s'en passer et faire un menu simple en utilisant menuAppendString ou menuAppendStringImage.
Exemple

var hanoi, puzzle, snake : integer;
jeu : command;

begin
showMenu('Selectionner le jeu', CH_IMPLICIT);

hanoi  := MenuAppendString('Hanoi');
puzzle := MenuAppendString('Puzzle');
{Il y a la possibilité de mettre une image dans la liste des menu}
snake  := MenuAppendStringImage('Snake', loadImage('/icon.png'));

jeu := CreateCommand('Jouer', CM_SCREEN, 1);
AddCommand(jeu);

repeat
delay(100);
until getClickedCommand = jeu;

end.

Vous pouvez également envoyer des messages d'alertes à l'utilisateur sous certaines conditions. Un cas d'utilisation serait : tant que l'utilisateur n'aura pas sélectionné le menu 'Hanoi' on lui enverra un message d'alerte en utilisant showAlert

Les formulaires

Les formulaires peuvent s'avérer nécessaires si vous voulez faire remplir des champs, par exemple, par un utilisateur de votre application. Il est évident que l'utilisation des fonctions de touches comme getKeyClicked ne vous aiderait pas, il faut donc quelque chose de plus approprié, un peu comme les boîtes de dialogue sur les plateformes PC.

Avant d'afficher les éléments du formulaire, il faut changer de mode en utilisant showForm.
Il existe principalement deux modes, un peu comme on dirait en Pascal standard, le mode graphique et le mode texte ou console. Ici quand on utilisera les éléments de formulaire il faudra ensuite utiliser showForm pour qu'ils soient visibles à l'écran.
Exemple

var label, textField: integer;
begin
label := formAddString('Bonjour');
textField := formAddTextField('pseudo', 'krachik', 20, TF_ANY);
showForm;
delay(2000);
end.

Si vous êtes dans ce mode, vous pouvez changer de mode si vous voulez dessiner par exemple un texte à l'écran en utilisant la procédure showCanvas.

var label, textField: integer;
begin
label := formAddString('Bonjour');
textField_id := FormAddTextField('pseudo', 'krachik', 20, TF_ANY);
showForm;
delay(2000);
showCanvas;
drawText('Hello world', 0, 0);
repaint;
delay(2000);
end.

Si vous faites un programme pour juste dessiner un texte par exemple, vous n'avez pas besoin d'utiliser showCanvas.

Envoi de messages

MIDlet Pascal permet à partir d'un téléphone d'envoyer un message vers un autre téléphone. Vous aurez besoin pour ce faire de :

- smsStartSend qui démarre l'envoi d'un message SMS (Short Message Service). Cette fonction retourne true si le message a été bien envoyé au système de gestion d'envoi de messages et qu'un autre message n'est pas en cours d'envoi. L'adresse de destination doit être sous la forme 'sms://<numro-de-telephone>'. Par exemple sms://+33606060606'

function smsStartSend(destination: string; message:string): boolean;

MIDlet Pascal permet l'envoi de messages SMS en utilisant WMA (Wireless Messaging API) de J2ME. Notez que ceci ne marche que sur les téléphones compatibles.

- smsIsSending qui retourne true si le système est en attente d'envoi de sms et false sinon

function smsIsSending: boolean;

- smsWasSuccessfull retourne true si l'envoi du dernier sms à réussi. Si la fonction retourne false cela voudra dire que :
1. soit le téléphone mobile ne supporte pas l'envoi de messages en utilisant les MIDlets
2. soit l'adresse de destination du message est invalide
3. soit l'opérateur téléphonique refuse de transmettre le message.

function smsWasSuccessfull: boolean;

Exemple

begin
// Démarre l'envoi du sms
if not smsStartSend('sms://+33606060606', 'Bonjour!') then
halt;

// On attend que le message soit envoyé
while smsIsSending do
delay(100);

// Tester si l'envoi à réussi
if not smsWasSuccessfull then
halt;
end.

L'envoi de messages à travers MIDlet Pascal n'exclut pas le fait d'avoir du crédit suffisant avant tout envoi de message SMS.

Connexion http

Vous pouvez vous connecter à internet avec votre téléphone mobile en utilisant une connexion WAP (Wireless Application Protocol). Vous pouvez donc envoyer et recevoir des données.

Il existe des fonctions pour manipuler le protocole HTTP. Pour pouvoir utiliser ces fonctions avec MIDlet Pascal, il faudrait que le téléphone cible de l'application supporte le protocole HTTP. Certains téléphones mobiles peuvent même supporter d'autres protocoles comme UDP mais MIDlet Pascal, pour le moment, ne permet pas de les gérer; il vous revient de faire votre propre unité pour les gérer.
Pour se connecter sur un site à travers MIDlet, il faut d'abord ouvrir la connexion vers le site en utilisant la fonction openHttp

function openHttp(httpConn: http; url: string):boolean;

L'url doit être de la forme 'http://www.monsite.com[:port][/fichier]'. La fonction retourne true si tout s'est bien passé et false sinon. Vous devez au préalable tester s'il n'existe pas une connexion déjà ouverte vers ce site avec isHttpOpen.

function isHttpOpen(httpConn: http):boolean;

Ensuite, pour lire les données de la page, il faut préciser le type de requête en utilisant setHttpMethod

procedure setHttpMethod(httpConn: http; method:string);

Il convient ensuite de préciser l'agent qui va lire les données, comme pour les navigateurs, quand nous nous connectons sur un site, il y a la possibilité de connaître l'agent utilisateur qui se connecte sur le site. Par exemple Mozilla/5.0.
Nous pouvons aussi préciser si nous voulons accepter l'encodage du site, la langue du site, le charset du site etc. Pour faire ceci utilisez la procédure addHttpHeader.

procedure addHttpHeader(httpConn: http; name, value:string);

Exemple

{préciser l'agent utilisateur}
addHttpHeader(connexion, 'User-agent', 'MIDletPascal');
{accepter l'encodage du site}
addHttpHeader(connexion, 'Accept-encoding', 'gzip,none');

Pour savoir si la connexion au site à réussi, il faut récupérer le code réponse du site en utilisant sendHttpMessage. Pour voir toute la liste des codes réponses renvoyés par les sites, il existe Status Code Definitions.

{le code 200 c'est si tout est OK}
if sendHttpMessage(connexion) <> 200 then halt;

A ce niveau, si tout est OK, il ne nous restera plus qu'à lire le contenu du site renvoyé par le serveur avec getHttpResponse.

{contenu html renvoyé}
contenuHtml := getHttpResponse(connexion);

N'oubliez pas de fermer la connexion une fois fini avec closeHttp.

Accès mémoire

Sur les téléphones mobiles qui supportent le MIDP 1, les données sont sauvegardées sur la mémoire flash par les MIDlets. Tous les téléphones mobiles n'ont pas de mémoires disques et donc certaines applications auront besoin de support de stockage. Ceci est possible à travers J2ME, qui permet l'accès à la mémoire flash des téléphones par ce que nous allons appelons recordstore.
Un RecordStore est une liste d'enregistrements formés de tableaux d'octets.

Chaque application MIDlet a son propre espace recordstore sur les téléphones mobiles, et chaque espace est isolé. Ce qui veut dire qu'une application ne peut accéder à l'espace réservé/créé par une autre application.

MIDP 2.0 permet le partage d'un même recordstore entre plusieurs applications MIDlets.

On utilisera donc la fonction openRecordStore pour ouvrir un recordstore

function openRecordStore(name: string): recordStore;

Si le recordstore n'existe pas, un nouvel espace sera créé à ce nom. Veillez à fermer le flux sur un recordstore ouvert avec closeRecordStore

procedure deleteRecordStore(name: string);

Toutes les données seront supprimées après l'utilisation de cette procédure; aucune action ne sera faite s'il n'existe pas de recordstore portant ce nom.

Les données stockées sont identifiées par des indices. Il est possible de connaître le nombre de données avec la fonction getRecordStoreSize. Vous pouvez ajouter une nouvelle entrée avec addRecordStoreEntry, que vous pourrez modifier par la suite si vous voulez en utilisant la procédure modifyRecordStoreEntry.

Librairies externes

Quand nous créons un projet sous MIDlet Pascal, nous pouvons créer des unités pouvant être utilisées par d'autres unités ou le programme principal. Nous serons d'accord qu'avec tout ce que nous avons vu jusqu'ici que MIDlet Pascal permet de faire pas mal de choses. Cependant MIDlet Pascal ne permet pas d'utiliser toutes les fonctions disponibles fournies par MIDP. Vous pouvez tout de même les utiliser si vous le souhaitez en créant des librairies externes en Java. Il donc clair que vous devez savoir programmer en J2ME pour pouvoir les faire.

Certains peuvent se demander alors : quelle est la réelle différence entre les unités habituelles crées sous MIDlet Pascal et les librairies externes ? Eh bien voilà :
- ces librairies externes sont écrites en JAVA
- elles doivent être placées dans le dossier {repertoire_install_MIDletPascal}\Libs
- elles ne peuvent contenir que des méthodes
- ces méthodes ne peuvent être appelées qu'avec des types comme :

- integer

- String

- image

- RecordStore

- Command

Nous allons illustrer ce que nous venons de dire. Mettons en place une librairie externe permettant d'additionner deux nombres entiers. Nous prenons un exemple basique dans le but de montrer le fonctionnement et la mise en place de ce qui précède.
Commençons par écrire notre code java.

public class Lib_uniteext {
public static int somme (int a, int b) {
return a + b ;
}
}

Il ne doit pas y avoir de package dans le code Java. Le nom de la classe doit être préfixé de Lib_ et toutes les autres lettres doivent être en minuscules.

Il faudrait maintenant compiler le code. Vous devez disposez de Java Wireless Toolkit.
Lancez ktoolbar.exe, créez un nouveau projet et donnez-lui un nom. Une fois le projet créé, vous trouverez dans votre profil un répertoire j2mewtk; le projet créé se trouve dans {profil\j2mewtk\{version}\apps\projet_cree}. Dans le dossier src, créez un fichier .java nommé Lib_uniteext, mettez-y le code Java ci-dessus et sauvegardez-le. Vous n'aurez qu'à cliquer sur Build pour compiler le source, ce qui permettra de créer le fichier class. Copiez le fichier .class dans le répertoire Libs se trouvant dans le répertoire d'installation de MIDlet Pascal.

{Appel à l'unité externe crée}
uses uniteext;
var aff : integer;
begin
showForm;
{l'appel se fait en mettant nom_unite.methode_static}
aff := formAddString('somme de 2 et 9 = ' +( uniteext.somme(2,9) ) );
delay(5000);
end.

L'écran affichera somme de 2 et 9 = 11

Le mode débogage

L'une des fonctionnalités qui manque, pour le moment, sous l'IDE MIDlet Pascal est une sortie pour le débogage comme celle montrant les erreurs de compilation. Nous savons combien le mode debug peut s'avérer important dans certaines circonstances.
Il y a quand même un moyen de suivre le déroulement de son application en paramétrant l'émulateur. Si vous avez le WKT de Sun installé, vous pouvez ajouter un nouvel émulateur sous MIDlet Pascal avec comme commande :
{lien vers emulateur} -Xdescriptor %JAD%.
Exemple

{moi j'ai installé le WKT à la racine C:\ et l'émulateur se trouve dans le dossier bin}
C:\WTK2.5.2_01\bin\emulator.exe -Xdescriptor %JAD%

Il existe cependant la procédure debug

procedure debug(s: string);

Cette procédure affiche sur la sortie standard le texte (tel quel) passé en paramètre.
Exemple

begin
drawText('MIDlet Pascal',0,0);
repaint;
debug('mode debug');
end.

Si vous avez paramétré l'émulateur comme indiqué ci-dessus, vous verrez apparaître une fenêtre console DOS si vous êtes sous Windows par exemple.

Notez l'affichage sur la dernière ligne 'mode debug', ce qui est marqué sur le code exemple du dessus.
Pour une utilisation avancée, voici la liste complète d'options :

emulator [arguments] <Application>

Arguments are:

-classpath, -cp    The class path for the VM
-D<property=value> Property definitions
-version           Display version information about the emulator
-help              Display list of valid arguments
-Xverbose[: allocation | gc | gcverbose | class | classverbose |
verifier | stackmaps | bytecodes | calls |
callsverbose | frames | stackchunks | exceptions |
events | threading | monitors | networking | all
enable verbose output
-Xquery
Query options
-Xdebug            Use a remote debugger
-Xrunjdwp:[transport=<transport>,address=<address>,server=<y/n>
suspend=<y/n>]
Debugging options
-Xdevice:<device name>
Name of the device to be emulated
-Xdescriptor:<JAD file name>
The JAD file to be executed
-Xjam[:install=<JAD file url> | force | list | storageNames |
run=[<storage name> | <storage number>] |
remove=[<storage name> | <storage number> | all] |
transient=<JAD file url>]
Java Application Manager and support
for Over The Air provisioning (OTA)
-Xautotest:<JAD file url>
Run in autotest mode
-Xheapsize:<size>  (e.g. 65536 or 128k or 1M)
specifies the VM heapsize
(overrides default value)
-Xprefs:<filename> Override preferences by properties in file
-Xnoagent          Supported for backwards compatibility
-Xdomain:<domain_name>
Set the MIDlet suite's security domain

Nouveautés de MIDlet Pascal 3

MIDlet Pascal est devenu open source et hébergé sur SourceForge depuis Octobre 2009. Son auteur originel est Niksa Orlic.

La version open source est reprise par d'autres développeurs. Il y a eu depuis Octobre 2009 plusieurs versions ALPHA, et ensuite des versions BETA. Le grand changement visible tout de suite concerne l'IDE. Voici les principaux changements qui se sont opérés depuis la sortie de la version open source jusqu' à la dernière version en date (la version beta 2).

- On note l'apparition de la notion de groupe, c'est à dire que vous pouvez classer maintenant vos projets par groupe. Il suffira donc de créer un groupe et d'y inclure un projet.

- La liste des derniers projets ouverts a été refaite sous un menu avec la possibilité d'effacer cette liste.

- La possibilité de renommer un fichier source ou les fichiers ressources.

- La possibilité de suivre les différences entre versions modifiées de code; il existe un onglet historique pour les voir. Vous pouvez donc choisir de retourner à une version précédente de votre code.

- Il est possible de mettre MIDlet Pascal sur un support amovible et l'utiliser où vous voulez; ceci marche aussi avec l'émulateur WINE.

- Depuis la BETA 2, des sources démos sont disponibles dans un répertoire Demos

- Vous pouvez utiliser la directive {$I} comme en Pascal standard pour inclure vos fichiers.

- Vous pouvez utiliser, comme il existe déjà, les directives de compilation conditionnelle, mais vous pouvez cette fois préciser d'exécuter du code suivant la plateforme

- Les codes sources .pas, .pp, .p et .inc peuvent s'ouvrir depuis l'IDE

Certains bugs ont été également corrigés.

Conclusion

Tout au long de ce tutoriel, nous avons appris les principales fonctions et procédures qu'offre MIDlet Pascal pour programmer. L'arrivée de la version 3 open source est une bonne chose parce qu'elle offre déjà de nouvelles fonctionnalités ou possibilités d'utilisation de MIDlet Pascal.
Aucune fonction ou procédure utilisée depuis MIDlet Pascal 2 n'a encore été dépréciée.

Liens :
Introduction au MIDlet Pascal 2.02
Programmer un jeu avec MIDlet Pascal

Je remercie darrylsite pour ses remarques ainsi que Alcatîz pour sa relecture et ses propositions.