diff --git a/.gitignore b/.gitignore
index 05c865c6c5..522f674c9f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,3 +84,4 @@ portal/js/templates.js
/stack/core/src/main/java/org/apache/usergrid/persistence/query/tree/QueryFilterParser.java
!/stack/corepersistence/common/src/test/resources/usergrid-UNIT.properties
*.iml
+sdks/dotnet/samples/notifications/packages/*
diff --git a/portal/js/push/push-config.html b/portal/js/push/push-config.html
index 8dbdf38811..8cacab0d05 100644
--- a/portal/js/push/push-config.html
+++ b/portal/js/push/push-config.html
@@ -165,7 +165,7 @@
A Notifier allows App Services to connect to and deliver a message to a communication provider such as
Windows Notifications Service (WNS). Copy and paste your API key to create a bridge between your app
- and GCM for push notifications on Android devices..
+ and WNS for push notifications on windows devices..
For more help: see our getting started page page.
@@ -189,10 +189,12 @@
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications.sln b/sdks/dotnet/samples/notifications/Usergrid.Notifications.sln
new file mode 100644
index 0000000000..5474b5b7f1
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications.sln
@@ -0,0 +1,40 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Usergrid.Notifications", "Usergrid.Notifications\Usergrid.Notifications.csproj", "{EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|ARM = Debug|ARM
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|ARM = Release|ARM
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|ARM.ActiveCfg = Debug|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|ARM.Build.0 = Debug|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|ARM.Deploy.0 = Debug|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|x86.ActiveCfg = Debug|x86
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|x86.Build.0 = Debug|x86
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Debug|x86.Deploy.0 = Debug|x86
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|ARM.ActiveCfg = Release|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|ARM.Build.0 = Release|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|ARM.Deploy.0 = Release|ARM
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|x86.ActiveCfg = Release|x86
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|x86.Build.0 = Release|x86
+ {EB364B8E-B7C1-45C2-BF13-1CBF731EA8B6}.Release|x86.Deploy.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml b/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml
index 8a363591d4..486a2fdf55 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml
@@ -3,5 +3,25 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Usergrid.Notifications">
-
+
\ No newline at end of file
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml.cs
index 9bf62ac99b..eb079fbba1 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml.cs
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/App.xaml.cs
@@ -1,4 +1,23 @@
-using System;
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/EntityResponse.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/EntityResponse.cs
new file mode 100644
index 0000000000..0be267a061
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/EntityResponse.cs
@@ -0,0 +1,80 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Usergrid.Notifications.Client
+{
+ public class EntityResponse : JObject
+ {
+ private HttpResponseMessage response;
+
+ private EntityResponse(HttpResponseMessage response, JObject jObject)
+ : base()
+ {
+ this.response = response;
+ parseResponse(jObject);
+ }
+
+ private void parseResponse(JObject jobject)
+ {
+ foreach (var kv in jobject)
+ {
+ this[kv.Key] = kv.Value;
+ }
+ }
+
+ public HttpStatusCode Status
+ {
+ get { return this.response.StatusCode; }
+ }
+
+ public static async Task
Parse(HttpResponseMessage httpResponseMessage)
+ {
+ JObject jobject;
+
+ using (var stream = await httpResponseMessage.Content.ReadAsStreamAsync())
+ {
+ using (var reader = new StreamReader(stream, Encoding.UTF8))
+ {
+ jobject = JObject.Parse(reader.ReadToEnd());
+ }
+ }
+
+ return new EntityResponse(httpResponseMessage, jobject);
+ }
+
+ public bool StatusIsOk
+ {
+ get
+ {
+ return this.Status == HttpStatusCode.OK;
+ }
+ }
+ }
+}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/IUsergridClient.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/IUsergridClient.cs
new file mode 100644
index 0000000000..3f4fb82242
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/IUsergridClient.cs
@@ -0,0 +1,123 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+
+using Newtonsoft.Json.Linq;
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using Windows.Networking.PushNotifications;
+namespace Usergrid.Notifications.Client
+{
+ ///
+ /// encapsulates usergrid calls, use UsergridFactory
+ ///
+ public interface IUsergridClient
+ {
+ ///
+ /// Authenticate your calls
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task Authenticate(string user, string password, bool isManagement);
+ ///
+ /// Send a message
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SendAsync(HttpMethod method, string url, object obj);
+ ///
+ /// Send a message
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SendAsync(HttpMethod method, string url, object obj, bool useManagementUrl);
+ ///
+ /// Reference the push client, you should call register before using
+ ///
+ IPushClient Push { get; }
+
+ Exception LastException { get; }
+
+ }
+
+ ///
+ /// Only show http calls
+ ///
+ public interface IUsergridHttpClient
+ {
+ ///
+ /// Send Http call async
+ ///
+ ///
+ ///
+ ///
+ /// use management endpoint
+ ///
+ Task SendAsync(HttpMethod method, string url, object obj, bool useManagementUrl);
+ ///
+ /// send Http call async
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task SendAsync(HttpMethod method, string url, object obj);
+ }
+
+ ///
+ /// Push client, call register
+ ///
+ public interface IPushClient
+ {
+ ///
+ /// the notifier you are currently using
+ ///
+ string Notifier { get; set; }
+
+ ///
+ /// Device id in usergrid
+ ///
+ Guid DeviceId { get; set; }
+ ///
+ /// send a toast
+ ///
+ ///
+ ///
+ Task SendToast(string message);
+
+ ///
+ /// Send a badge update
+ ///
+ ///
+ ///
+ Task SendBadge(T message);
+
+ Exception LastException { get; }
+
+ }
+
+}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/PushClient.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/PushClient.cs
new file mode 100644
index 0000000000..8668626fec
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/PushClient.cs
@@ -0,0 +1,153 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.Networking.PushNotifications;
+using Windows.Storage;
+
+namespace Usergrid.Notifications.Client
+{
+ public class PushClient : IPushClient
+ {
+ const string DEVICE_KEY = "currentDeviceId";
+ private IUsergridHttpClient usergrid;
+ private ApplicationDataContainer settings;
+ private PushNotificationChannel channel;
+
+ public PushClient(IUsergridHttpClient usergrid, string notifier)
+ {
+ this.usergrid = usergrid;
+ this.settings = ApplicationData.Current.LocalSettings;
+ this.Notifier = notifier;
+ this.init().ContinueWith(t =>
+ {
+ LastException = t.Exception;
+ }
+ );
+ }
+
+
+ public async Task SendToast(string message)
+ {
+ if (DeviceId == null)
+ {
+ throw new Exception("Please call PushClient.RegisterDevice first.");
+ }
+ var jsonObject = new JObject();
+ var payloads = new JObject();
+ var payload = new JObject();
+ payload.Add("toast", new JValue(message));
+ payloads.Add(Notifier, payload);
+ jsonObject.Add("payloads", payloads);
+ jsonObject.Add("debug", true);
+ var jsonResponse = await usergrid.SendAsync(HttpMethod.Post, String.Format("devices/{0}/notifications", this.DeviceId), jsonObject);
+ return jsonResponse.StatusIsOk;
+ }
+
+ public async Task SendBadge(T message)
+ {
+ if (DeviceId == null)
+ {
+ throw new Exception("Please call PushClient.RegisterDevice first.");
+ }
+ var jsonObject = new JObject();
+ var payloads = new JObject();
+ var payload = new JObject();
+ payload.Add("badge", new JValue(message));
+ payloads.Add(Notifier, payload);
+ jsonObject.Add("payloads", payloads);
+ jsonObject.Add("debug", true);
+ var jsonResponse = await usergrid.SendAsync(HttpMethod.Post, String.Format("devices/{0}/notifications", this.DeviceId), jsonObject);
+ return jsonResponse.StatusIsOk;
+ }
+
+ private async Task init()
+ {
+ channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync().AsTask();
+ if (settings.Values[DEVICE_KEY] == null)
+ {
+ Guid uuid = await registerDevice(true);
+ settings.Values.Add(DEVICE_KEY, uuid);
+ this.DeviceId = uuid;
+ }
+ else
+ {
+ object tempId;
+ settings.Values.TryGetValue(DEVICE_KEY, out tempId);
+ this.DeviceId = Guid.Parse(tempId.ToString());
+ var device = await GetDevice(DeviceId);
+ if (device == null)
+ {
+ Guid uuid = await registerDevice(true);
+ settings.Values[DEVICE_KEY] = uuid;
+ this.DeviceId = uuid;
+ }
+ else
+ {
+ await registerDevice(false);
+ }
+ }
+ }
+
+
+ private async Task GetDevice(Guid deviceId)
+ {
+ var jsonResponse = await usergrid.SendAsync(HttpMethod.Get, "devices/" + deviceId, null);
+
+ if (jsonResponse.StatusIsOk)
+ {
+ var body = jsonResponse.GetValue("entities");
+ return body != null && body.Value().Count > 0 ? body.Value()[0] : null;
+ }
+ else { return null; }
+ }
+
+ private async Task registerDevice(bool isNew)
+ {
+ JObject obj = new JObject();
+ obj.Add(Notifier + ".notifier.id", new JValue(channel.Uri));
+ var jsonResponse = await usergrid.SendAsync(
+ (isNew ? HttpMethod.Post : HttpMethod.Put),
+ "devices/" + (isNew ? "" : this.DeviceId.ToString()),
+ obj
+ );
+
+ if (jsonResponse.StatusIsOk)
+ {
+ var entity = jsonResponse.GetValue("entities").Value()[0];
+ var uuid = Guid.Parse(entity.Value("uuid"));
+ return uuid;
+ }
+ else {
+ return Guid.Empty;
+ }
+ }
+
+ public string Notifier { get; set; }
+ public Guid DeviceId { get; set; }
+ public Exception LastException { get; set; }
+
+ }
+}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/Usergrid.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/Usergrid.cs
new file mode 100644
index 0000000000..cd0330df3b
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Client/Usergrid.cs
@@ -0,0 +1,120 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+
+using System;
+using System.Threading.Tasks;
+using System.Net;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System.Net.Http;
+using System.Net.Http.Headers;
+
+namespace Usergrid.Notifications.Client
+{
+
+ ///
+ /// Usergrid client
+ ///
+
+ public class Usergrid : IUsergridHttpClient, IUsergridClient
+ {
+ private string appUrl;
+ private string token;
+ private HttpClient client;
+ private IPushClient push;
+ private string managementUrl;
+
+ ///
+ /// Constructor
+ ///
+ ///
+ ///
+ ///
+ ///
+ internal Usergrid(string serverUrl, string org, string app, string notifier)
+ {
+ string serverUrlWithSlash = serverUrl.EndsWith("/", StringComparison.CurrentCulture) ? serverUrl : serverUrl + "/";
+ this.appUrl = String.Format("{0}{1}/{2}/", serverUrlWithSlash, org, app);
+ this.managementUrl = serverUrlWithSlash + "management/";
+ this.client = new HttpClient();
+ this.push = new PushClient(this,notifier);
+ }
+
+ public async Task Authenticate(string user, string password, bool isManagement)
+ {
+ var jsonObject = new JObject();
+ jsonObject.Add("username", user);
+ jsonObject.Add("password", password);
+ jsonObject.Add("grant_type", "password");
+
+ var response = await SendAsync(HttpMethod.Post,"token", jsonObject, isManagement);
+
+ if (response.StatusIsOk)
+ {
+ this.token = response.GetValue("access_token").Value();
+ client.DefaultRequestHeaders.Add("X-Authorization", token);
+ }
+ else
+ {
+ throw new Exception("Authentication failed: "+response.ToString());
+ }
+ }
+
+ private async Task GetJsonResponse(HttpResponseMessage response)
+ {
+ return await EntityResponse.Parse(response);
+ }
+
+ public async Task SendAsync(HttpMethod method, string url, object obj)
+ {
+ return await SendAsync(method, url, obj, false);
+ }
+
+ public async Task SendAsync(HttpMethod method, string url, object obj, bool useManagementUrl)
+ {
+ HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, (useManagementUrl ? this.managementUrl : this.appUrl) + url);
+ if (obj != null)
+ {
+ message.Content = getJsonBody(obj);
+ }
+ message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue( "application/json"));
+ var response = await this.client.SendAsync(message);
+ return await EntityResponse.Parse(response);
+ }
+
+ public IPushClient Push
+ {
+ get { return push; }
+ }
+
+ private HttpContent getJsonBody(Object jsonObject)
+ {
+ return new StringContent(JsonConvert.SerializeObject(jsonObject));
+ }
+
+
+ public Exception LastException
+ {
+ get;
+ set;
+ }
+ }
+
+}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml b/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml
index 3e0affdb58..f22c8b6616 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml
@@ -7,14 +7,32 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
-
+
-
-
-
-
-
-
+
+
+
+
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml.cs
index 882838d2c1..7e03c79bba 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml.cs
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/MainPage.xaml.cs
@@ -1,18 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
-using Windows.Networking.PushNotifications;
-using Windows.Storage;
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+using System;
+using System.Threading.Tasks;
+using Usergrid.Notifications.Client;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=391641
@@ -24,33 +33,38 @@ namespace Usergrid.Notifications
///
public sealed partial class MainPage : Page
{
- private Usergrid usergrid;
+ private IUsergridClient usergrid;
private string serverUrl;
private string org;
private string app;
private string notifier;
- private string apiKey;
- private string secret;
- private Guid deviceId;
+ private string user;
+ private string password;
public MainPage()
{
this.InitializeComponent();
- var myIp = "10.0.1.20";
- serverUrl = "http://" + myIp + ":8080";
+ //TODO: change me to your server
+ serverUrl = "http://10.0.1.20:8080";
+ //TODO: change me to your org
org = "mobile";
+ //TODO: change me to your app
app = "sandbox";
+ //TODO: change me to your notifier name
notifier = "winphone";
+ //TODO: change me to your user
+ user = "superuser";
+ //TODO: change me to your password
+ password = "test";
this.NavigationCacheMode = NavigationCacheMode.Required;
- this.setup();
+ this.setup().ContinueWith(t => {
+ LastException = t.Exception;
+ });
}
- private async void setup()
+ private async Task setup()
{
- usergrid = new Usergrid(serverUrl, org, app);
- await this.usergrid.Authenticate("superuser", "test", true);
- await usergrid.Push.RegisterDevice(notifier);
-
-
+ usergrid = new Client.Usergrid(serverUrl, org, app, notifier);
+ await usergrid.Authenticate(user, password, true);
}
///
@@ -68,22 +82,46 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
// If you are using the NavigationHelper provided by some templates,
// this event is handled for you.
}
+
+ private void pushText_TextChanged(object sender, TextChangedEventArgs e)
+ {
+
+ }
private async void Button_Click(object sender, RoutedEventArgs e)
{
+ Result.Text = "Sending....";
var message = this.pushText.Text;
- await usergrid.Push.SendNotification(deviceId,message);
+ if (await usergrid.Push.SendToast(message))
+ {
+ Result.Text = "It did! :)";
+ }
+ else
+ {
+ Result.Text = "It did not! :(";
+ }
}
- private void pushText_TextChanged(object sender, TextChangedEventArgs e)
+ private async void Badge_Click(object sender, RoutedEventArgs e)
{
+ Result.Text = "Sending....";
+ if (await usergrid.Push.SendBadge(new Random().Next(1,100)))
+ {
+ Result.Text = "It did! :)";
+ }
+ else
+ {
+ Result.Text = "It did not! :(";
+ }
}
- private async void AddNotifierButton_Click(object sender, RoutedEventArgs e)
+ private void Result_SelectionChanged(object sender, RoutedEventArgs e)
{
- await usergrid.Push.AddNotifier(NotifierName.Text,Sid.Text,Api_Key.Text);
+
}
+
+ public AggregateException LastException { get; set; }
}
}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Package.appxmanifest b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Package.appxmanifest
index a47ef82182..03165e622a 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Package.appxmanifest
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Package.appxmanifest
@@ -1,6 +1,27 @@
-
+
+
usergrid sample
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.Notifications.csproj b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.Notifications.csproj
index c811c83e4c..f5ec3fa5c0 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.Notifications.csproj
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.Notifications.csproj
@@ -84,11 +84,14 @@
App.xaml
+
+
+
MainPage.xaml
-
+
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.cs b/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.cs
deleted file mode 100644
index cc715f87f0..0000000000
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/Usergrid.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Net;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Json;
-using System.Text;
-using Newtonsoft.Json.Linq;
-using Newtonsoft.Json;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using Windows.Storage;
-using Windows.Networking.PushNotifications;
-
-namespace Usergrid.Notifications
-{
- public class Usergrid : UsergridHttpClient
- {
- private string url;
- private string token;
- private HttpClient client;
- private PushClient push;
- private string managementUrl;
-
- public Usergrid(string url, string org, string app)
- {
- string urlWithSlash = url.EndsWith("/",StringComparison.CurrentCulture) ? url : url+"/";
- this.url = String.Format("{0}{1}/{2}/", urlWithSlash, org, app);
- this.managementUrl = urlWithSlash + "management/";
- this.client = new HttpClient();
- push = new PushClient(this);
- }
-
- public async Task Authenticate(string user, string password, bool isManagement)
- {
- var url = "token";
- var jsonObject = new JObject();
- jsonObject.Add("username", user);
- jsonObject.Add("password", password);
- jsonObject.Add("grant_type", "password");
- HttpResponseMessage response = await SendAsync(HttpMethod.Post,url, jsonObject, isManagement);
-
- if (response.StatusCode == HttpStatusCode.OK)
- {
- JObject jsonResponse = await GetJsonResponse(response);
- this.token = jsonResponse.GetValue("access_token").Value();
- client.DefaultRequestHeaders.Add("X-Authorization", token);
- }
- else
- {
- throw new Exception("Authentication failed");
- }
- }
-
- public async Task GetJsonResponse(HttpResponseMessage response)
- {
- JObject jsonResponse = null;
- using (var stream = await response.Content.ReadAsStreamAsync())
- {
- using (var reader = new StreamReader(stream, Encoding.UTF8))
- {
- jsonResponse = JObject.Parse(reader.ReadToEnd());
- }
- }
- return jsonResponse;
- }
-
- private HttpContent getJsonBody(Object jsonObject)
- {
- var content = new StringContent(JsonConvert.SerializeObject(jsonObject));
- return content;
- }
- public Task SendAsync(HttpMethod method, string url, object obj)
- {
- return SendAsync(method, url, obj, false);
- }
- public Task SendAsync(HttpMethod method, string url, object obj, bool useManagementUrl)
- {
- HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, (useManagementUrl ? this.managementUrl : this.url) + url);
- if(obj!=null)
- message.Content = getJsonBody(obj);
- message.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue( "application/json"));
- return this.client.SendAsync(message);
-
- }
-
- public PushClient Push
- {
- get { return push; }
- }
-
-
- }
-
- public interface UsergridHttpClient
- {
- TaskSendAsync(HttpMethod method,string url, object obj);
- Task GetJsonResponse(HttpResponseMessage response);
-
- }
- public class PushClient
- {
- private UsergridHttpClient usergrid;
-
- public PushClient(UsergridHttpClient usergrid)
- {
- this.usergrid = usergrid;
- }
-
- public async Task SendNotification(string message)
- {
- if (DeviceId == null)
- {
- throw new Exception("Please call PushClient.RegisterDevice first.");
- }
- var jsonObject = new JObject();
- var payloads = new JObject();
- var payload = new JObject();
- payload.Add("toast", new JValue(message));
- payloads.Add("winphone", payload);
- jsonObject.Add("payloads",payloads);
- jsonObject.Add("debug", true);
- var response = await usergrid.SendAsync(HttpMethod.Post,String.Format("devices/{0}/notifications",deviceId), jsonObject);
- var status = response.StatusCode;
- JObject jsonResponse = await usergrid.GetJsonResponse(response);
- return (status == HttpStatusCode.OK);
- }
-
- public async Task RegisterDevice(string notifier)
- {
- this.Notifier = notifier;
- var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
- var settings = ApplicationData.Current.LocalSettings;
- if (!settings.Values.ContainsKey("currentDeviceId"))
- {
- Guid uuid = await registerDevice(notifier, channel.Uri);
- settings.Values.Add("currentDeviceId", uuid);
- this.DeviceId = uuid;
- }
- else
- {
- object tempId;
- settings.Values.TryGetValue("currentDeviceId", out tempId);
- this.DeviceId = Guid.Parse(tempId.ToString());
- if (!await DeviceExists(DeviceId))
- {
- Guid uuid = await registerDevice(notifier, channel.Uri);
- settings.Values["currentDeviceId"] = uuid;
- this.DeviceId = uuid;
- }
-
- }
-
-
- }
-
- public async Task AddNotifier(string name, string sid, string apiKey)
- {
- JObject obj = new JObject();
- obj.Add("name", new JValue(name));
- obj.Add("sid", new JValue(sid));
- obj.Add("provider", new JValue("windows"));
- obj.Add("apiKey", new JValue(apiKey));
- obj.Add("logging", new JValue(true));
- HttpResponseMessage response = await usergrid.SendAsync(HttpMethod.Post, "notifiers", obj);
-
- JObject jsonResponse = await usergrid.GetJsonResponse(response);
- if (jsonResponse != null)
- {
- var body = jsonResponse.GetValue("entities").ToString();
- }
- }
-
- public async Task DeviceExists(Guid deviceId)
- {
- HttpResponseMessage response = await usergrid.SendAsync(HttpMethod.Get, "devices/"+deviceId, null);
- JObject jsonResponse = await usergrid.GetJsonResponse(response);
- if (jsonResponse != null)
- {
- var body = jsonResponse.GetValue("entities");
- return body!=null && body.Value().Count > 0;
- }
- else { return false; }
- }
-
- private async Task registerDevice(string notifier, string uri)
- {
- JObject obj = new JObject();
- obj.Add(notifier + ".notifier.id", new JValue(uri));
- HttpResponseMessage response = await usergrid.SendAsync(HttpMethod.Post, "devices/", obj);
-
- JObject jsonResponse = await usergrid.GetJsonResponse(response);
-
- if (response.StatusCode == HttpStatusCode.OK && jsonResponse != null)
- {
- var entity = jsonResponse.GetValue("entities").Value()[0];
- var uuid = Guid.Parse(entity.Value("uuid"));
- return uuid;
- }
- else { return Guid.Empty; }
- }
-
- public string Notifier { get; set; }
- private Guid DeviceId { get; set; }
-
- }
-}
diff --git a/sdks/dotnet/samples/notifications/Usergrid.Notifications/packages.config b/sdks/dotnet/samples/notifications/Usergrid.Notifications/packages.config
index efaa424470..2a3ff3c3ae 100644
--- a/sdks/dotnet/samples/notifications/Usergrid.Notifications/packages.config
+++ b/sdks/dotnet/samples/notifications/Usergrid.Notifications/packages.config
@@ -1,4 +1,25 @@
+
\ No newline at end of file
diff --git a/sdks/dotnet/samples/notifications/packages/repositories.config b/sdks/dotnet/samples/notifications/packages/repositories.config
new file mode 100644
index 0000000000..deb999191a
--- /dev/null
+++ b/sdks/dotnet/samples/notifications/packages/repositories.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/stack/services/src/main/java/org/apache/usergrid/services/notifications/impl/ApplicationQueueManagerImpl.java b/stack/services/src/main/java/org/apache/usergrid/services/notifications/impl/ApplicationQueueManagerImpl.java
index c8c51659bf..8cc3450307 100644
--- a/stack/services/src/main/java/org/apache/usergrid/services/notifications/impl/ApplicationQueueManagerImpl.java
+++ b/stack/services/src/main/java/org/apache/usergrid/services/notifications/impl/ApplicationQueueManagerImpl.java
@@ -396,15 +396,19 @@ public void stop(){
/**
- * Call the adapter with the notifier
+ * Validates that a notifier and adapter exists to send notifications to;
+ * {"winphone":"mymessage","apple":"mymessage"}
+ * TODO: document this method better
*/
private Map translatePayloads(Map payloads, Map notifierMap) throws Exception {
Map translatedPayloads = new HashMap( payloads.size());
for (Map.Entry entry : payloads.entrySet()) {
String payloadKey = entry.getKey().toLowerCase();
Object payloadValue = entry.getValue();
+ //look for adapter from payload map
ProviderAdapter providerAdapter = notifierMap.get(payloadKey);
if (providerAdapter != null) {
+ //translate payload to usable information
Object translatedPayload = payloadValue != null ? providerAdapter.translatePayload(payloadValue) : null;
if (translatedPayload != null) {
translatedPayloads.put(payloadKey, translatedPayload);
@@ -520,4 +524,4 @@ private String getProviderId(EntityRef device, Notifier notifier) throws Excepti
}
-}
\ No newline at end of file
+}
diff --git a/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/TranslatedNotification.java b/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/TranslatedNotification.java
new file mode 100644
index 0000000000..9e702b763c
--- /dev/null
+++ b/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/TranslatedNotification.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * * Licensed to the Apache Software Foundation (ASF) under one or more
+ * * contributor license agreements. The ASF licenses this file to You
+ * * under the Apache License, Version 2.0 (the "License"); you may not
+ * * use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * *
+ * * http://www.apache.org/licenses/LICENSE-2.0
+ * *
+ * * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License. For additional information regarding
+ * * copyright in this work, please see the NOTICE file in the top level
+ * * directory of this distribution.
+ *
+ */
+
+package org.apache.usergrid.services.notifications.wns;
+
+import org.apache.usergrid.persistence.model.entity.Entity;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+/**
+ * Classy class class.
+ */
+public class TranslatedNotification extends HashMap implements Serializable {
+
+ public TranslatedNotification() {
+ super();
+ }
+
+ public TranslatedNotification(Object message, String type) {
+ super();
+ this.put("message",message);
+ this.put("type" , type);
+ }
+
+ public Object getMessage() {
+ return get("message");
+ }
+
+ public String getType() {
+ return get("type").toString();
+ }
+}
diff --git a/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/WNSAdapter.java b/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/WNSAdapter.java
index b331e86d1d..0ba2db3259 100644
--- a/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/WNSAdapter.java
+++ b/stack/services/src/main/java/org/apache/usergrid/services/notifications/wns/WNSAdapter.java
@@ -21,9 +21,11 @@
package org.apache.usergrid.services.notifications.wns;
import ar.com.fernandospr.wns.WnsService;
-import ar.com.fernandospr.wns.exceptions.WnsException;
+import ar.com.fernandospr.wns.model.WnsBadge;
import ar.com.fernandospr.wns.model.WnsToast;
+import ar.com.fernandospr.wns.model.builders.WnsBadgeBuilder;
import ar.com.fernandospr.wns.model.builders.WnsToastBuilder;
+import com.sun.jersey.api.client.ClientHandlerException;
import org.apache.usergrid.persistence.EntityManager;
import org.apache.usergrid.persistence.entities.Notification;
import org.apache.usergrid.persistence.entities.Notifier;
@@ -31,11 +33,11 @@
import org.apache.usergrid.services.notifications.ConnectionException;
import org.apache.usergrid.services.notifications.ProviderAdapter;
import org.apache.usergrid.services.notifications.TaskTracker;
-import org.mortbay.util.ajax.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
/**
@@ -59,17 +61,34 @@ public WNSAdapter(EntityManager entityManager, Notifier notifier) {
public void testConnection() throws ConnectionException {
WnsToast toast = new WnsToastBuilder().bindingTemplateToastText01("test").build();
try{
- service.pushToast("ms-app://s-1-15-2-2411381248-444863693-3819932088-4077691928-1194867744-112853457-373132695",toast);
- }catch (Exception e){
- LOG.error(e.toString());
+ //this fails every time due to jax error which is ok
+ service.pushToast("s-1-15-2-2411381248-444863693-3819932088-4077691928-1194867744-112853457-373132695",toast);
+ }catch (ClientHandlerException e){
+ LOG.info("Windows Phone notifier added: "+e.toString());
}
}
@Override
public void sendNotification(String providerId, Object payload, Notification notification, TaskTracker tracker) throws Exception {
try {
- WnsToast toast = new WnsToastBuilder().bindingTemplateToastText01(payload.toString()).build();
- service.pushToast(providerId, toast);
+ List translatedNotifications = ( List) payload;
+ for(TranslatedNotification translatedNotification : translatedNotifications) {
+ switch (translatedNotification.getType()) {
+ case "toast":
+ WnsToast toast = new WnsToastBuilder().bindingTemplateToastText01(translatedNotification.getMessage().toString()).build();
+ service.pushToast(providerId, toast);
+ break;
+ case "badge":
+ WnsBadge badge;
+ if (translatedNotification.getMessage() instanceof Integer) {
+ badge = new WnsBadgeBuilder().value((Integer) translatedNotification.getMessage()).build();
+ } else {
+ badge = new WnsBadgeBuilder().value(translatedNotification.getMessage().toString()).build();
+ }
+ service.pushBadge(providerId, badge);
+ break;
+ }
+ }
tracker.completed();
} catch (Exception e) {
tracker.failed(0,e.toString());
@@ -89,17 +108,28 @@ public void removeInactiveDevices() throws Exception {
@Override
public Object translatePayload(Object payload) throws Exception {
- String toast = "";
+ //TODO: allow for badges and toasts at same time
+ List translatedNotifications = new ArrayList<>();
if (payload instanceof Map) {
- toast = ((Map) payload).get("toast").toString();
+ //{payloads:{winphone:{toast:"mymessage",badge:1}}}
+ Map map = (Map) payload;
+ if (map.containsKey("toast")) {
+ translatedNotifications.add(new TranslatedNotification(map.get("toast").toString(), "toast"));
+ }
+ if (map.containsKey("badge")) {
+ translatedNotifications.add(new TranslatedNotification(map.get("badge"), "badge"));
+ }
+
} else {
+ //{payloads:{winphone:"mymessage"}}
+ //make it a toast if its just a string
if (payload instanceof String) {
- toast = (String) payload;
+ translatedNotifications.add(new TranslatedNotification( (String) payload,"toast"));
}else{
throw new IllegalArgumentException("format is messed up");
}
}
- return toast;
+ return translatedNotifications;
}
@Override
@@ -128,4 +158,5 @@ public Notifier getNotifier() {
return notifier;
}
+
}