Il presente articolo è stato tradotto automaticamente.

Microsoft Azure

Dati con connessione occasionale nelle app mobili multipiattaforma

Kevin Alice

Scaricare il codice di esempio

Appsneed più mobile per rimanere in modalità offline per alcuni periodi di tempo e gli utenti mobili prevede che le applicazioni a lavorare normalmente in stati connessi e disconnessi. Centinaia di milioni di utenti di dispositivi mobili potrebbe non essere consapevoli della necessità che le applicazioni dispongono per quanto riguarda gli stati in linea e non in linea; si aspettano semplicemente apps per lavorare in qualsiasi circostanza. In questo articolo verrà illustrato modi per attivare l'applicazione mobile lavorare in entrambi gli Stati e sincronizzare i dati correttamente con il cloud in Windows, iOS e Android utilizzando utensili Xamarin piattaforme e servizi mobili di Microsoft Azure.

Lo sviluppatore di applicazioni mobili, ha rilevato la necessità di sincronizzare i dati non in linea all'inizio. Per il mio sport invernali sci app (winter sports.co) e attività di Fitness Attiva rilevamento app (activefitness.co), è previsto un po' le pendenze o l'esecuzione non è possibile ottenere una buona connessione. Pertanto tali applicazioni devono essere in grado di sincronizzare i dati raccolti in modalità offline, senza alcun impatto significativo sulla durata della batteria e affidabilità. In altre parole, è necessario che le applicazioni funzionano in modo efficiente in tutte le condizioni.

È più che soddisfa l'occhio quando si considera un archivio permanente. Per iniziare, esistono diversi approcci disponibili per la sincronizzazione, ovvero può essere eseguita all'interno di un'applicazione o come processo in background nel sistema operativo. Inoltre, esistono diversi tipi di archivi di dati, ad esempio semistructured dati dai sensori e potenzialmente relazionale dati archiviati in SQLite. È inoltre importante implementare un criterio di risoluzione dei conflitti in modo degradazione e perdita di dati sono ridotte a icona. Infine, sono disponibili una vasta gamma di formati di dati da gestire, ad esempio binario, JSON, XML e personalizzati.

Applicazioni per dispositivi mobili sono in genere memorizzano diversi tipi di dati. I dati strutturati, ad esempio JSON o XML, in genere viene utilizzati per le impostazioni locali, i file locali o la memorizzazione nella cache. Oltre a memorizzare i dati nel file, anche possibile scegliere di motori di archiviazione, ad esempio SQLite per memorizzare ed eseguire query di dati. Applicazioni per dispositivi mobili possono inoltre memorizzare BLOB, file multimediali e altri tipi di dati binari di grandi dimensioni. Per questi tipi di dati, illustrerò le tecniche che consentono di rendere più affidabile il trasferimento di dati sui dispositivi connessi occasionalmente. Si prenda una panoramica delle diverse tecnologie. Ad esempio, anziché concentrarsi esclusivamente sulla sincronizzazione offline per dati strutturati, mostrerò un quadro più ampio di entrambi strutturati e tecniche di sincronizzazione dei dati non strutturati (blob). Si utilizzerà inoltre un approccio multipiattaforma ovunque all'interno di questi esempi.

L'approccio multipiattaforma

Poiché sta diventando sempre più diffusa per la connessione sensore -­dispositivi abilitati al cloud, ho incluso dati dei sensori dispositivo nel progetto per illustrare i vari metodi per eseguire la sincronizzazione con il cloud. Tratterò tre scenari: sincronizzazione di dati non in linea, sincronizzazione manuale dei dati e sincronizzazione dei dati binari e multimediali di grandi dimensioni. Nell'esempio di codice che li accompagnano è completamente multipiattaforma, con possibilità di riutilizzare il 100 percento per finestre, iOS e Android. Per ottenere che, ho utilizzato Xamarin.Forms, XAML multipiattaforma / C# tooling che funziona bene in iOS, Android e Windows e recupero integrato con strumenti di Visual Studio (vedere il video di Channel 9 di Microsoft, "piattaforme mobili Development Using Visual Studio," all'indirizzo bit.ly/1xyctO2).

Nell'esempio di codice sono due classi che consentono di gestire i modelli di dati di piattaforme: SensorDataItem e SensorModel. Questo approccio può essere utilizzato da molti programmi sportivi e fitness rilevamento delle applicazioni, ad esempio Active idoneità o le applicazioni che è necessario sincronizzare i dati strutturati dall'archivio locale con il cloud. Ho aggiunto latitudine, longitudine, velocità e distanza per la classe SensorDataItem come esempio di dati raccolti dai sensori, ad esempio GPS, per illustrare il concetto. Naturalmente, la struttura di dati nell'applicazione di effettivo potrebbe essere più complicata e includere le dipendenze, ma il mio esempio dare un'idea del concetto.

Sincronizzazione dei dati strutturati con sincronizzazione Offline

La sincronizzazione non in linea è una potente nuova funzionalità di servizi mobili di Azure. È possibile fare riferimento il pacchetto di servizi mobili di Azure nel progetto Visual Studio mediante NuGet. Più importante, è supportato anche in applicazioni multipiattaforma con la nuova versione di Azure Mobile Services SDK. Ciò significa che è possibile utilizzare questa funzionalità nel Windows, iOS e Android applicazioni che in alcuni casi è necessario connettersi al cloud e sincronizzare i loro Stati.

Inizierò con alcuni concetti.

Sincronizzare la tabella si tratta di un nuovo oggetto in Azure Mobile Services SDK creato per distinguere le tabelle che supportano la sincronizzazione delle tabelle "locale". Sincronizzazione tabelle implementano la IMobileServiceSyncTable < T > interfaccia e includono metodi aggiuntivi "sincronizzazione", ad esempio PullAsync, PushAsync e di pulizia. Se si desidera sincronizzare i dati del sensore non in linea con il cloud, è necessario utilizzare tabelle di sincronizzazione anziché le tabelle standard. Nel mio esempio di codice, inizializzo la tabella di sincronizzazione dati sensore utilizzando il GetSyncTable < T > chiamare il metodo. Nel portale Servizi mobili di Azure, è stato creato una normale tabella denominata SensorDataItem ed aggiungere il codice in Figura 1 per l'inizializzazione del client (è possibile scaricare il codice sorgente completo di bit.ly/11yZyhN).

Il contesto di sincronizzazione questo è responsabile della sincronizzazione dei dati tra gli archivi locali e remoti. Servizi mobili Azure viene fornito con SQLiteStore, che si basa sulla libreria SQLite più diffusa. Il codice in Figura 1 esegue alcune operazioni. Viene verificato se un contesto di sincronizzazione è già stato inizializzato e, se non crea una nuova istanza dell'archivio SQLite dal file local.db definisce la tabella in base alla classe SensorDataItem e inizializza l'archivio. Per gestire le operazioni in sospeso, il contesto di sincronizzazione utilizza una coda, accessibile tramite la proprietà PendingOperations. Il contesto di sincronizzazione fornito dai servizi Mobile Azure è anche "abbastanza" per distinguere le operazioni di aggiornamento in corso nell'archivio locale. Sincronizzazione viene eseguita automaticamente dal sistema, quindi non è necessario chiamare manualmente e inutilmente cloud per rendere persistenti i dati. Si tratta di una buona perché riduce il traffico e aumenta la durata della batteria di dispositivo.

Figura 1 sfruttando l'oggetto MobileServiceSQLiteStore per la sincronizzazione

// Initialize the client with your app URL and key
client = new MobileServiceClient(applicationURL, applicationKey);
// Create sync table instance
todoTable = client.GetSyncTable<SensorDataItem>();
// Later in code
public async Task InitStoreAsync()
{
  if (!client.SyncContext.IsInitialized)
  {
    var store = new MobileServiceSQLiteStore(syncStorePath);
    store.DefineTable<SensorDataItem>();
    await client.SyncContext.InitializeAsync(store,
      new MobileServiceSyncHandler   ());
  }
}

L'operazione Push consente di sincronizzare i dati tra l'archivio locale e l'archivio di cloud in modo esplicito spingendo dati locali al server. È importante sottolineare che nella versione corrente di Azure Mobile Services SDK, è necessario richiamare in modo esplicito push e pull per sincronizzare il contesto. L'operazione push esegue nel contesto di sincronizzazione intero consentono di mantenere relazioni tra tabelle. Ad esempio, se si dispone di relazioni tra tabelle, mio primo inserimento forniscano un Id dell'oggetto e inserimenti successivi è in grado di mantenere l'integrità referenziale:

 

await client.SyncContext.PushAsync();

L'operazione di Pull consente di sincronizzare i dati in modo esplicito dall'estrazione dei dati da un archivio remoto nell'archivio locale. È possibile utilizzare LINQ per specificare un sottoinsieme di dati o qualsiasi query OData. A differenza delle operazioni di push, eseguita su un intero contesto, viene eseguito pull sul livello di tabella. Se gli elementi sono in sospeso nella coda di sincronizzazione, gli elementi vengono inseriti prima, ovvero pull prima di eseguire le operazioni, per evitare la perdita di dati (ancora un altro vantaggio dell'utilizzo di servizi mobili di Azure per la sincronizzazione dei dati). In questo esempio, recuperare dati con velocità diverso da zero (raccolte dal mio Sensore GPS, ad esempio), precedentemente memorizzate sul server:

var query = sensorDataTable.Where(s => s.speed > 0);
await sensorDataTable.PullAsync(query);

L'operazione di pulizia specificati dalle tabelle locali e remoti, causando la sincronizzazione dei dati verranno cancellati. Simile a pull, è possibile utilizzare LINQ per specificare un sottoinsieme di dati o qualsiasi query OData. In questo esempio, eliminano dei dati con distanza nulla (che potrebbe anche venire dal mio Sensore GPS) dal mio tabelle:

var query = sensorDataTable.Where(s => s.distance == 0);
await sensorDataTable.PurgeAsync(query);

Gestisce i conflitti in modo appropriato si tratta di una parte importante della strategia di sincronizzazione di dati quando i dispositivi sono disponibili online e offline. Conflitti accadrà e Azure Mobile Services SDK fornisce modi per gestire i conflitti. Per la risoluzione dei conflitti per l'utilizzo, è stata attivata la colonna di proprietà di versione dell'oggetto SensorDataItem. Inoltre, ho creato la classe ConflictHandler, che implementa l'interfaccia IMobileServiceSyncHandler. Quando è necessario risolvere un conflitto, sono disponibili tre opzioni: mantenere il valore di client, mantenere il valore di server o interrompere l'operazione push.

Nel mio esempio, verificare la classe ConflictHandler. Quando viene inizializzato nel costruttore è impostata con uno dei tre criteri di risoluzione dei conflitti:

public enum ConflictResolutionPolicy
{
  KeepLocal,
  KeepRemote,
  Abort
}

A seconda del metodo ogni volta che si verifica un conflitto, nel metodo ExecuteTableOperationAsync automaticamente applicare il criterio di risoluzione dei conflitti. Quando Inizializza il contesto di sincronizzazione, la classe ConflictHandler passa al contesto di sincronizzazione con il criterio di risoluzione dei conflitti predefinito:

await client.SyncContext.InitializeAsync(
  store,
  new ConflictHandler(client, ConflictResolutionPolicy.KeepLocal)
);

Per ulteriori sulla risoluzione dei conflitti, vedere l'esempio MSDN, "Azure Mobile Services – Gestione conflitti con modalità non in linea WP8," al bit.ly/14FmZan e l'articolo della documentazione Azure "la gestione è in conflitto con sincronizzazione dati Offline in servizi di telefonia Mobile," in bit.ly/1zA01eo.

Sincronizzare i dati serializzati manualmente

Prima di servizi mobili di Azure offre la sincronizzazione non in linea, gli sviluppatori dovevano implementare manualmente la sincronizzazione di dati. Pertanto, se si sviluppa un'applicazione che in alcuni casi è necessario sincronizzare i dati e non si utilizza la funzionalità di sincronizzazione non in linea di servizi mobili di Azure, è possibile farlo manualmente (anche se è consigliabile esaminare la funzionalità di sincronizzazione non in linea). È possibile utilizzare una serializzazione diretto all'oggetto (ad esempio un serializzatore JSON) in file o dati di archiviazione dei motori ad esempio SQLite. La differenza principale tra il meccanismo di sincronizzazione non in linea e la sincronizzazione manuale è che è necessario eseguire la maggior parte del lavoro in quest'ultimo. Uno dei metodi per rilevare se i dati sono stati sincronizzati consiste nell'utilizzare la proprietà Id di qualsiasi oggetto nel modello dati. Ad esempio, vedere la classe SensorDataItem utilizzata nell'esempio precedente, notare i campi Id e versione, illustrato nella Figura 2.

Figura 2 struttura dei dati per la sincronizzazione dei dati

public class SensorDataItem
{
  public string Id { get; set; }
  [Version]
  public string Version { get; set; }
  [JsonProperty]
  public string text { get; set; }
  [JsonProperty]
  public double latitude { get; set; }
  [JsonProperty]
  public double longitude { get; set; }
  [JsonProperty]
  public double distance { get; set; }
  [JsonProperty]
  public double speed { get; set; }
}

Quando un record viene inserito in un database remoto, servizi mobili di Azure automaticamente crea un Id e assegna all'oggetto, in modo che l'Id sarà un valore diverso da null quando il record è stato inserito e null quando il record non è mai stato sincronizzato con il database:

// Manually synchronizing data
if (item.Id == null)
{
  await this.sensorDataTable.InsertAsync(item);
}

Sincronizzazione delle eliminazioni e aggiornamenti manualmente è un processo molto più difficile e rientra nell'ambito di questo articolo. Se si sta cercando una soluzione di sincronizzazione completa, controllare le funzionalità di sincronizzazione non in linea di Azure Mobile Services SDK. Ovviamente, questo esempio è molto semplice rispetto a scenari reali, ma se si desiderano per implementare la sincronizzazione manuale dei dati, questo può avere un'idea su dove iniziare. Certamente, poiché Azure Mobile Services SDK offre una soluzione collaudata, ben congegnato per la sincronizzazione dei dati, è consigliabile provare l'approccio di sincronizzazione non in linea, soprattutto nelle applicazioni che richiedono un metodo solido e testato per mantenere sincronizzati i dati locali e remoti.

Trasferimento di dati binari, Foto e file multimediali nel cloud

Oltre ai dati strutturati, le applicazioni devono spesso sincronizzare i dati non strutturati o binari o file.  Considerare un'applicazione mobile foto o un'applicazione che è necessario caricare un file binario nel cloud, ad esempio una foto o video. Poiché si descrivono questo oggetto in un contesto multipiattaforma, diverse piattaforme dispongono di funzionalità diverse. Ma sono davvero così diversi? Sincronizzazione dei dati blob può essere effettuata in più modi, ad esempio con un servizio in corso o sfruttando un processo out-of, il servizio di trasferimento di sfondo specifico della piattaforma. Per gestire i download, inoltre disponibile una semplice classe di TransferQueue, basata su ConcurrentQueue. Ogni volta che si desidera inviare un file per il caricamento o download, è possibile aggiungere un nuovo oggetto processo alla coda. Questo è un modello comune nel cloud, in cui è inserito il lavoro non completati in una coda e hanno quindi un altro processo di background lettura dalla coda e il completamento del lavoro.

Trasferimento di File in-Process a volte è necessario trasferire i file direttamente dall'interno dell'applicazione. Questo è il modo più ovvio di gestire i trasferimenti di blob, ma come già detto, presenta svantaggi. Per proteggere l'esperienza utente, il sistema operativo inserisce un delimitatore di utilizzo di un'applicazione di larghezza di banda e risorse. Tuttavia, si presuppone che l'utente sta utilizzando l'applicazione per l'utilizzo. Per le applicazioni disconnesse in alcuni casi, potrebbe non essere la soluzione migliore. Il vantaggio di trasferimento di file direttamente da un'applicazione è il controllo completo su trasferimento di dati. Con il controllo completo, un'applicazione può sfruttare accesso condiviso metodi di firma per la gestione di upload e download. È possibile leggere i vantaggi nel post del Blog del Team Microsoft Azure Storage "Introduzione della tabella coda SAS, SAS (Shared Access firma) e l'aggiornamento del Blob SAS," in bit.ly/1t1Sb94. Sebbene non tutte le piattaforme forniscono questa funzionalità incorporata, se si è disposti a utilizzare un approccio basato sul resto, certamente usufruire delle chiavi SAS da servizi di archiviazione Azure. Lo svantaggio di trasferimento di file direttamente da un'applicazione è duplice. Innanzitutto, è necessario scrivere altro codice. In secondo luogo, l'applicazione deve essere in esecuzione, potenzialmente lo svuotamento della batteria e limitando l'UX. Le migliori soluzioni sfruttano alcune dell'eleganza di tecniche di sincronizzazione di dati incorporati.

Fornito codice sorgente per un caricamento di base e l'operazione di download in un'applicazione di Xamarin multipiattaforma in BlobTransfer.cs (vedere download di codice di accompagnamento). Questo codice dovrebbe funzionare su iOS, Android e Windows. Per utilizzare l'archiviazione di file indipendenti dalla piattaforma, ho utilizzato il pacchetto PCLStorage NuGet (PCLStorage pacchetto di installazione), che consente di astrarre le operazioni su file su iOS, Android e Windows.

Per avviare un trasferimento in corso, chiamare il metodo TransferQueue AddInProcessAsync:

var ok = await queue.AddInProcessAsync(new Job {
  Id = 1, Url = imageUrl, LocalFile = String.Format("image{0}.jpg", 1)});

Ciò consente di pianificare un'operazione di download nel processo tipico, definita nell'oggetto BlobTransfer, come illustrato nella Figura 3.

Operazione di Download nella figura 3 (codice multipiattaforma)

public static async Task<bool> DownloadFileAsync(
  IFolder folder, string url, string fileName)
{
  // Connect with HTTP
  using (var client = new HttpClient())
  // Begin async download
  using (var response = await client.GetAsync(url))
  {
    // If ok?
    if (response.StatusCode == System.Net.HttpStatusCode.OK)
    {
      // Continue download
      Stream temp = await response.Content.ReadAsStreamAsync();
      // Save to local disk
      IFile file = await folder.CreateFileAsync(fileName,
        CreationCollisionOption.ReplaceExisting);
      using (var fs =
        await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
      {
        // Copy to temp folder
        await temp.CopyToAsync(fs); 
        fs.Close();
        return true;
      }
    }
    else
    {
      Debug.WriteLine("NOT FOUND " + url);
      return false;
    }
  }
}

Naturalmente, se si desidera caricare un file, è possibile farlo in-process utilizzando il metodo illustrato nella Figura 4.

Operazione di caricamento della figura 4 (codice multipiattaforma)

public static async Task UploadFileAsync(
  IFolder folder, string fileName, string fileUrl)
{
  // Connect with HTTP
  using (var client = new HttpClient()) 
  {
    // Start upload
    var file = await folder.GetFileAsync(fileName);
    var fileStream = await file.OpenAsync(PCLStorage.FileAccess.Read);
    var content = new StreamContent(fileStream);
    // Define content type for blob
    content.Headers.Add("Content-Type", "application/octet-stream");
    content.Headers.Add("x-ms-blob-type", "BlockBlob");
    using (var uploadResponse = await client.PutAsync(
      new Uri(fileUrl, UriKind.Absolute), content))
    {
      Debug.WriteLine("CLOUD UPLOADED " + fileName);
      return;
    }
  }
}

Sistema operativo utilizzo di trasferimento File out-of-Process-servizio di trasferimento specifico il download e caricamento tramite servizi di trasferimento di file incorporato offre molti vantaggi. La maggior parte delle piattaforme offrono un servizio che consente di trasferire file di grandi dimensioni (caricamento e download) in modo autonomo come servizio in background. Si potranno sfruttare tali servizi quando possibile poiché vengono eseguiti all'esterno del processo, vale a dire, l'applicazione non è limitata al trasferimento di dati effettivi, che può essere piuttosto costoso in termini di risorse consumate. Inoltre, non è necessario che l'applicazione rimane in memoria tutto il tempo di trasferimento dei file e il sistema operativo è in genere fornisce un meccanismo di risoluzione (Riprova) dei conflitti per riavviare gli upload e download. Altri vantaggi comprendono scrivere meno codice, l'applicazione non deve essere attivo (sistema operativo gestisce la propria coda di upload e download) e l'applicazione è la maggiore quantità di memoria /­risorse efficiente. La sfida, tuttavia, è che questo metodo richiede un'implementazione specifica della piattaforma: iOS, Windows Phone e così via sono proprio background transfer implementazioni.

Concettualmente, un caricamento affidabile per i file in un'applicazione per dispositivi mobili utilizzando un servizio di out-of-process di specifiche del sistema operativo è simile all'implementazione in app. Ma la gestione delle code di caricamento/scaricamento effettivo è affidato a terzi per il servizio di trasferimento del sistema operativo. Per applicazioni Windows Phone Store e applicazioni Windows Store, gli sviluppatori possono utilizzare gli oggetti BackgroundDownloader e BackgroundUploader. Per iOS 7 e versioni successive, NSUrlSession fornisce i metodi CreateDownloadTask e CreateUploadTask per avviare il download e caricamento.

Utilizzando l'esempio precedente, a questo punto necessario chiamare il metodo out-of-process per richiamare una chiamata utilizzando uno sfondo specifiche del sistema operativo servizio di trasferimento. Poiché il servizio è gestito dal sistema operativo, infatti, verranno programmare 10 download per illustrare l'applicazione non sia bloccata e l'esecuzione viene gestita dal sistema operativo (in questo esempio, ho utilizzato lo sfondo iOS trasferimento servizio):

for (int i = 0; i < 10; i++)
{
  queue.AddOutProcess(new Job { Id = i, Url = imageUrl,
    LocalFile = String.Format("image{0}.jpg", i) });
}

Per un esempio di un servizio di trasferimento di sfondo per iOS, controllare BackgroundTransferService.cs. In iOS è necessario inizializzare una sessione di sfondo con CreateBackgroundSessionConfiguration (notare che questo metodo funziona solo su iOS 8 o versione successiva):

using (var configuration = NSUrlSessionConfiguration.
  CreateBackgroundSessionConfiguration(sessionId))
{
  session = NSUrlSession.FromConfiguration(configuration);
}

Quindi è possibile inviare un caricamento lungo o operazione di download e il sistema operativo verrà gestito in modo indipendente dall'applicazione:

using (var uri = NSUrl.FromString(url))
using (var request = NSUrlRequest.FromUrl(uri))
{
  downloadTask = session.CreateDownloadTask(request);
  downloadTask.Resume();
}

È inoltre necessario considerare un meccanismo di coda in modo affidabile a caricare e scaricare i BLOB.

Codice di esempio e i passaggi successivi

Tutti i codice di esempio per questo articolo è disponibile su GitHub in bit.ly/11yZyhN. Per utilizzare questo codice sorgente, è possibile utilizzare Visual Studio con Xamarin o Xamarin Studio, disponibile da xamarin.com. Il progetto utilizza Xamarin.Forms di piattaforme e la libreria di servizi mobili di Azure con sincronizzazione offline. Per i passaggi successivi, sarebbe interessante vedere un servizio di out-of-process aggiunto alle librerie di Comunità, quali laboratori di Xamarin, nonché funzionalità di accodamento e risoluzione dei conflitti simile a quelle fornite per i dati strutturati in Azure Mobile Services non in linea Sync SDK.

Ricapitolando, Microsoft Azure Mobile Services forniscono in modo efficiente ed efficace per sincronizzare i dati non in linea. È possibile utilizzare questi servizi in uno scenario di piattaforme in Windows, Android e iOS. Microsoft fornisce inoltre facile utilizzare SDK nativo che funzionano su tutte le piattaforme. È possibile migliorare l'affidabilità dell'applicazione in scenari disconnessi mediante l'integrazione di questi servizi e aggiunta di sincronizzazione non in linea per le applicazioni.


Kevin Alice è un architect evangelist presso Microsoft. È coautore di "Professional Windows 8 Programming" (Wrox, 2012) e uno sviluppatore di applicazioni superiore e giochi, in particolare Active idoneità (activefitness.co). Egli presenta spesso sulla tecnologia a vari eventi, programmi di settore e webcast. Lavora con avvii e partner, consulenza sulla progettazione del software, business e strategia tecnologica, architettura e sviluppo. Seguirlo nel suo blog all'indirizzo kevinashley.com e su Twitter in twitter.com/kashleytwit.

Grazie ai seguenti esperti Microsoft per la revisione dell'articolo: Greg Oliver e Bruno Terkaly