70
Mobile Translation System in Crowdsourcing Stefano Zingarini Luca Figoli

Tiyla @Whymca '11

Embed Size (px)

DESCRIPTION

Tiyla is an infrastructure that enables management of software internationalization.- Multiplatform Libraries- Public Api- Support for multiple translation Crews- Support for Crowdsourcing- Community database of translations.. and more :]

Citation preview

Page 1: Tiyla @Whymca '11

Mobile Translation Systemin Crowdsourcing

Stefano ZingariniLuca Figoli

Page 2: Tiyla @Whymca '11

About Us

2

xiaprojects.com  &  @xiateam

Page 3: Tiyla @Whymca '11

Our Projects

3

Page 4: Tiyla @Whymca '11

About Us

4

Chi  siamoDal  1998  sviluppiamo  so/ware  per  ges4one  da4  su  interfaccia  Web  Nel  2004  realizzata  prima  versione  piaAaforma  RAD  e  BPM  -­‐Dal  2009  introdoAa  estensione  Mobile  Mul4piaAaforma  (                ,            ,                  ,  ,                                  )Reparto  R&D  con  20  dipenden4  tecnici  ([email protected])

Il  Prodo.o  e  le  SoluzioniAAraverso  gli  strumen4  RAD  e  BPM  offer4  dalla  nostra  piaAaforma  possiamo  realizzare  velocemente  applicazioni  Mobile  Mul4piaAaforma  in  grado  di  ges4re,  da4,  contenu4  e  processi

Chi  ha  scelto  al  nostra  tecnologia

Page 5: Tiyla @Whymca '11

About Us

5

ERP/Web

Enterprise/SaaS Apps

Page 6: Tiyla @Whymca '11

Intro: Roundup

6

La soluzione Tiyla: Goals & Examples

Internazionalizzazione del software oggi

Interazione Software / Utente

Page 7: Tiyla @Whymca '11

Software & i18n

7

Problematica non nuova ma attualissima

Internazionalizzazione

Localizzazione

“Progettazione per mercati diversi da quello di origine in cui si sviluppa”

“Le azioni volte a rendere il software fruibile per tali mercati”

Page 8: Tiyla @Whymca '11

Why i18n is a chance

8

Affinità culturali trasversali alle lingue

Raggiungere nuovi mercati / paesi non in crisi

11 persone su 12 nel mondo non conoscono l’Inglese

Psicologicamente rassicurantepagare per un’App da poter usare nella

propria lingua

Page 9: Tiyla @Whymca '11

Markets For All

9

Markets Mobile & Desktop

Multi-language and Multi Country Billing Support

Page 10: Tiyla @Whymca '11

With great opportunities... few problems

10

• Supporto nativo i18n diverso per ogni dispositivo•Gestione “script automatici” traduzioni attraverso un sw specifico: integrazione?•Distribuzione delle traduzioni in diversi formati (crossplatform)

Sviluppo

Page 11: Tiyla @Whymca '11

With great opportunities... few problems

11

• A chi rivolgersi per le traduzioni• Come gestire le collaborazioni• Come gestire la validazione della traduzione• Tenere sotto controllo il processo per più

lingue e più fornitori

Gestione

Page 12: Tiyla @Whymca '11

With great opportunities... few problems

12

• Ri-Pubblicazione dell’applicativo quando è disponibile una nuova lingua• Diversi store / versioni• Tempi di attesa• Possibilità di reject (per qualsiasi fantasioso

motivo)

Pubblicazione

Page 13: Tiyla @Whymca '11

Our Solution: Tiyla

13

Crossplatform

Process Control

Libraries

Api

Crowdsourcing

Collaboration

Page 14: Tiyla @Whymca '11

Tiyla Components

14

•Community•Applicazione•Crowdsourcing

Database

Api LibsGui Libs

Admin Manager

Crossplatform

API

AS

Page 15: Tiyla @Whymca '11

15

Tiyla Components Interaction

Page 16: Tiyla @Whymca '11

3 core of Tiyla solution

16

Trasparenza

Flessibilità

Crowdsourcing

Page 17: Tiyla @Whymca '11

Tiyla & Trasparenza

17

Esigenza di Traduzioni “Trasparenti”con Tiyla nel Backend

(es Software Enterprise)

• Supporto alla crew di traduzione aziendale o ai Partner in outsourcing tramite Tiyla

• Offerta traduzioni Tiyla Crew dai nostri partner• Disponibilità delle traduzioni di default “Community”• Generazione dei file per i18n multipiattaforma da

includere offline

Page 18: Tiyla @Whymca '11

Tiyla & Trasparenza

18

Le traduzioni sono generate all’atto della compilazione del progetto.

• Il sistema Tiyla è completamente nascosto all’utente finale

• L’azienda rimane proprietaria delle proprie traduzioni seguendone workflow & deploy

Plugin Ambiente di sviluppo

Tiyla Desktop

Page 19: Tiyla @Whymca '11

Tiyla & Trasparenza

19

Workflow “Standard”

• Registrazione  App• Abilitazione  Crew

Page 20: Tiyla @Whymca '11

20

Pannello di controllo Developer (OSx)

Page 21: Tiyla @Whymca '11

Tiyla & Trasparenza

21

Workflow “Standard”

• Registrazione  App• Abilitazione  Crew

• Traduzione• Da  Partner• Da  Community• Da  Tiyla  Crew

Page 22: Tiyla @Whymca '11

22

Pannello di controllo Traduzione (Win)

Page 23: Tiyla @Whymca '11

Tiyla & Trasparenza

23

Workflow “Standard”

• Registrazione  App• Abilitazione  Crew

• Traduzione• Da  Partner• Da  Community• Da  Tiyla  Crew

• File  i18n  generato  da  Plugin  in  IDE

• File  i18n  generato  da  Desktop  Client  da  includere  al  progeOo

• Build

SELL

Page 24: Tiyla @Whymca '11

Tiyla & Flessibilità

• Inclusione di un set base di lingue• Update remoto (via Api) di nuove lingue per l’app

quando queste vengono validate• Possibilità di contribuire / usufruire del db

Community delle traduzioni

24

Si abilita l’update dell’i18n App Remoto

Page 25: Tiyla @Whymca '11

Tiyla & Flessibilità

• Possibilità di pubblicare l’applicazione partendo da una lingua base (abbattere i tempi di debutto sul mercato)

• Arricchire l’app “on the fly” senza bisogno di ripubblicarla

• Correggere le traduzioni al volo

25

Vantaggi: Tempo = Denaro

Page 26: Tiyla @Whymca '11

Tiyla & Flessibilità

26

Workflow Tiyla On The FLy

• Registrazione  App• Abilitazione  Crew

• Traduzione• Da  Partner• Da  Commuinity• Da  Tiyla  Crew

• File  i18n  generato  da  Plugin  in  IDE

• File  i18n  generato  da  Desktop  Client  da  includere  al  progeOo

• Build

SELL• Correzioni• Nuove  Lingue

Page 27: Tiyla @Whymca '11

Tiyla & Crowdsourcing

27

Perchè fa Fico?

Page 28: Tiyla @Whymca '11

Tiyla & Crowdsourcing

28

Innumerevoli casi di successo...

...anche nell’ambito delle traduzioni sw

Page 29: Tiyla @Whymca '11

Tiyla & Crowdsourcing

29

Page 30: Tiyla @Whymca '11

Tiyla & Crowdsourcing

30

Infrastruttura:

• Gestione di base Utenti • Traduzione degli utenti a partire da una lingua

certificata• Rating delle traduzioni• Conteggio attività dell’utente in Crowd Tiyla

– Rating degli utenti (individuare best & worst)– Possibilità di indire contest

VALUE

VALUE

VALUE

Page 31: Tiyla @Whymca '11

31

Into the Code

&

Page 32: Tiyla @Whymca '11

Tiyla & iOS (1/5)

32

Page 33: Tiyla @Whymca '11

Tiyla & iOS (2/5)

33

Page 34: Tiyla @Whymca '11

Tiyla & iOS (3/5)

34

Page 35: Tiyla @Whymca '11

Tiyla & iOS (4/5)

35

Page 36: Tiyla @Whymca '11

Tiyla & iOS (5/5)

36

Page 37: Tiyla @Whymca '11

iOS + MacOS: Supporto Nativo

37

• Prevede un file “Localizzato” aggiunto al bundle del progetto

• Automatico in base alla lingua impostata nel dispositivo

• API da utilizzare• Traduce anche i contenuti XIB Disegnati usando il

Designer

Page 38: Tiyla @Whymca '11

iOS + MacOS: Supporto Nativo

38

Page 39: Tiyla @Whymca '11

iOS + MacOS: Supporto Nativo

39

Aggiungo la lingua a Localizable.strings

Completo le traduzioni

Page 40: Tiyla @Whymca '11

iOS + MacOS: Supporto Nativo

40

NSLocalizedString(@”Hello World”,@”Label Description”);

Page 41: Tiyla @Whymca '11

iOS + MacOS: Supporto Nativo

41

• Richiede la ricompilazione: File (*) da mettere nel bundle

• Aggiungere un file per ogni nuova lingua da tradurre• Modificare tutti i file se cambia la lingua del

“programmatore”

Page 42: Tiyla @Whymca '11

Tiyla & iOS: .h

42

//! Profile management//! create new profile, or if exist and password match return TRUE-(BOOL)registerProfile:(NSString *)email password:(NSString *)password;//! verify your password-(BOOL)loginProfile:(NSString *)email password:(NSString *)password;//! remove profile-(BOOL)dropProfile:(NSString *)email password:(NSString *)password;//! return data for profile, if password is empty you will receive public informations-(NSDictionary *)getProfile:(NSString *)email password:(NSString *)password;//! Developer API://! create new Application, if application exists does do nothing-(NSString *)registerApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password;//! set KeyPairs App info to db-(BOOL)setApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password data:(NSDictionary *)data;//! Crew manage-(BOOL)linkCrew:(NSString *)emailCrew toApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password;-(BOOL)unlinkCrew:(NSString *)emailCrew toApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password;//! Translations Update Crew-(BOOL)setTApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:(NSString *)language data:(NSDictionary *)data;//! Translations Update Developer-(BOOL)setTRankApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:(NSString *)language data:(NSDictionary *)data;//! Translations Client-(NSDictionary *)getApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password data:(NSDictionary *)data;//! get Translation * work with shots *-(NSDictionary *)getTApp:(NSString *)bundleId email:(NSString *)email password:(NSString *)password language:(NSString *)language data:(NSDictionary *)data;

Page 43: Tiyla @Whymca '11

Tiyla & iOS: RAPI

43

+(NSMutableDictionary *)rapi:(NSURL *)url data:(NSDictionary *)data{ //! Data Variables NSString *jsonStringEncodedData=nil;! NSData *dataFromJson=nil;! NSData *dataCompressedFromJson=nil; NSMutableURLRequest *urlRequest =nil; NSData *replyFromServer=nil; NSString *replyFromServerString=nil; NSMutableDictionary *returnResponse=nil; //! JSON Engine SBJsonWriter *jsonWriter=[[SBJsonWriter alloc] init]; SBJsonParser *jsonParser=[[SBJsonParser alloc] init]; //! Some casts jsonStringEncodedData=[jsonWriter stringWithObject:data];! dataFromJson=[jsonStringEncodedData dataUsingEncoding:NSUTF8StringEncoding]; dataCompressedFromJson=[self gzipData:dataFromJson];!! //! Prepare Remote API! urlRequest =[NSMutableURLRequest requestWithURL:url];! [urlRequest setHTTPMethod:@"POST"]; [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];! [urlRequest setHTTPBody:dataCompressedFromJson];! //! Reply RAPI! replyFromServer=[NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:nil];! replyFromServerString=[[NSString alloc] initWithData:replyFromServer encoding:NSASCIIStringEncoding];

//! JSON Return returnResponse=[jsonParser objectWithString:replyFromServerString]; return returnResponse;!}

Page 44: Tiyla @Whymca '11

Tiyla & iOS: GZIP

44

/** * GZip Compression helper for NSData */+(NSData *)gzipData:(NSData *)pUncompressedData { z_stream zlibStreamStruct; // ... int initError = deflateInit2(&zlibStreamStruct, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY); // ... NSMutableData *compressedData = [NSMutableData dataWithLength:[pUncompressedData length] * 1.01 + 12]; // ... do { // ... deflateStatus = deflate(&zlibStreamStruct, Z_FINISH); // ...! ! } while ( deflateStatus == Z_OK ); // ... deflateEnd(&zlibStreamStruct); // ... [compressedData setLength: zlibStreamStruct.total_out]; // ... return compressedData; }

Page 45: Tiyla @Whymca '11

Tiyla: Server IO GZIP

45

<?php//  Imposto  il  Xpo  di  ritornoheader  ("content-­‐type:  applicaXon/json");//  Imposto  il  fuso  orario  (il  server  è  in  USA)date_default_Xmezone_set('UTC');//  DEBUG:  Memorizzo  l'ora  di  partenza  per  calcolare  il  "peso"  in  fondo$start_Xme=microXme(TRUE);//  ATTENZIONE:  lo  stream  in  ingresso  POST  deve  essere  compresso$fp=gzopen("php://input","r");//  POST:  leggo  in  input  tuOo  il  JSON  inviato  dai  client$data  =  gzread($fp,1024000);  //  1MB  in  upload  (decompresso...)//  chiudo  il  descriOorefclose($fp);$fp=0;//  genero  un  array  associaXvo  dal  POST$data=json_decode($data,true);

?>

Page 46: Tiyla @Whymca '11

Tiyla & iOS: Libreria (1/5)

46

Page 47: Tiyla @Whymca '11

Tiyla & iOS: Libreria (2/5)

47

Page 48: Tiyla @Whymca '11

Tiyla & iOS: Libreria (3/5)

48

Page 49: Tiyla @Whymca '11

Tiyla & iOS: Libreria (4/5)

49

Page 50: Tiyla @Whymca '11

Tiyla & iOS: Libreria (5/5)

50

Page 51: Tiyla @Whymca '11

Tiyla & MacOS: Desktop Client

51

Page 52: Tiyla @Whymca '11

Tiyla & MacOS: Desktop Client

52

Page 53: Tiyla @Whymca '11

53

Into the Code

&

Page 54: Tiyla @Whymca '11

Android: Supporto Nativo

54

• Sistema di localizzazione integrato basato su file xml, presenti in diverse folder con suffisso differente a seconda della lingua (values, values-it, values-fr)

• Il file chiamato strings.xml è semplicemente un elenco di righe chiave – valore dove il valore è appunto la stringa tradotta.

• Da codice per recuperare la stringa corrente getString(R.string.key)

• Se si vuole modificare o aggiungere una nuova lingua bisogna ricompilare il programma producendo il nuovo apk e pubblicare l’aggiornamento sul market

Page 55: Tiyla @Whymca '11

Tiyla & Android: Presentazione

55

Page 56: Tiyla @Whymca '11

Tiyla & Android: API

56

//!  Profile  management//!  create  new  profile,  or  if  exist  and  password  match  return  TRUEsta7c  public  boolean  registerProfile(String  email,  String  password)//!  verify  your  passwordsta7c  public  boolean  loginProfile(String  email,  String  password)//!  remove  profilesta7c  public  boolean  dropProfile(String  email,  String  password)//!  return  data  for  profile,  if  password  is  empty  you  will  receive  public  informaXonssta7c  public  JSONObject  getProfile(String  email,  String  password)//!  Developer  API://!  create  new  ApplicaXon,  if  applicaXon  exists  does  do  nothingsta7c  public  String  registerApp(String  bundleId,  String  email,  String  password)//!  set  KeyPairs  App  info  to  dbsta7c  public  boolean  setApp(String  bundleId,  String  email,  String  password,  JSONObject  data)//!  Crew  managesta7c  public  boolean  linkCrew(String  emailCrew,  String  bundleId,  String  email,  String  password)sta7c  public  boolean  unlinkCrew(String  emailCrew,  String  bundleId,  String  email,  String  password)//!  TranslaXons  Update  Crewsta7c  public  boolean  setTApp(String  bundleId,  String  email,  String  password,  String  language,  JSONObject  data)//!  TranslaXons  Update  Developersta7c  public  boolean  setTRankApp(String  bundleId,  String  email,  String  password,  String  language,  JSONObject  data)//!  TranslaXons  Clientsta7c  public  JSONObject  getApp(String  bundleId,  String  email,  String  password,  JSONObject  data)//!  get  TranslaXon  *  work  with  shots  *sta7c  public  JSONObject  getTApp(String  bundleId,  String  email,  String  password,  String  language,  JSONObject  data);

Page 57: Tiyla @Whymca '11

Tiyla & Android: RAPI

57

//Inizialmente  comprimo  i  daX  in  formato  gzip  uXlizzando  //l'oggeOo  GZIPOutputStreambyte[]  compressedData  =  Library.compressData(dataS.getBytes());

//-­‐-­‐-­‐//Apro  una  HOpURLConnecXon  verso  il  serverconnecXon  =  (HOpURLConnecXon)  new  URL(url).openConnec8on();//-­‐-­‐//Imposto  il  parametro  "Accept-­‐Encoding"  "deflate"  per  ricevere  i  daX  in  formato  compresso  connecXon.addRequestProperty("Accept-­‐Encoding",  "deflate");connecXon.setRequestProperty("Content-­‐Type","applicaXon/json");

//Invio  i  daXconnecXon.getOutputStream().write(compressedData);

//Ricevo  i  daX  dal  serverInputStream  input  =  connecXon.getInputStream();String  contentEncoding  =  connecXon.getContentEncoding();  BufferedInputStream  inputB  =  new  BufferedInputStream(input,  10000);

//-­‐-­‐-­‐while  ((nRead  =  inputB.read(data,  0,  data.length))  !=  -­‐1)  {byteAOSB.write(data,  0,  nRead);}

//-­‐-­‐        //ScompaOo  i  daX  dal  serverreceived_result  =  new  String(Library.decompressData(received_result.getBytes()));//-­‐-­‐        

Page 58: Tiyla @Whymca '11

Tiyla & BlackBerry

58

•Java•Eclipse Sdk

Page 59: Tiyla @Whymca '11

Tiyla & Nokia

59

QT

Page 60: Tiyla @Whymca '11

60

Into the Code

&

Page 61: Tiyla @Whymca '11

Windows & WP7: Supporto Nativo

61

• Sistema di localizzazione integrato basato su file di risorse (resx), con nomi organizzati gerarchicamente a partire dal file della lingua di default. Ad esempio myRes.resx contiene le informazioni in lingua di default, mentre una eventuale traduzione in francese standard si ottiene aggiungendo il file myRes.fr.resx al progetto

• Un file di risorse è composto da una serie di coppie chiave-valore. Tutti i file dovrebbero avere le stesse chiavi a cui corrispondono le versioni in lingua degli stessi testi

• Le interfacce utente invocano le stringhe contenute nei file di risorse tramite la loro chiave, usando l’operatore binding

• Se si vuole modificare o aggiungere una nuova lingua bisogna ricompilare il programma producendo il nuovo xap e pubblicare l’aggiornamento sul market

Page 62: Tiyla @Whymca '11

Tiyla & WP7: Presentazione

62

Page 63: Tiyla @Whymca '11

Windows & WP7: Supporto Nativo

63

• Le chiamate al server in WP7 sono gestite in modo asincrono.

• La libreria mette a disposizione una serie di eventi che vengono generati quando la chiamata è stata completata.

Page 64: Tiyla @Whymca '11

Tiyla & WP7: Metodi (1/3)

64

               public  delegate  void  OperationCompletedDelegate  (String  result,  Exception  error);                public  event  OperationCompletedDelegate  OperationCompleted;                ///  <summary>                ///  Profile  management                ///  create  new  profile,  or  if  exist  and  password  match  return  TRUE                ///  </summary>                              public  void  registerProfile(String  email,  String  password);                public  OperationCompletedDelegate  registerProfile_Completed;

               ///  <summary>                ///  verify  your  password                ///  </summary>                public  void  loginProfile(String  email,  String  password);                public  OperationCompletedDelegate  loginProfile_Completed;

               ///  <summary>                ///  remove  profile                ///  </summary>                public  void  dropProfile(String  email,  String  password);                public  OperationCompletedDelegate  dropProfile_Completed;

               ///  <summary>                ///  return  data  for  profile,  if  password  is  empty  you  will  receive    informations                ///  </summary>                public  void  getProfileString(String  email,  String  password);                public  OperationCompletedDelegate  getProfileString_Completed;

               ///  <summary>                ///  create  new  Application,  if  application  exists  does  do  nothing                ///  </summary>                public  void  registerApp(String  bundleId,  String  email,  String  password);                public  OperationCompletedDelegate  registerApp_Completed;

               

Page 65: Tiyla @Whymca '11

Tiyla & WP7: Metodi (2/3)

65

               ///  <summary>                ///  set  KeyPairs  App  info  to  db                ///  </summary>                public  void  setApp(String  bundleId,  String  email,  String  password,  Dictionary<string,  string>  data);                public  OperationCompletedDelegate  setApp_Completed;

               ///  <summary>                ///  Crew  manage                ///  </summary>                public  void  linkCrew(String  emailCrew,  String  bundleId,  String  email,  String  password);                public  OperationCompletedDelegate  linkCrew_Completed;                                ///  <summary>                ///  Crew  manage                ///  </summary>                                public  void  unlinkCrew(String  emailCrew,  String  bundleId,  String  email,  String  password);                public  OperationCompletedDelegate  unlinkCrew_Completed;

               ///  <summary>                ///  Translations  Update  Crew                ///  </summary>                              public  void  setTApp(String  bundleId,  String  email,  String  password,  String  language,  Dictionary<string,  string>  data);                public  OperationCompletedDelegate  setTApp_Completed;

               ///  <summary>                ///  Translations  Update  Developer                ///  </summary>                              public  bool  setTRankApp(String  bundleId,  String  email,  String  password,  String  language,  Dictionary<string,  string>  data);                public  OperationCompletedDelegate  setTRankApp_Completed;

               ///  <summary>                ///  Translations  Client                ///  </summary>                              public  void  getApp(String  bundleId,  String  email,  String  password,  Dictionary<string,  string>  data);                public  OperationCompletedDelegate  getApp_Completed;

               

Page 66: Tiyla @Whymca '11

Tiyla & WP7: Metodi (3/3)

66

///  <summary>///  get  Translation  *  work  with  shots  *///  </summary>              public  void  getTApp(String  bundleId,  String  email,  String  password,  String  language,  Dictionary<string,  string>  data);public  OperationCompletedDelegate  getTApp_Completed;

               ///  <summary>                ///  get  Translation  *  work  with  shots  *                ///  </summary>                              public  void  getTApp(String  bundleId,  String  email,  String  password,  String  language,  Dictionary<string,  string>  data);                public  OperationCompletedDelegate  getTApp_Completed;

Page 67: Tiyla @Whymca '11

Tiyla & WP7: RAPI (1/3)

67

• Per implementare alcune funzionalità sono state usate librerie open source pubblicate da CODEPLEX:

• JSON.NET - http://json.codeplex.com/releases/view/64935

• Silverlight SharpZipLib - http://slsharpziplib.codeplex.com/releases/view/50561

Page 68: Tiyla @Whymca '11

Tiyla & WP7: RAPI (2/3)

68

               private  void  registerProfile(String  email,  String  password,  string  method  =  "GET")                {                                                var  sender  =  new  TyilaUtils();                        sender.MyDownLoadCompletedEvent  +=  onDownloadCompleted;                        switch  (method)                        {                                case  "POST":                                        string  postData  =  JsonConvert.SerializeObject(new  command3pars()  {  func  =  "registerProfile",  email  =  email,         password  =  password  });                                        sender.executeCommandWithPost("http://tiyla.xiaprojects.com/core/echo.php",  postData);                                        break;                                case  "GET":                                default:                                        var  theUrlAndGetData  =  String.Format("func={0}&email={1}&password={2}",  "registerProfile",           HttpUtility.UrlEncode(email),  HttpUtility.UrlEncode(password));                                        theUrlAndGetData  =  "http://tiyla.xiaprojects.com/core/echo.php?"  +  theUrlAndGetData;                                        sender.executeCommandWithGet(theUrlAndGetData);                                        break;                        }                }                            private  void  onDownloadCompleted(TyilaUtils  sender,  String  content,  Exception  ex)                {                        sender.MyDownLoadCompletedEvent  -­‐=  onDownloadCompleted;                        if  (ex  !=  null)                        {                                MessageBox.Show(ex.Message);                        }                        else                        {                                MessageBox.Show(content);                        }                }

Page 69: Tiyla @Whymca '11

Tiyla & WP7: RAPI (3/3)

69

               public  void  executeCommandWithGet(String  theUrl)                {                        var  client  =  new  WebClient();                        client.DownloadStringCompleted  +=  new                         DownloadStringCompletedEventHandler(client_DownloadStringCompleted);                        client.DownloadStringAsync(new  Uri(theUrl));                }

               private  void  client_DownloadStringCompleted(object  sender,           DownloadStringCompletedEventArgs  e)                {                        if  (MyDownLoadCompletedEvent  !=  null)                                MyDownLoadCompletedEvent(this,  e.Result,  e.Error);                }

Page 70: Tiyla @Whymca '11

Contact us

70

xiaprojects.com  &  @xiateam

Xyla.com  &  @Xylatweets