Работа c облачным бэкендом мобильных приложений в Visual...

Preview:

DESCRIPTION

Windows Azure Mobile Services – быстрый и функциональный мобильный бэкенд

Citation preview

5 июля 2013

Создание современных приложений с Visual Studio 2013

Ефимцева Наталия, natale@micorosoft.comРабота c облачным бэкендом мобильных приложений

Mobile Services – быстрый и функциональный мобильный бэкенд

Windows Azure Mobile Services

Data

Notifications

Auth

Server Logic

Scheduler

Logging & Diag

Scale

Mobile Service: что нового? Продакшен – 99.9% SLA

БД 20МБ бесплатно CLI Планировщик Custom API Source Control (git) Общий код

NPM Android SDK HTML + JS SDK Поддержка WP7.x

Приложение My TODO

Мультиплатформенность

Вам не нужно создавать отдельный мобильный сервис к каждой платформе!

Подключайте их все!

Мультиплатформенность

Смешарики

• Используют Mobile Services в Windows 8, Windows Phone, iOS, Android приложениях

Push-нотификации

Единая платформа для pushWindows Store

push.wns.sendToastText04(item.channel, {text1: text}, … );

Windows Phone

push.mpns.sendFlipTile(item.channel, {title: text}, …);

iOS

push.apns.send(item.token, { alert: text, payload: { inAppMessage: Details }}, …);

Android

push.gcm.send(item.registrationId, item.text, …);

Единая платформа для pushfunction sendNotifications() {

var deviceInfoTable = tables.getTable('DeviceInfo');

deviceInfoTable.where({ userId : user.userId }).read({

success: function(deviceInfos){

deviceInfos.forEach(function(deviceInfo){

if (deviceInfo.uuid != request.parameters.uuid) {

if (deviceInfo.pushToken != null && deviceInfo.pushToken != 'SimulatorToken') {

if (deviceInfo.platform == 'iOS') {

push.apns.send(deviceInfo.pushToken, {

alert: "New something created"

} , { //success / error block});

} else if (deviceInfo.platform == 'Android') {

push.gcm.send(deviceInfo.pushToken, "New something created", { success / error block});

}

}

}

});

}

});

}

Не забывайте проверять ответ при возврате от notification-сервера ошибке (или getFeedback для APNS)

Добавим toast-уведомления

Виртуальные таблицы

Создание таблицыЕе использование как endpoint’аТ.е. нет вызова request.Execute

Собственный код\API

• Скрипты, не привязанные к таблице• Доступ как• GET• POST• PUT• PATCH• DELETE

• Разделение прав

Собственный код\API

Обновим тайл через Custom API

Работа с хранилищем (Azure Storage)

Это возможноЭто еще не совершенноРеализуется через серверные скрипты и модули

Чтением данных из таблицыvar azure = require('azure');

function read(query, user, request) {

var accountName = 'accountname';

var accountKey = 'Accountkey------------nKHDsW2/0Jzg==';

var host = accountName + '.table.core.windows.net';

var tableService = azure.createTableService(accountName, accountKey, host);

tableService.queryTables(function (error, tables) {

if (error) {

request.respond(500, error);

} else {

request.respond(200, tables);

}

});

}

Работа с BLOB’амиvar azure = require('azure'), qs = require('querystring');

function insert(item, user, request) {

var accountName = 'accountname';

var accountKey = 'Accountkey------------nKHDsW2/0Jzg==';

var host = accountName + '.blob.core.windows.net';

var blobService = azure.createBlobService(accountName, accountKey, host);

var sharedAccessPolicy = {

AccessPolicy: {

Permissions: 'rw', //Read and Write permissions

Expiry: minutesFromNow(5)

}

};

var sasUrl = blobService.generateSharedAccessSignature(request.parameters.containerName,

request.parameters.blobName, sharedAccessPolicy);

var sasQueryString = { 'sasUrl' : sasUrl.baseUrl + sasUrl.path + '?' + qs.stringify(sasUrl.queryString) };

request.respond(200, sasQueryString);

}

function minutesFromNow(minutes) {

var date = new Date()

date.setMinutes(date.getMinutes() + minutes);

return date;

}

Работа с BLOB’ами

Работа с email

Отправка сообщения//var crypto = require('crypto');

//item.tempId = new Buffer(crypto.randomBytes(16)).toString('hex');

function sendEmail(item) {

var sendgrid = new SendGrid('myaccount@azure.com', 'mypassword');

var email = {

to : item.email,

from : 'from-me@chrisrisner.com',

subject : 'Welcome to MyApp',

text: 'Thanks for installing My App! Click this link to verify:\n\n'

+ 'http://myapp.azurewebsites.net/activate.html?id=' + item.id + '&tid=' + item.tempId,

createDate : new Date()

};

sendgrid.send({

to: item.email,

from: email.from,

subject: email.subject,

text: email.text

}, function(success, message) {

// If the email failed to send, log it as an error so we can investigate

if (!success) {

console.error(message);

} else {

saveSentEmail(email);

}

});

}

Отправим письмо

DelegatingHandler’ы

На стороне клиентаПерехватывают запросы и ответы

Добавляет версию к каждому запросуpublic static MobileServiceClient MobileService = new MobileServiceClient( "https://<your subdomain>.azure-mobile.net/", "<your app key>", new VersionHandler()); using System;using System.Net.Http;using System.Threading.Tasks;namespace WindowsStore{ public class VersionHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,

System.Threading.CancellationToken cancellationToken) { request.RequestUri = new Uri(request.RequestUri.AbsoluteUri.ToString() + "?version=v2"); return base.SendAsync(request, cancellationToken); } }}

Работа с версиями в серверном скриптеfunction insert(item, user, request) {

if (request.parameters.build < 2.0) {

item.description = 'Not entered';

}

request.execute({

success : function() {

if (request.parameters.build < 2.0) {

delete item.description;

}

request.respond();

}

});

}

Версионность

Авторизация: кэширование токена

Кэширование в .NETpublic static class CredentialLocker    {        private const string RESOURCE= "MobileServices";        public static void AddCredential(string username, string password) {            var vault = new PasswordVault();            var credential = new PasswordCredential(RESOURCE, username, password);            vault.Add(credential);        }        public static PasswordCredential GetCredential() {                        PasswordCredential credential = null;                        var vault = new PasswordVault();                        try {                                        credential = vault.FindAllByResource(RESOURCE).FirstOrDefault();                                if (credential != null){                                                               credential.Password = vault.Retrieve(RESOURCE, credential.UserName).Password;                        }                }    

catch (Exception)    { //creds not found       }

            return credential;        }

        public static void RemoveCredential(string username) {                var vault = new PasswordVault();                try {                        // Removes the credential from the password vault.                        vault.Remove(vault.Retrieve(RESOURCE, username));                }                catch (Exception)    { //creds not stored       }        }    }

Получение токенаSetting:

MoblieServiceUser user;user = await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook);CredentialLocker.AddCredential(user.userId, user.MobileServiceAuthenticationToken);

Getting:

var credential = CredentialLocker.GetCredential();if (credential != null){ MobileService.CurrentUser = new MobileServiceUser(credential.UserName); MobileService.CurrentUser.MobileServiceAuthenticationToken =

credential.Password; }

Авторизуемся с Google

Авторизация: обновление токена

Обновление токенаЗапрос (request)

Проверка ответа (response) на 401 код ошибки Повторный login

пользователя

Обновление запроса (request) новым токеном

Повторная отправка запроса (request)

Обновление UI

DelegationHandlers (снова)public class VersionHandler : DelegatingHandler{ protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,

System.Threading.CancellationToken cancellationToken) { var response = await base.SendAsync(request, cancellationToken); while (response.StatusCode == HttpStatusCode.Unauthorized) { try { await App.MobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook); request.Headers['X-ZUMO-AUTH'] =

App.MobileService.CurrentUser.MobileServiceAuthenticationToken; } catch (Exception ex) {}

response = await base.SendAsync(request, cancellationToken); } } }

Получение данных постранично

На клиентеНа сервере

На клиентеC#:IMobileServiceTableQuery<TodoItem> query = todoTable .Where(todoItem => todoItem.Complete == false) .Skip(3) .Take(3);items = await query.ToCollectionAsync();ListItems.ItemsSource = items;

iOS:NSPredicate * predicate = [NSPredicate predicateWithFormat:@"complete == NO"];MSQuery * query = [self.table queryWithPredicate:predicate];query.includeTotalCount = YES; // Request the total item count

query.fetchOffset = 3;query.fetchLimit = 3;

[query readWithCompletion:^(NSArray *results, NSInteger totalCount, NSError *error) { …

Android:mToDoTable.where().field("complete").eq(false).skip(3).top(3) .execute(new TableQueryCallback<ToDoItem>() {

На сервереOption 1:query.where({complete: false}) .take(3) .skip(3);

Option 2:var q = query.getComponents();q.take = 3;q.skip = 1;query.setComponents(q);

Option 3:query.where(function() {

return this.complete == false}) .take(3) .skip(3);

Поддержка Source Control

Включается на порталеСоздается git репозиторийКопируем локально, работаем, обновляем удаленный репозиторийДобавление NPM модулей

Интеграция с Git и добавление node-uuid

Windows Azure Mobile Services

© 2012 Microsoft Corporation. All rights reserved. Microsoft, Windows, and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.

Ефимцева Наталияnatale@microsoft.com@nefimtseva

Команда Windows Azure в России – azurerus@microsoft.com

Recommended