I am developing a windows phone application and I could send a message to another windows phone device based on that device's channel uri.
public static HttpNotificationChannel pushChannel;
App.pushChannel = new HttpNotificationChannel(channelName);
App.pushChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(PushChannel_ShellToastNotificationReceived);
void PushChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
{
//TODO:
}
I have below questions related to the above code:
How do I read the channelUri of the sender so that I can reply to the sender ? I see it is available in sender -> ChannelUri- > AbsoluteUri
And if sender wants to send more parameters can we add more toast xml tags apart from wp:Text1 and wp:Text2 or do we need to make use of wp:param only?
In scenario like Chat application should my code first store the channeluri of every device in some database and then when it wants to send a message to a particular user/device, it should read that particular user's channeluri based on his id or emailid ? Any other suggestion in this point on how to maintain users info for exchanging the messages ?
1.
You don't get the channel Uri, because they are not build for direct device to device communication. You have to transmit them by yourself.
2.
In a toast notification you only have these params available.
3.
Your application probably won't work without an extra server that manages the device/user/channel ids. Push Notifications are not made for direct device to device communication.
ChannelUris may change at any time, so your app has to send it to your server from time to time (recommended is on every start).
Also, notifications have a very limited payload, so you need to transfer the complete messages and user data on another way.
Related
We've been trying to get iOS push notifications to work but it's been very inconsistent. We've created a test project with as little code as possible just to get notifications to work.
We decided to test with alert notifications since we couldn't even get that to work consistently.
This is what we've been doing in the FinishedLaunching method of the AppDelegate:
UNUserNotificationCenter.Current.Delegate = this;
var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
{
LogInformation("RequestAuthorization", $"Granted: {granted}, Error: {error}");
if (granted)
InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications);
});
And we log the registration token of the device in the console so that we can use that to send notifications.
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
LogInformation("RegisteredForRemoteNotifications", "init");
var token = ExtractToken(deviceToken);
LogInformation("RegisteredForRemoteNotifications", token);
}
That's basically all we have in the app for now.
We use the notification token in a test app to send notifications to that specific device.
These are our results:
Use case 1
Restart device
Send notification to device
Result: Notification shows up and all new notifications keep working too.
Use case 2
Restart device
Send notification to device
Result: Notification is not shown and no matter how often you send the notification, it won't be shown.
Use case 3
Restart device
Send notification to device
Notification is not shown.
Restart device
Result: Notification shows up and all new notifications keep working too.
Use case 4
Restart device
Start application once
Put app in background, or close it completely
Send notification to device
Result: Notification is shown and all new notifications keep working too.
So it looks like that once we receive 1 notification, all future notifications will work too up until the device is restarted.
After restarting the device, it's basically a coinflip: You either are lucky and receive a notification and all future notifications. Or you don't receive anything at all.
We want to receive notifications consistently and are trying to figure out how to get this done and we hope someone can shed some light into this matter.
Thanks in advance.
Notes
We're using a 6th gen iPad with iOS 13.5.1
iPad is WiFi only
We've got a stable WiFi and internet connection
I'm writing a program in C# to get the system's public IP and inform the user of the new one if it changes. The problem is I have two ways of informing the user: Email or Cortana. For the first one (Email) I need an anonymous email sender that I don't have, or ask the user to provide his/her credentials (most people won't). Second way (Cortana): Let's say I have the program installed on my home PC and I have Cortana enabled on Windows 10 and a Windows Phone with Cortana. If my home PC's public IP address changed, Cortana will show a notification on my phone including my new IP address.
I saw an API on github (that can't do this) and Cortana for developers. I thought "actions" can do the job but after reading the descriptions I'm somehow sure that it can't.
How can I do that?
What I did:
I wrote a little program for Windows 10
https://www.microsoft.com/en-us/store/apps/remotecmd/9nblggh4vr31
and the server side app
http://naryhd.com/RemoteCMDServerBETA.zip
This app lets you have your PC's cmd on your windows phone. (locally)
Now I want to add "access from internet" to it, (I did that, but for security reasons I disabled it, now I got a more secure solution for it)
There are 3 things that I do for accessing it from the internet
Command 1:
netsh http add urlacl url=http://ip:port/ user=everyone
Command 2:
netsh advfirewall firewall add rule name=\"RemoteCMDserver2\" dir=in protocol=tcp localport=port profile=public | private remoteip=localsubnet action=allow
Forwarding that port:
var discoverer = new NatDiscoverer();
var cts = new System.Threading.CancellationTokenSource(10000);
var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port, "REMOTECMD"));
I used open.nat from nuget to do port forwarding.
I use this code to get the PC's public IP:
var discoverer = new NatDiscoverer();
var device = await discoverer.DiscoverDeviceAsync();
var ip = await device.GetExternalIPAsync();
I save that IP in a text file, and repeat checking it every minute, and if it changes it will save that IP and send that IP to the user (currently via email) but I would like to send it with Cortana.
You can't do that with Cortana, as of right now. You can have a App, on the Phone, that displays a push Notification in the Action Center or on a Live Tile.
Here is some hopefully useful links:
Toast Notification and Action Center Overview for Windows 10
Inside Windows Platform | How to Add Push Notifications to Your App
I am building a c#/wpf project.
It's architecture is this:
A console application which will be on a virtual machine (or my home computer) that will be the server side.
A wpf application that will be the client app.
Now my problem is this - I want the server to be able to send changes to the clients. If for example I have a change for client ABC, I want the server to know how to call a service on the clients computer.
The problem is, that I don't know how the server will call the clients.
A small example in case I didn't explain it well:
The server is on computer 1, and there are two clients, on computers 2 and 3.
Client 2 has a Toyota car and client 3 has a BMW car.
The server on computer 1 wants to tell client 2 that it has a new car, an Avenger.
How do I keep track and call services on the clients?
I thought of saving their ip address (from calling ipconfig from the cmd) in the DB - but isn't that based on the WI-FI/network they are connected to?
Thanks for any help!
You could try implementing SignalR. It is a great library that uses web sockets to push data to clients.
Edit:
SignalR can help you solve your problem by allowing you to set up Hubs on your console app (server) that WPF application (clients) can connect to. When the clients start up you will register them with a specified Hub. When something changes on the server, you can push from the server Hub to the client. The client will receive the information from the server and allow you to handle it as you see fit.
Rough mockup of some code:
namepsace Server{}
public class YourHub : Hub {
public void SomeHubMethod(string userName) {
//clientMethodToCall is a method in the WPF application that
//will be called. Client needs to be registered to hub first.
Clients.User(userName).clientMethodToCall("This is a test.");
//One issue you may face is mapping client connections.
//There are a couple different ways/methodologies to do this.
//Just figure what will work best for you.
}
}
}
namespace Client{
public class HubService{
public IHubProxy CreateHubProxy(){
var hubConnection = new HubConnection("http://serverAddress:serverPort/");
IHubProxy yourHubProxy = hubConnection.CreateHubProxy("YourHub");
return yourHubProxy;
}
}
}
Then in your WPF window:
var hubService = new HubService();
var yourHubProxy = hubService.CreateHubProxy();
yourHubProxy.Start().Wait();
yourHubProxy.On("clientMethodToCall", () => DoSometingWithServerData());
You need to create some kind of subscription model for the clients to the server to handle a Publish-Subscribe channel (see http://www.enterpriseintegrationpatterns.com/patterns/messaging/PublishSubscribeChannel.html). The basic architecture is this:
Client sends a request to the messaging channel to register itself as a subscriber to a certain kind of message/event/etc.
Server sends messages to the channel to be delivered to subscribers to that message.
There are many ways to handle this. You could use some of the Azure services (like Event hub, or Topic) if you don't want to reinvent the wheel here. You could also have your server application track all of these things (updates to IP addresses, updates to subscription interest, making sure that messages don't get sent more than once; taking care of message durability [making sure messages get delivered even if the client is offline when the message gets created]).
In general, whatever solution you choose is plagued with a common problem - clients hide behind firewalls and have dynamic IP addresses. This makes it difficult (I've heard of technologies claiming to overcome this but haven't seen any in action) for a server to push to a client.
In reality, the client talks and the server listens and response. However, you can use this approach to simulate a push by;
1. polling (the client periodically asks for information)
2. long polling (the client asks for information and the server holds onto the request until information arrives or a timeout occurs)
3. sockets (the client requests server connection that is used for bi-directional communication for a period of time).
Knowing those terms, your next choice is to write your own or use a third-party service (azure, amazon, other) to deliver messages for you. I personally like long polling because it is easy to implement. In my application, I have the following setup.
A web API server on Azure with and endpoint that listens for message requests
A simple loop inside the server code that checks the database for new messages every 100ms.
A client that calls the API, handling the response.
As mentioned, there are many ways to do this. In your particular case, one way would be as follows.
Client A calls server API to listen for message
Server holds onto call, waiting for new message entry in database
Client B calls server API to post new message
Server saves message to database
Server instance from step 2 sees new message
Server returns message to Client A.
Also, the message doesn't have to be stored in a database - it just depends on your needs.
Sounds like you want to track users à la https://www.simple-talk.com/dotnet/asp.net/tracking-online-users-with-signalr/ , but in a desktop app in the sense of http://www.codeproject.com/Articles/804770/Implementing-SignalR-in-Desktop-Applications or damienbod.wordpress.com/2013/11/20/signalr-a-complete-wpf-client-using-mvvm/ .
I am working with Cisco phones and i want to send them alert messages.
I do this by posting the following to the phone
"<CiscoIPPhoneExecute><ExecuteItem URL=\"Play:chime.raw\"/><ExecuteItem Priority=\"0\" URL=MY GET MESSAGE URL></CiscoIPPhoneExecute>";
My HTTP server then responds with a CiscoIPPhoneText xml object.
This is all working fine, however it is my desire not to have the messages stacking up on top of each other so that the user does not have to dismiss each message individually. I wish only for the most recent message to remain active on the phone so regardless of how many messages the phone has received the user can dismiss one and be returned home.
At first i included an init:services uri in the post but this caused a conflict with another service and my CiscoIPPhoneText was being dismissed immediately by the other service (i have no control over the other service).
Is there a way to return the phone to the home screen before an CiscoIPPhoneText is displayed or any other way to ensure that only one message is active?
Thanks
I found the answer
App:Close:0 is an internal URI which closes the current (or specified) application.
All my messages have the same AppId so when this URI is invoked all my messages close
I'm working on a project which receive notification from GCM server.
I've got the registration ID from GCM server and i send it to my server application which save it in the database.
My device receive the message but when I try to send another one, the precedent is replaced.
I know that we've 2 types of message:
Collapsible "send to sync"
Non-Collapsible
So without changing the name of the message, how can I get two message send at different time?
UPDATE 1:
When my device is offline (for example airport mode activated), I try
to send for example 2 messages from my application server to Google
server (I read that Google stores all the messages). But when I
desactivate this mode, I receive only the last message sent.
I use different collapse_key for different message and I receive all
of them (of course when the device online).
Is anybody knows how can I fix this?
The collapse key is relevant only to messages that were sent to the GCM server but haven't reached the destination device yet (if more than one such message has the same collapse key, only one of them will be sent to the device when it becomes online).
In your question you describe a different situation - the first message is received by the device and then the second message is received by the device and replaces the original message. That has nothing to do with GCM. It has to do with the way your application handles the received messages. For example, if your application code that receives the message displays is as a notification, it's up to you to decide whether a new message will override the existing notification or create a new notification.
You need to make sure that the value of the 'collapse_key' field in each message is different