android push notification using gcm - c#

I am developing wcf push notification service using google's GCM API. i created a service which sends to all the device which use my application but, i wanted to be specific to some device. i am thinking i have to use the token i get when i register for the GCM service. but i dont know where and how to implment it. most of the online posts are in PHP and i am kind of confused when i see the codes. Any one with C# implmentation advice or in general may be?
here is my code for all the devices:
public bool notify(string sender, string message)
{
var jGcmData = new JObject();
var jData = new JObject();
bool Value;
jData.Add("message", message);
jData.Add("name", sender);
jGcmData.Add("to", "/topics/global");
jGcmData.Add("data", jData);
var url = new Uri("https://gcm-http.googleapis.com/gcm/send");
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation(
"Authorization", "key=" + API_KEY);
Task.WaitAll(client.PostAsync(url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
Value = true;
}
catch (Exception e)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(e.StackTrace);
Value = false;
}
return Value;
}
thanks in advance!

1st of all I think you should not reinvent the wheel and include a Push messaging library to do all the redundant work.
I use PushSharp
Then everything is cake.
Declare the following handler class
Using the SendGCMNotification method just throw an object to serialize and a specific user's push messaging id .
public class PushNotificationHandler : IDisposable
{
private static readonly string googleApiKey;
private static PushBroker pushBrokerInstance;
static PushNotificationHandler()
{
googleApiKey = ConfigurationManager.AppSettings["GoogleAPIKey"].ToString();
pushBrokerInstance = new PushBroker();
pushBrokerInstance.RegisterGcmService(new GcmPushChannelSettings(googleApiKey));
}
public static void SendGCMNotification(Notification messageObj, String CloudMessagingId)
{
String Content = Newtonsoft.Json.JsonConvert.SerializeObject(messageObj);
pushBrokerInstance.QueueNotification(new GcmNotification().ForDeviceRegistrationId(CloudMessagingId).WithJson(Content));
}
}

Related

Conversation always restarts in Directline BOT channel websocket, how to keep it flowing?

I have built an app that needs to connect to a Bot DirectLine - websockets channel to interact in conversations via LUIS and sms with Twilio.
To make the bot talk to the app I wrote a mvc controller that relays messages.
I am not sure this approach is correct, I made it up from some samples.
It works, but the main problem is that my code seems to always start a new conversation when a message is received from the client, so the context is not maintained.
How can I keep the conversation flowing and not restarting at every message?
I mean, the steps should be, for example:
Bot: Hello, what's your name?
User: Carl
Bot: Pleased to meet you Carl!
instead I get:
Bot: Hello, what's your name?
User: Carl
Bot: Sorry, I can't help you with that.
like the conversation is restarted from scratch.
Here is my controller code (the Twilio webhook is set to https://mySmsMVCapp.azurewebsites.net/smsapp/):
public class smsappController : TwilioController
{
private static string directLineSecret = ConfigurationManager.AppSettings["DirectLineSecret"];
private static string botId = ConfigurationManager.AppSettings["BotId"];
const string accountSid = "obfuscated";
const string authToken = "obfuscated";
private static string fromUser = "DirectLineSampleClientUser";
private string SMSreply = "";
public async Task<TwiMLResult> Index(SmsRequest incomingMessage)
{
// Obtain a token using the Direct Line secret
var tokenResponse = await new DirectLineClient(directLineSecret).Tokens.GenerateTokenForNewConversationAsync();
// Use token to create conversation
var directLineClient = new DirectLineClient(tokenResponse.Token);
var conversation = await directLineClient.Conversations.StartConversationAsync();
using (var webSocketClient = new WebSocket(conversation.StreamUrl))
{
webSocketClient.OnMessage += WebSocketClient_OnMessage;
// You have to specify TLS version to 1.2 or connection will be failed in handshake.
webSocketClient.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12;
webSocketClient.Connect();
while (true)
{
string input = incomingMessage.Body;
if (!string.IsNullOrEmpty(input))
{
if (input.ToLower() == "exit")
{
break;
}
else
{
if (input.Length > 0)
{
Activity userMessage = new Activity
{
From = new ChannelAccount(fromUser),
Text = input,
Type = ActivityTypes.Message
};
await directLineClient.Conversations.PostActivityAsync(conversation.ConversationId, userMessage);
//break;
if (!string.IsNullOrEmpty(SMSreply))
{
var messagingResponse = new MessagingResponse();
var message = messagingResponse.AddChild("Message");
message.AddText(SMSreply); //send text
SMSreply = string.Empty;
return TwiML(messagingResponse);
}
}
}
}
}
}
return null;
}
private void WebSocketClient_OnMessage(object sender, MessageEventArgs e)
{
// Occasionally, the Direct Line service sends an empty message as a liveness ping. Ignore these messages.
if (!string.IsNullOrWhiteSpace(e.Data))
{
var activitySet = JsonConvert.DeserializeObject<ActivitySet>(e.Data);
var activities = from x in activitySet.Activities
where x.From.Id == botId
select x;
foreach (Activity activity in activities)
{
if (!string.IsNullOrEmpty(activity.Text))
{
SMSreply = activity.Text;
}
}
}
}
}
The issue was actually I wasn't saving and retrieving conversationID.
For the moment I am testing using a static variable to store the value.
Then I reconnect to the conversation with it and the conversation with the bot keeps in context.

Lambda Function using c# cannot invoke external HTTPS APIs

I am trying to invoke External APIs from AWS lambda function written in c#. The Lamda function is deployed in No VPC mode. I am calling this function from Alexa skill. The code works fine for an http request, but its not working for https.
The below code works when I use http://www.google.com.
But, if I replace http with https, then I get the error in the cloud watch saying:
"Process exited before completing request."
Even the log written in catch is not getting logged in cloud watch.
public class Function
{
public const string INVOCATION_NAME = "bingo";
public async Task<SkillResponse> FunctionHandler(SkillRequest input, ILambdaContext context)
{
var requestType = input.GetRequestType();
if (requestType == typeof(IntentRequest))
{
string response = "";
IntentRequest request = input.Request as IntentRequest;
response += $"About {request.Intent.Slots["carmodel"].Value}";
try
{
using (var httpClient = new HttpClient())
{
Console.WriteLine("Trying to access internet");
//var resp=httpClient.GetAsync("http://www.google.com").Result // this works perfect!
var resp = httpClient.GetAsync("https://www.google.com").Result; // this throws error
Console.WriteLine("Call was successful");
}
}
catch (Exception ex)
{
Console.WriteLine("Exception from main function " + ex.Message);
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.StackTrace);
}
return MakeSkillResponse(response, true);
}
else
{
return MakeSkillResponse(
$"I don't know how to handle this intent. Please say something like Alexa, ask {INVOCATION_NAME} about Tesla.",
true);
}
}
private SkillResponse MakeSkillResponse(string outputSpeech, bool shouldEndSession,
string repromptText = "Just say, tell me about car models to learn more. To exit, say, exit.")
{
var response = new ResponseBody
{
ShouldEndSession = shouldEndSession,
OutputSpeech = new PlainTextOutputSpeech { Text = outputSpeech }
};
if (repromptText != null)
{
response.Reprompt = new Reprompt() { OutputSpeech = new PlainTextOutputSpeech() { Text = repromptText } };
}
var skillResponse = new SkillResponse
{
Response = response,
Version = "1.0"
};
return skillResponse;
}
}
The issue was resolved by updating the library version.
System.Net.Http v4.3.4 was not completely compatible with dotnet core v1.
So outbound http calls were working but not https calls. Changing the version of System.net.http resolved the issue.

Can't receive any notification from AmazonSNS

I am not sure why I can't receive any notification from AmazonSNS. Am I missing something in my code? I am using the latest version of AWSSDK for Windows Store App by the way.
Here's my code so far.
d("init AmazonSimpleNotificationServiceClient");
AmazonSimpleNotificationServiceClient sns = new AmazonSimpleNotificationServiceClient("secret", "secret", RegionEndpoint.EUWest1);
d("get notification channel uri");
string channel = string.Empty;
var channelOperation = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
channelOperation.PushNotificationReceived += ChannelOperation_PushNotificationReceived;
d("creating platform endpoint request");
CreatePlatformEndpointRequest epReq = new CreatePlatformEndpointRequest();
epReq.PlatformApplicationArn = "arn:aws:sns:eu-west-1:X413XXXX310X:app/WNS/Device";
d("token: " + channelOperation.Uri.ToString());
epReq.Token = channelOperation.Uri.ToString();
d("creat plateform endpoint");
CreatePlatformEndpointResponse epRes = await sns.CreatePlatformEndpointAsync(epReq);
d("endpoint arn: " + epRes.EndpointArn);
d("subscribe to topic");
SubscribeResponse subsResp = await sns.SubscribeAsync(new SubscribeRequest()
{
TopicArn = "arn:aws:sns:eu-west-1:X413XXXX310X:Topic",
Protocol = "application",
Endpoint = epRes.EndpointArn
});
private void ChannelOperation_PushNotificationReceived(Windows.Networking.PushNotifications.PushNotificationChannel sender, Windows.Networking.PushNotifications.PushNotificationReceivedEventArgs args)
{
Debug.WriteLine("receiving something");
}
this is actually working after enabling Toast on .appxmanifest
I get notified everytime I publish a RAW message from Amazon SNS console. I am not receiving a JSON though which I actually need.

How to implement HttpGet for android client?

I am developing client-server application. The server side is asp.net web api. I did simple web api application and simple android client. When I set up web api it works. And I get json. But how I can get data from my clietn application? I conncted my Android-device and trying to get data via WI-FI from my web api. For web api I create a seld hosting.
protected Boolean doInBackground(String... urls) {
BufferedReader in = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://124.18.240.169:3890/api/values/1/");
HttpResponse response = client.execute(request);
in = new BufferedReader(
new InputStreamReader(
response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null) {
sb.append(line + NL);
}
in.close();
String page = sb.toString();
System.out.println(page);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
It is my web api
static void Main(string[] args)
{
var config = new HttpSelfHostConfiguration("http://124.18.240.169:3890");
config.Routes.MapHttpRoute(
"API Default", "api/{controller}/{id}",
new { id = RouteParameter.Optional });
using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
server.OpenAsync().Wait();
Console.WriteLine("Press Enter to quit.");
Console.ReadLine();
}
}
where
124.18.240.160 is my IP whcih i found in ipconfig. What I should to do (I tried to do like
http://localhost) but it not wrok for Android app
You should consider using a library to help handle async callbacks. It can be super helpful for this.
This is the one I usually use:
LoopJ's Async HTTP Callback Library
This will handle GET and POST requests with a lot of cool features such as custom timeouts, JSON format, onSuccess() and onFailure() methods, etc. There's a lot of working examples of this library too. I've used it in all my apps and haven't had any problems yet!
Hopefully this helps.

Office 365 REST API - Adding a Contact with JSON in C#

I am trying to use the Office API to sync contacts from a few different sources. I have been having a problem trying to make a POST request with my JSON object to create a new contact. I have been looking at the MSDN pages but I feel like I should clarify I’m relatively new to C#, this is my first time trying to use REST protocols, and async methods in C#.
I have my code below, I tried to create a class that will add a new contact with a hard coded JSON string. I have tried a few various ways of trying to complete this request. Every request I have attempted gives me a 401 or 400 Error. I left a couple lines that I felt were closest to the solution but if those are not on the right track I have no problem trying something else. There is also a function that I believe could be useful but I couldn’t really find documentation on how to use it:
await client.Me.Contacts.AddContactAsync();
Again I said I am pretty new to this so if there is a way to create an IContact item from the JSON and use the above method or to just pass the JSON directly either would be extremely useful. Even links to documentation that could be useful I would love to see. I’m a pretty stuck on this problem I’ve never posted a question before but I’m stumped on this.
Below is the documentation for the Contacts API maybe it will make more sense to you guys than me.
http://msdn.microsoft.com/en-us/library/office/dn792115(v=office.15).aspx
If anybody can figure out how to make a post request from that JSON it will be much appreciated.
using Microsoft.Office365.Exchange;
using Microsoft.Office365.OAuth;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Windows;
using System.Net.Http;
using System.Net.Http.Headers;
namespace ContactSynchronization
{
class OfficeAPIWrite
{
private static string odata = "#odata.type";
private static string type = "#Microsoft.Exchange.Services.OData.Model.Contact";
const string ServiceResourceId = "https://outlook.office365.com";
static readonly Uri ServiceEndpointUri = new Uri("https://outlook.office365.com/ews/odata/Me/Contacts");
static string _lastLoggedInUser;
static DiscoveryContext _discoveryContext;
public static async Task OfficeWrite()
{
try
{
var client = await EnsureClientCreated();
string json = new JavaScriptSerializer().Serialize(new
{
odata = type,
GivenName = "Mara",
Surname = "Whitley",
EmailAddress1 = "mara#fabrikam.com",
BusinessPhone1 = "425-555-1313",
Birthday = "1974-07-22T07:00:00Z"
});
try
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, ServiceEndpointUri);
request.Content = new StringContent(json);
request.Headers.Add("Accept", "application/json;odata=minimalmetadata");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}
catch (System.Net.WebException e)
{
MessageBox.Show(e.ToString());
}
}
catch (Microsoft.Office365.OAuth.AuthenticationFailedException)
{
MessageBox.Show("Authentication Failed Exception was thrown");
}
}
public static async Task<ExchangeClient> EnsureClientCreated()
{
if (_discoveryContext == null)
{
_discoveryContext = await DiscoveryContext.CreateAsync();
}
var dcr = await _discoveryContext.DiscoverResourceAsync(ServiceResourceId);
_lastLoggedInUser = dcr.UserId;
return new ExchangeClient(ServiceEndpointUri, async () =>
{
return (await _discoveryContext.AuthenticationContext.AcquireTokenSilentAsync(ServiceResourceId, _discoveryContext.AppIdentity.ClientId, new Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier(dcr.UserId, Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifierType.UniqueId))).AccessToken;
});
}
public static async Task SignOut()
{
if (string.IsNullOrEmpty(_lastLoggedInUser))
{
return;
}
if (_discoveryContext == null)
{
_discoveryContext = await DiscoveryContext.CreateAsync();
}
await _discoveryContext.LogoutAsync(_lastLoggedInUser);
}
}
}
Well I guess I figured out a work around. This uses a ContactObject that I created and newtonsoft's JSON serializer. I was hoping to see an example of the microsoft ExchangeClient in action, the only reason I am posting this is to help others that might have similar issues posting to the office API, the below code will run successfully. I'm still looking though if anybody can show me the correct way to use the ExchangeClient functions.
// your request must include these, and a given name,
// everything else is optional
private const string odata = "#odata.type";
private const string type = "#Microsoft.Exchange.Services.OData.Model.Contact";
public static async Task CreateContact(ContactObject officeContact, string userEmail, string userPassword)
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, new Uri("https://outlook.office365.com/ews/odata/Me/Contacts"));
// Add the Authorization header with the basic login credentials.
var auth = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(userEmail + ":" + userPassword));
request.Headers.Add("Accept", "application/json");
request.Headers.Add("Authorization", auth);
var createResponse = new JObject();
createResponse[odata] = type; // this needs to be here for this to work
if (!String.IsNullOrEmpty(officeContact.officeDisplayName)) createResponse["DisplayName"] = officeContact.officeDisplayName;
if (!String.IsNullOrEmpty(officeContact.officeGivenName)) createResponse["GivenName"] = officeContact.officeGivenName;
if (!String.IsNullOrEmpty(officeContact.officeMiddleName)) createResponse["MiddleName"] = officeContact.officeMiddleName;
if (!String.IsNullOrEmpty(officeContact.officeNickName)) createResponse["NickName"] = officeContact.officeNickName;
if (!String.IsNullOrEmpty(officeContact.officeSurname)) createResponse["Surname"] = officeContact.officeSurname;
if (!String.IsNullOrEmpty(officeContact.officeEmailAddress1)) createResponse["EmailAddress1"] = officeContact.officeEmailAddress1;
if (!String.IsNullOrEmpty(officeContact.officeEmailAddress2)) createResponse["EmailAddress2"] = officeContact.officeEmailAddress2;
if (!String.IsNullOrEmpty(officeContact.officeEmailAddress3)) createResponse["EmailAddress3"] = officeContact.officeEmailAddress3;
if (!String.IsNullOrEmpty(officeContact.officeHomePhone1)) createResponse["HomePhone1"] = officeContact.officeHomePhone1;
if (!String.IsNullOrEmpty(officeContact.officeHomePhone2)) createResponse["HomePhone2"] = officeContact.officeHomePhone2;
if (!String.IsNullOrEmpty(officeContact.officeBusinessPhone1)) createResponse["BusinessPhone1"] = officeContact.officeBusinessPhone1;
if (!String.IsNullOrEmpty(officeContact.officeBusinessPhone2)) createResponse["BusinessPhone2"] = officeContact.officeBusinessPhone2;
if (!String.IsNullOrEmpty(officeContact.officeMobilePhone1)) createResponse["MobilePhone1"] = officeContact.officeMobilePhone1;
if (!String.IsNullOrEmpty(officeContact.officeOtherPhone)) createResponse["OtherPhone"] = officeContact.officeOtherPhone;
if (!String.IsNullOrEmpty(officeContact.officeId)) createResponse["Id"] = officeContact.officeId;
if (!String.IsNullOrEmpty(officeContact.officeCompanyName)) createResponse["CompanyName"] = officeContact.officeCompanyName;
request.Content = new StringContent(JsonConvert.SerializeObject(createResponse));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = await client.SendAsync(request);
try
{
response.EnsureSuccessStatusCode();
}
catch (System.Net.WebException)
{
MessageBox.Show("BAD REQUEST");
}
}

Categories

Resources