Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
/[Ll]ibrary/
/[Tt]emp/
/[Oo]bj/
/[Bb]uild/
/[Bb]uilds/
/Assets/AssetStoreTools*

# Autogenerated VS/MD solution and project files
# Visual Studio 2015 cache directory
/.vs/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
Expand All @@ -13,10 +20,21 @@
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb

# Unity3D generated meta files
*.pidb.meta
*.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

# IDEs
/.vscode
omnisharp.json
.editorconfig
61 changes: 61 additions & 0 deletions AppServiceClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using RESTClient;
using System;
using System.Collections;
using UnityEngine;

namespace Azure.AppServices {
public sealed class AppServiceClient : ZumoClient {

public AppServiceClient(string url) : base(url) {
}

public static AppServiceClient Create(string account) {
string url = AppUrl(account);
return new AppServiceClient(url);
}

private const string URI_API = "api";

public AppServiceTable<E> GetTable<E>(string tableName) where E : class {
return new AppServiceTable<E>(tableName, this);
}

/// <summary>
/// GET custom API
/// </summary>
public IEnumerator InvokeApi<T>(string apiName, Action<IRestResponse<T>> callback = null) where T : new() {
return InvokeApi<T>(apiName, Method.GET, callback);
}

/// <summary>
/// Invokes custom API for HTTP Methods: GET, POST, PUT, PATCH, DELETE
/// </summary>
public IEnumerator InvokeApi<T>(string apiName, Method httpMethod, Action<IRestResponse<T>> callback = null) where T : new() {
string url = ApiUrl(apiName);
Debug.Log(httpMethod.ToString() + " custom API Request Url: " + url);
ZumoRequest request = new ZumoRequest(url, httpMethod, true, User);
yield return request.Request.Send();
request.ParseJson<T>(callback);
}

/// <summary>
/// Invokes custom API with body (of type B) and returning response (of type T)
/// </summary>
public IEnumerator InvokeApi<B, T>(string apiName, Method httpMethod, B body, Action<IRestResponse<T>> callback = null) where T : new() {
string url = ApiUrl(apiName);
Debug.Log(httpMethod.ToString() + " custom API Request Url: " + url);
ZumoRequest request = new ZumoRequest(url, httpMethod, true, User);
request.AddBody<B>(body);
yield return request.Request.Send();
request.ParseJson<T>(callback);
}

private string ApiUrl(string apiName) {
return string.Format("{0}/{1}/{2}", Url, URI_API, apiName);
}

}
}
27 changes: 27 additions & 0 deletions IAppServiceClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using RESTClient;
using System;
using System.Collections;

namespace Azure.AppServices {
public interface IAppServiceClient : IZumoClient {
AppServiceTable<E> GetTable<E>(string tableName) where E : class;

/// <summary>
/// Invokes a custom API using GET HTTP method
/// </summary>
IEnumerator InvokeApi<T>(string apiName, Action<IRestResponse<T>> callback = null) where T : new();

/// <summary>
/// Invokes a custom API for HTTP Methods: GET, POST, PUT, PATCH, DELETE
/// </summary>
IEnumerator InvokeApi<T>(string apiName, Method httpMethod, Action<IRestResponse<T>> callback = null) where T : new();

/// <summary>
/// Invokes a custom API with body object
/// </summary>
IEnumerator InvokeApi<B, T>(string apiName, Method httpMethod, B body, Action<IRestResponse<T>> callback = null) where T : new();
}
}
25 changes: 25 additions & 0 deletions IZumoClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using RESTClient;
using System;
using System.Collections;

namespace Azure.AppServices {
public interface IZumoClient {

AuthenticatedUser User { get; }

IEnumerator LoginWithFacebook(string accessToken, Action<IRestResponse<AuthenticatedUser>> callback = null);

IEnumerator LoginWithTwitter(string accessToken, string accessTokenSecret, Action<IRestResponse<AuthenticatedUser>> callback = null);

IEnumerator LoginWithGoogle(string accessToken, string idToken, Action<IRestResponse<AuthenticatedUser>> callback = null);

IEnumerator LoginWithMicrosoftAccount(string accessToken, Action<IRestResponse<AuthenticatedUser>> callback = null);

IEnumerator LoginWithAAD(string accessToken, Action<IRestResponse<AuthenticatedUser>> callback = null);

IEnumerator Logout(Action<IRestResponse<string>> callback = null);
}
}
111 changes: 71 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Azure App Services for Unity3d
For game developers looking to use Azure App Services (previously Mobile Services) in their Unity project. This App Services REST API library for Unity is quite similar in structure to the Azure Mobile Services SDK so if you've used that before you should feel relatively at home.
# Azure App Services for Unity
For Unity developers looking to use Azure App Services (previously Mobile Services) in their Unity game / app.

## Prerequisites
## What's new
Please be aware this latest update of the library brings a number of changes to the namespace, some class names and method calls have been updated as Mobile Services is replaced by App Services. There is also a dependency on a shared [RESTClient for Unity](https://github.com/Unity3dAzure/RESTClient) so that multiple Unity libraries for Azure can be supported without adding duplicate scripts.

## External dependencies
**First download the shared [REST Client library for Unity](https://github.com/Unity3dAzure/RESTClient) and extract the contents into your Unity project "Assets" folder.**
* [RESTClient](https://github.com/Unity3dAzure/RESTClient)

## Requirements
Requires Unity v5.3 or greater as [UnityWebRequest](https://docs.unity3d.com/Manual/UnityWebRequest.html) and [JsonUtility](https://docs.unity3d.com/ScriptReference/JsonUtility.html) features are used. Unity will be extending platform support for UnityWebRequest so keep Unity up to date if you need to support these additional platforms.

## How to setup App Services with a new Unity project
1. [Download AppServices](https://github.com/Unity3dAzure/AppServices/archive/master.zip)
1. [Download AppServices](https://github.com/Unity3dAzure/AppServices/archive/master.zip)
* Copy 'AppServices' into project `Assets` folder.
2. Create an Azure App Service [Mobile App](https://portal.azure.com)
* Create a Table (using Easy Tables) for app data.
Expand All @@ -15,94 +22,118 @@ Try the [Azure App Services Demos](https://github.com/Unity3dAzure/AppServicesDe
For detailed instructions read my developer blog on [how to setup Azure App Services and Unity demo project](http://www.deadlyfingers.net/azure/azure-app-services-for-unity3d/).

## Supported Features
### MobileServiceClient
### AppServiceClient API
API | Description
--- | -----------
Login | Client-directed login using access token.
LoginWithFacebook | Client-directed login using user access token.
LoginWithTwitter | Client-directed login using access token and access token secret.
LoginWithGoogle | Client-directed login using access token and id token.
LoginWithMicrosoftAccount | Client-directed login using access token.
LoginWithAAD | Client-directed login using access token.
Logout | Logout current user
InvokeApi | Invoke custom API (Easy API) using GET, POST, PUT, PATCH or DELETE

### MobileServiceTable
### AppServiceTable API
API | Description
--- | -----------
Insert | Create a new item.
Read | Get a list of items.
Update | Update an item’s data using id property.
Delete | Delete an item using id property.
Delete | Delete an item using id property.
Query | Get a list of results using a custom query.
Lookup | Get an item’s data using id property.

### [MobileServiceClient Interface](https://github.com/Unity3dAzure/AppServices/blob/master/client/IAzureMobileServiceClient.cs)
Login(MobileServiceAuthenticationProvider provider, string token, Action<IRestResponse<MobileServiceUser>> callback = null);
InvokeApi<T>(string apiName, Action<IRestResponse<T>> callback = null) where T : new();
InvokeApi<T>(string apiName, Method httpMethod, Action<IRestResponse<T>> callback = null) where T : new();
InvokeApi<T>(string apiName, Method httpMethod, T body, Action<IRestResponse<T>> callback = null) where T : new();
### [AppServiceClient Interface](https://github.com/Unity3dAzure/AppServices/blob/master/IAppServiceClient.cs)
LoginWithFacebook(string accessToken, Action<IRestResponse<AuthenticatedUser>> callback = null);
LoginWithTwitter(string accessToken, string accessTokenSecret, Action<IRestResponse<AuthenticatedUser>> callback = null);
LoginWithGoogle(string accessToken, string idToken,Action<IRestResponse<AuthenticatedUser>> callback = null);
LoginWithMicrosoftAccount(string accessToken,Action<IRestResponse<AuthenticatedUser>> callback = null);
LoginWithAAD(string accessToken, Action<IRestResponse<AuthenticatedUser>> callback = null);
Logout(Action<IRestResponse<string>> callback = null);

### [AppServiceClient (Easy APIs) Interface](https://github.com/Unity3dAzure/AppServices/blob/master/IAppServiceClient.cs)
InvokeApi<T> (string apiName, Action<IRestResponse<T>> callback = null) where T : new();
InvokeApi<T> (string apiName, Method httpMethod, Action<IRestResponse<T>> callback = null) where T : new();
InvokeApi<B,T> (string apiName, Method httpMethod, B body, Action<IRestResponse<T>> callback = null) where T : new();

### [MobileServiceTable Interface](https://github.com/Unity3dAzure/AppServices/blob/master/table/IAzureMobileServiceTable.cs)
### [AppServiceTable (Easy Tables) Interface](https://github.com/Unity3dAzure/AppServices/blob/master/table/IAppServiceTable.cs)
Insert<T>(T item, Action<IRestResponse<T>> callback = null) where T : new();
Read<T>(Action<IRestResponse<T[]>> callback = null) where T : new();
Update<T>(T item, Action<IRestResponse<T>> callback = null) where T : new();
Delete<T>(string id, Action<IRestResponse<T>> callback = null) where T : new();
Query<T>(CustomQuery query, Action<IRestResponse<T[]>> callback = null) where T : new();
Query<T>(CustomQuery query, Action<IRestResponse<T>> callback = null) where T : INestedResults, new();
Query<T>(TableQuery query, Action<IRestResponse<T[]>> callback = null) where T : new();
Query<T>(TableQuery query, Action<IRestResponse<T>> callback = null) where T : INestedResults, new();
Lookup<T>(string id, Action<IRestResponse<T>> callback = null) where T : new();

## Sample usage
- Data model for **TodoItem.cs**
```
using Azure.AppServices;
[System.Serializable]
public class TodoItem : DataModel {
public string text;
public bool complete;
}
```

- Unity script
```
using System.Collections
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Collections.Generic;
using Unity3dAzure.AppServices;

using RESTClient;
using Azure.AppServices;
```

```
private MobileServiceClient _client;
private MobileServiceTable<TodoItem> _table;
private AppServiceClient _client;
private AppServiceTable<TodoItem> _table;
```

```
void Start () {
_client = new MobileServiceClient(appUrl); // <- add your app url here.
_table = _client.GetTable<TodoItem>("TodoItem");
_client = AppServiceClient.Create("unityapp"); // <- add your App Service account here!
_table = _client.GetTable<TodoItem>("TodoItem");
ReadItems();
}
```
```
private void ReadItems() {
StartCoroutine( _table.Read<TodoItem>(OnReadItemsCompleted) );
StartCoroutine( _table.Read<TodoItem>(OnReadItemsCompleted) );
}

private void OnReadItemsCompleted(IRestResponse<TodoItem[]> response) {
if (!response.IsError) {
Debug.Log ("OnReadCompleted: " + response.Url + " data: " + response.Content);
TodoItem[] items = response.Data;
Debug.Log ( "Todo items count: " + items.Count);
} else {
Debug.LogWarning ("Read Error Status:" + response.StatusCode + " Url: " + response.Url);
}
if (!response.IsError) {
Debug.Log ("OnReadCompleted: " + response.Url + " data: " + response.Content);
TodoItem[] items = response.Data;
Debug.Log ( "Todo items count: " + items.Length);
} else {
Debug.LogWarning ("Read Error Status:" + response.StatusCode + " Url: " + response.Url);
}
}
```

## Known issues
* There is an issue with [PATCH on Android using UnityWebRequest with Azure App Services](http://answers.unity3d.com/questions/1230067/trying-to-use-patch-on-a-unitywebrequest-on-androi.html). Android won't recognize the "PATCH" http method currently required to update an item in App Services. One workaround is to enable the `X-HTTP-Method-Override` header. Here's the quick fix for App Services running node backend:
1. Install the "method-override" package.
1. Install the "method-override" package.
```
npm install method-override --save
```
2. In 'app.js' file insert:
```
var methodOverride = require('method-override');
// after the line "var app = express();" add
2. In 'app.js' file insert:
```
var methodOverride = require('method-override');
// after the line "var app = express();" add
app.use(methodOverride('X-HTTP-Method-Override'));
```

This will enable PATCH requests to be sent on Android.

## Supported platforms
Will work on all the platforms [UnityWebRequest](https://docs.unity3d.com/Manual/UnityWebRequest.html) supports including:
* Unity Editor and Standalone players
Intended to work on all the platforms [UnityWebRequest](https://docs.unity3d.com/Manual/UnityWebRequest.html) supports including:
* Unity Editor (Mac/PC) and Standalone players
* iOS
* Android
* Windows

Questions or tweet #Azure #GameDev [@deadlyfingers](https://twitter.com/deadlyfingers)
Questions or tweet [@deadlyfingers](https://twitter.com/deadlyfingers)
Loading