Статьи

Windows Azure Mobile Services — серверная часть Microsoft для мобильных приложений

Вступление

Решения Mobile Backend as a Service (MBaaS) призваны снизить сложность разработки мобильных приложений, предлагая облачное хранилище, аутентификацию, push-уведомления и аналогичные услуги. Они используют интерфейс программирования RESTful для доступа к данным (операции создания / чтения / обновления / удаления на основе методов HTTP GET / PUT / POST / DELETE) и предлагают услуги аутентификации с использованием протокола OAuth. Поставщики также склонны предлагать комплекты разработки программного обеспечения для различных платформ, таких как iOS, Android, Windows Phone и т. Д. Это общая платформа, предлагаемая поставщиками MBaaS для разработчиков мобильных приложений для ускорения разработки. В этой сфере есть множество сервисов, таких как Kinvey, StackMob, Appcelerator и основные игроки в облаке, такие как Salesforce.com (см.
Database.comсообщение), Google и Microsoft также имеют свои собственные предложения. В этой статье мы собираемся представить Windows Azure Mobile Service в качестве облачной базы данных для мобильных приложений.

Начало работы с мобильными службами Azure

Мы покажем, как написать простое приложение Android, используя мобильные службы Azure в качестве облачной серверной базы данных для хранения контактных данных (имя, адрес электронной почты, номер телефона), а также покажем, как ввести аутентификацию для защиты наших данных и разрешать только аутентификацию. пользователи получают к нему доступ. Предполагая, что мы уже зарегистрировались в службах Windows Azure, нам необходимо войти на
портал управления Azure и щелкнуть значок «Мобильные службы». Откроется форма, в которой нам нужно будет указать наш URL-адрес (с постфиксом домена .azure-mobile.net), имя базы данных и регион (на момент написания статьи мы могли выбирать из западных районов США, восточных районов США). Северная Европа и Восточная Азия).

лазурью-1

Следующим шагом является создание нашей таблицы SQL. Мы можем нажать на меню « Данные» , предоставить имя для нашей таблицы и определить права доступа для каждого типа операций, таких как вставка, обновление, удаление и чтение.

лазурью-2

В результате у нас будет базовая таблица с несколькими предопределенными столбцами, такими как id, _createdAt, _version, которые автоматически генерируются мобильными службами Azure.

лазурью-3

Затем мы можем добавить наши столбцы, такие как имя, адрес электронной почты и телефон, к этой таблице, используя меню Добавить столбец (+) в нижней части консоли управления. На рисунке ниже показана таблица контактов, которая будет использоваться нашим приложением для Android. Наш облачный бэкэнд-слой готов к использованию.

лазурью-4

Мобильный клиент

Мобильные службы Windows Azure поддерживают большинство популярных платформ, таких как iOS, Android, Windows Phone или HTML / Javascript. Для этого поста мы разработали простое приложение для Android, чтобы продемонстрировать, как хранить контактную информацию в облаке. SDK для мобильных служб можно загрузить с
веб-страницы Windows Azure Developer Tools for Mobile Service . На момент написания статьи версия Android SDK 1.1.0. Первым шагом является создание проекта Android из Инструментов разработчика Android (ADT). Затем нам нужно разархивировать Mobile Service SDK для Android и скопировать все файлы jar из каталога mobileservices в каталог libs нашего проекта AzureContact.

лазурью-5

Тогда мы можем начать писать наш код. Приложение имеет два класса; основной класс активности называется AzureContactActivity.java, а класс сущностей, который описывает сущность данных, называется Contact.java. Ниже приведен код для этих классов. AzureContactActivity.java:

import java.net.MalformedURLException;
import java.util.List;
import com.example.azurecontacts.Contact;
import com.microsoft.windowsazure.mobileservices.MobileServiceClient;
import com.microsoft.windowsazure.mobileservices.MobileServiceTable;
import com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
import com.microsoft.windowsazure.mobileservices.TableOperationCallback;
import com.microsoft.windowsazure.mobileservices.TableQueryCallback;
import com.microsoft.windowsazure.mobileservices.MobileServiceUser;
import com.microsoft.windowsazure.mobileservices.UserAuthenticationCallback;
import com.microsoft.windowsazure.mobileservices.MobileServiceAuthenticationProvider;

import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class AzureContactActivity extends Activity {
    private MobileServiceClient mobileClient;
    private MobileServiceTable mobileContactTable;
    private EditText newContactName;
    private EditText newContactEmail;
    private EditText newContactPhone;
    private Button addButton;
    private Button searchButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		try {
			// Create the Mobile Service Client instance, using the provided
			// Mobile Service URL and key
			mobileClient = new MobileServiceClient(
					"https://istvan-contact.azure-mobile.net/",
					"XXXXXXXXXXXXXXXXXXXXXXXX", 
					this);
		} catch (MalformedURLException e) {
			createAndShowDialog(new Exception("There was an error creating the Mobile Service. Verify the URL"), "Error");
		}
		// TODO: Comment this section out if you do not want authentication
		/*
           mobileClient.login(MobileServiceAuthenticationProvider.MicrosoftAccount,
		        new UserAuthenticationCallback() {

		            @Override
		            public void onCompleted(MobileServiceUser user,
		                    Exception exception, ServiceFilterResponse response) {
		                if (exception == null) {
		                    createContactTable();
		                } else {
		                    createAndShowDialog("You must login.", "Error");
		                    return;
		                }
		            }
		        });
		 */      

		// TODO: Uncomment this section if you do not want authentication
		createContactTable();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void createContactTable() {
		mobileContactTable = mobileClient.getTable(Contact.class);
	    newContactName = (EditText) findViewById(R.id.name);
	    newContactEmail = (EditText) findViewById(R.id.email);
	    newContactPhone= (EditText) findViewById(R.id.phone);
	    addButton = (Button) findViewById(R.id.addButton); 
	    searchButton = (Button) findViewById(R.id.searchButton);
	    addButton.setOnClickListener( new Button.OnClickListener() {
		    public void onClick(View v) {
                addContact(v);
		    }
	    });

	    searchButton.setOnClickListener( new Button.OnClickListener() {
		    public void onClick(View v) {
                searchContact(v);
		    }
	    });
    }

	public void addContact(View view) {
                // Create a new contact
		Contact contact = new Contact();
		contact.setName(newContactName.getText().toString());
		contact.setEmail(newContactEmail.getText().toString());
		contact.setPhone(newContactPhone.getText().toString());

		// Insert the new contact
		mobileContactTable.insert(contact, new TableOperationCallback() {
			public void onCompleted(Contact entity, Exception exception, ServiceFilterResponse response) {
				if (exception != null) {
					createAndShowDialog(exception, "Error");
				}
			}
		});
	}
	private void searchContact(View view) {
		String name = newContactName.getText().toString();
		// Search for the contact based on the name field
		mobileContactTable.where().field("name").eq(name).execute(new TableQueryCallback() {
		    public void onCompleted(List result, int count, Exception exception, ServiceFilterResponse response) {
		    	if (exception == null) {
		    		if ( !result.isEmpty() ) {
		    			newContactName.setText(result.get(0).getName());
					    newContactEmail.setText(result.get(0).getEmail());
					    newContactPhone.setText(result.get(0).getPhone());
		    		}
			 } else {
					createAndShowDialog(exception, "Error");

	     		}
		    }
		});
	}

	private void createAndShowDialog(Exception exception, String title) {
		createAndShowDialog(exception.toString(), title);
	}

	private void createAndShowDialog(String message, String title) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(message);
		builder.setTitle(title);
		builder.create().show();
	}
}

Contact.java:

package com.example.azurecontacts;
public class Contact {
	/**
	 * Item Id
	 */
	@com.google.gson.annotations.SerializedName("id")
	private String cId;

	@com.google.gson.annotations.SerializedName("name")
	private String cName;

	@com.google.gson.annotations.SerializedName("email")
	private String cEmail;

	@com.google.gson.annotations.SerializedName("phone")
	private String cPhone;

	/**
	 * Contact constructor
	 */
	public Contact() {
	}

	/**
	 * Initializes a new Contact
	 * 
	 * @param name
	 *            The contact name
	 * @param email
	 *            The contact email
	 * @param phone
	 *            The contact phone
	 * @param id
	 *            The item id
	 */
	public Contact(String name, String email, String phone, String id) {
		this.setName(name);
		this.setEmail(email);
		this.setPhone(phone);
		this.setId(id);
	}

	/**
	 * Returns the contact name
	 */
	public String getName() {
		return cName;
	}

	/**
	 * Sets the contact name
	 * 
	 * @param name
	 *            name to set
	 */
	public final void setName(String name) {
		cName = name;
	}

	/**
	 * Returns the contact email
	 */
	public String getEmail() {
		return cEmail;
	}

	/**
	 * Sets the contact email
	 * 
	 * @param email
	 *            email to set
	 */
	public final void setEmail(String email) {
		cEmail = email;
	}

	/**
	 * Returns the contact phone
	 */
	public String getPhone() {
		return cPhone;
	}

	/**
	 * Sets the contact phone


	 * 
	 * @param phone
	 *             phone to set
	 */
	public final void setPhone(String phone) {
		cPhone = phone;
	}

	/**
	 * Returns the item id
	 */
	public String getId() {
		return cId;
	}

	/**
	 * Sets the item id
	 * 
	 * @param id
	 *            id to set
	 */
	public final void setId(String id) {
		cId = id;
	}

	@Override
	public boolean equals(Object o) {
		return o instanceof Contact && ((Contact) o).cId == cId;
	}
}

В файле манифеста (AndroidManifest.xml) нам нужно убедиться, что у нас есть разрешение на доступ в ИНТЕРНЕТ:

     <uses-permission android:name="android.permission.INTERNET" />

Теперь, если мы запустим наше приложение, мы можем ввести новое имя контакта, адрес электронной почты и телефон и отправить данные, нажав
кнопку
Добавить .

лазурью-6

The mobile application will execute the addContact() function that invokes mobileContactTable.insert(contact, … ) method to insert the data into the contact table store on Microsoft Azure cloud store. If we enter a name into the empty form and click on Search button, the application will return the contact details for the given person. Under the hood our AzureContact application invokes searchContact() method that will call mobileContactTable.where().field(«name»).eq(name).execute(…) This LINQ query will return the contact details if the value of column ‘name’соответствует заданному имени — аналогично SELECT * FROM contact WHERE name = SQL-запрос ‘Name’. Портал управления Azure позволяет нам проверять наши данные, хранящиеся в таблице контактов.

лазурью-7

Проверка подлинности для мобильных служб Azure

Мобильные службы Azure также поддерживают проверку подлинности OAuth, чтобы ограничить доступ к нашим данным, хранящимся в облаке. На данный момент поддерживаемыми поставщиками аутентификации являются Microsoft, Google, Twitter и Facebook. Чтобы настроить проверку подлинности OAuth для нашего приложения Android, нам нужно изменить разрешение таблицы контактов на «Только прошедшие проверку пользователи».

лазурью-8

Затем нам нужно перейти на веб-сайт нашего предпочтительного поставщика аутентификации, в примере мы собираемся использовать учетную запись Microsoft.

This webpage describes how to register your application with Microsoft Account. лазурь-10
After this step we need to configure the client id and client secret under our mobile service in Azure Management Portal (see Identity menu). лазурью-9
And finally we need to modify our Android application (AzureContactActivity.java) to invoke the Mobile Services login function, se TODO comment in the code:

        
        @Override
	protected void onCreate(Bundle savedInstanceState) {
        ....
        ....
                // TODO: Comment this section out if you do not want authentication
		mobileClient.login(MobileServiceAuthenticationProvider.MicrosoftAccount,
		        new UserAuthenticationCallback() {
		            @Override
		            public void onCompleted(MobileServiceUser user,
		                    Exception exception, ServiceFilterResponse response) {
		                if (exception == null) {
		                    createContactTable();
		                } else {
		                    createAndShowDialog("You must login.", "Error");
		                    return;
		                }
		            }
		        });

		// TODO: Uncomment this section if you do not want authentication
		//createContactTable();
          }

Теперь, когда мы запускаем наше мобильное приложение AzureContact, оно запрашивает имя пользователя и пароль, которые должны быть аутентифицированы с помощью учетной записи Microsoft. Только после успешной аутентификации мы можем искать или добавлять контактные данные.
лазурь-11