I'm trying to get a raw push notification to work from Azure Mobile Services to Windows Phone 8.
I've only signed up with Windows Azure for the free mobile services which comes with the free 20mb database and free mobile services.
The site to manage Windows Azure services has a link to an example of how to send a push notification to an app to update a flip tile which can be found here.
On insert into a table a script runs which sends the notification.
There's another example on MSDN which provides an example of how to create an ASP page that sends a raw notification to a WP8 app. That example is here.
I've gotten both examples to work but I need the first example to send a raw notification instead so the code in the second example works.
This is the code I have:
In my Windows Phone 8 app I have this to receive notifications, in App.xaml.cs:
private void AcquirePushChannel()
{
/// Holds the push channel that is created or found.
HttpNotificationChannel pushChannel;
// The name of our push channel.
string channelName = "RawSampleChannel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
pushChannel.Open();
}
else
{
// The channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
//MessageBox.Show(String.Format("Channel Uri is {0}",
// pushChannel.ChannelUri.ToString()));
}
}
void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
MessageBox.Show(String.Format("Channel Uri is {0}",
e.ChannelUri.ToString()));
});
}
void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
// Error handling logic for your particular application would be here.
Deployment.Current.Dispatcher.BeginInvoke(() =>
MessageBox.Show(String.Format("A push notification {0} error occurred. {1} ({2}) {3}",
e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData))
);
}
/// <summary>
/// Event handler for when a raw notification arrives. For this sample, the raw
/// data is simply displayed in a MessageBox.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
string message;
using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
{
message = reader.ReadToEnd();
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
MessageBox.Show(String.Format("Received Notification {0}:\n{1}",
DateTime.Now.ToShortTimeString(), message))
);
}
In Application Launching it calls AcquirePushChannel:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
AcquirePushChannel();
}
My issue is in my Windows Azure Mobile Services database, where I have the following code on insert to a table to send the raw push notification, which doesn't work:
function insert(item, user, request) {
request.execute({
success: function () {
// Write to the response and then send the notification in the background
request.respond();
// for testing I'm manually putting in the channel ID where it says <channelID> below
push.mpns.sendRaw(<channelID>,
'test', {
success: function (pushResponse) {
console.log("Sent push:", pushResponse);
}
});
}
});
}
There is doc on this here, so I'm sure it's correct, but it just doesn't work.
And there's an example here.
One other question is, how can I view console.log via Windows Azure?
I was able to find out from the logs that my code wasn't sending the notification and worked out that it was my method of testing which was causing it and so I've fixed it. I've found out that the insert script only fires when I use the code:
private MobileServiceCollection<TodoItem, TodoItem> items;
private IMobileServiceTable<TodoItem> todoTable = App.MobileService.GetTable<TodoItem>();
private async void InsertTodoItem(TodoItem todoItem)
{
// This code inserts a new TodoItem into the database. When the operation completes
// and Mobile Services has assigned an Id, the item is added to the CollectionView
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
}
The insert script for example doesn't run if you use Management Studio and insert a row manually.
Related
I have been working on a location-oriented project that I need to be able to track a user's location while the app is terminated.
I have a background service in my Android project and the Geolocator Plugin.
Just for reference, here are my Geolocator settings:
App.xaml.cs
public static async void StartListening()
{
if (CrossGeolocator.Current.IsListening)
return;
CrossGeolocator.Current.DesiredAccuracy = 10;
await CrossGeolocator.Current.StartListeningAsync(TimeSpan.FromSeconds(LOCATION_PING_SECONDS), 1, true, new Plugin.Geolocator.Abstractions.ListenerSettings
{
AllowBackgroundUpdates = true,
PauseLocationUpdatesAutomatically = false
});
CrossGeolocator.Current.PositionChanged += PositionChanged;
CrossGeolocator.Current.PositionError += PositionError;
}
This + my location service for Android work like a charm while the app is running and backgrounded, but obviously everything stops when the app is terminated.
Android/MainActivity.cs
public void StartLocationService()
{
powerManager = (PowerManager) GetSystemService(PowerService);
wakeLock = powerManager.NewWakeLock(WakeLockFlags.Full, "LocationHelper");
// create a new service connection so we can get a binder to the service
locationServiceConnection = new LocationServiceConnection(null);
// this event will fire when the Service connectin in the OnServiceConnected call
locationServiceConnection.ServiceConnected += (object sender, ServiceConnectedEventArgs e) => {
Console.WriteLine("Service Connected");
};
// Starting a service like this is blocking, so we want to do it on a background thread
new Task(() => {
// Start our main service
Console.WriteLine("App", "Calling StartService");
Android.App.Application.Context.StartService(new Intent(Android.App.Application.Context, typeof(LocationService)));
// bind our service (Android goes and finds the running service by type, and puts a reference
// on the binder to that service)
// The Intent tells the OS where to find our Service (the Context) and the Type of Service
// we're looking for (LocationService)
Intent locationServiceIntent = new Intent(Android.App.Application.Context, typeof(LocationService));
Console.WriteLine("App", "Calling service binding");
// Finally, we can bind to the Service using our Intent and the ServiceConnection we
// created in a previous step.
Android.App.Application.Context.BindService(locationServiceIntent, locationServiceConnection, Bind.AutoCreate);
}).Start();
Console.WriteLine("Aquiring Wake Lock");
wakeLock.Acquire();
}
Does anyone know of any tutorials for getting location updates even when the app is terminated? Is this even possible?
Thanks!
Also, I found this Xamarin forum post... The last post says he is able to get updates while the app is terminated from a service, but I have not been able to get the same outcome.
I'm developing a c# desktop api with forms where I want to receive ACC data from a BLE server und display them in a chart.
So I'm running in a connection problem and I can't find any solution.
I can find my LE server Device with the watcher.
DevicePairingResult dpr = await device.DeviceInformation.Pairing.PairAsync(DevicePairingProtectionLevel.Encryption);
returns me "AlreadyPaired"
But when I do
device = await BluetoothLEDevice.FromBluetoothAddressAsync(bluetoothAddress: eventArgs.BluetoothAddress);
mGattService = device.GetGattService(MotionService_GUID);
mCharacteristic = mGattService.GetCharacteristics(ACC_Characteristic_GUID)[0];
and then
var con = device.ConnectionStatus;
I receive "Disconnected" in con.
I am bound with de device on windows( I searched for it in Windows and entered the Code) but I am not connected(based on the Status in the windows info center).
I've read in another Thread in the windows c# developer page that it should not be necessary anymore to pair the device manually.
I'm pretty shure that the rest of my code works because sometimes I can get a connection( pretty confusing for me) and see the right Data in my chart.
Right now I just want to reach a stable connection before changing other part of my code.
Anyone any idea how to solve this?
Thx medTech
Edit:
Here is part of the Code:
Scanning for BLE
private void button1_Click(object sender, EventArgs e)
{
// Create Bluetooth Listener
var watcher = new BluetoothLEAdvertisementWatcher();
watcher.ScanningMode = BluetoothLEScanningMode.Active;
// Register callback for when we see an advertisements
watcher.Received += OnAdvertisementReceivedAsync;
// Wait 5 seconds to make sure the device is really out of range
watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(5000);
watcher.SignalStrengthFilter.SamplingInterval = TimeSpan.FromMilliseconds(2000);
// Starting watching for advertisements
watcher.Start();
}
Connect to Server:
private async void OnAdvertisementReceivedAsync(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
{
// Filter for specific Device
if (eventArgs.Advertisement.LocalName == "MYDEVICE")
{
watcher.Stop();
var MotionService_GUID = new Guid("00002000-0000-1000-8000-00805F9B34FB");
var ACC_Characteristic_GUID = new Guid("00002001-0000-1000-8000-00805F9B34FB");
device = await BluetoothLEDevice.FromBluetoothAddressAsync(bluetoothAddress: eventArgs.BluetoothAddress);
DevicePairingResult dpr = await device.DeviceInformation.Pairing.PairAsync(DevicePairingProtectionLevel.Encryption);
mGattService = device.GetGattService(MotionService_GUID);
mCharacteristic = mGattService.GetCharacteristics(ACC_Characteristic_GUID)[0];
GattDeviceServicesResult result = await device.GetGattServicesAsync();
GattCommunicationStatus status1 = await ReadFromCharacteristicAsync(mCharacteristic);
var con = device.ConnectionStatus;
while (status1 == GattCommunicationStatus.Success)
{
try
{
status1 = await ReadFromCharacteristicAsync(mCharacteristic);
}
catch
{
Console.WriteLine("ERROR");
status1 = GattCommunicationStatus.Unreachable;
}
}
}
}
Read from Characteristic:
async Task ReadFromCharacteristicAsync(GattCharacteristic mCharacteristic)
{
GattReadResult readResult = await mCharacteristic.ReadValueAsync(BluetoothCacheMode.Uncached);
if (readResult.Status == GattCommunicationStatus.Success)
{
byte[] data = new byte[readResult.Value.Length];
DataReader.FromBuffer(readResult.Value).ReadBytes(data);
if (chart1.IsHandleCreated)
{
this.Invoke((MethodInvoker)delegate { updateChart(data); });
}
return readResult.Status;
}
return readResult.Status;
}
Terminate Connection
private async Task<bool> ClearBluetoothLEDeviceAsync()
{
mCharacteristic.Service.Dispose();
mGattService.Dispose();
await device.DeviceInformation.Pairing.UnpairAsync();
device?.Dispose();
device = null;
GC.Collect();
return true;
}
SO now when I connect the first time to the Server, I only receive zeros which shows me that the there might be a authentication Error.
After that I always receive this Error:
"System.ArgumentException" in mscorlib.dll with a notification that there is noch executable Code left because all Threads are doing some asynchronous stuff.
This Error gets thrown when I try to read from the Characteristic.
I never coded in c# before so I am not shure if there is an error in my asynchronous part oder the communication part.
Thanks you
Pairing is not the same as connecting!
I really advise using the BLE-advertisementWatcher to select and connect to your device.
The reason is that many BLE-devices don't save their pairing status.
In windows device-watcher once paired, the device stays paired even if it is switched off or out of reach.
Also many times the connection status is kept, unless the device is unpaired and disposed in code or removed in windows settings.
All BLE-devices that I know of start advertising as soon as there is no connection for some time.
This time depends on the device, but most of the time within seconds.
So don't pair but just connect if the device is advertising.
I am trying to made windows phone application with offline routing. I have found that It is possible by using Bing API.
I have registered and got the key, but I can't find, how can I use the key.
I am using following code:
private async void Button_Click(object sender, RoutedEventArgs e)
{
RouteQuery query = new RouteQuery();
List<GeoCoordinate> wayPoints = new List<GeoCoordinate>();
wayPoints.Add(new GeoCoordinate(47.23449, -121.172447));
wayPoints.Add(new GeoCoordinate(47.062638, -120.691795));
query.Waypoints = wayPoints;
query.QueryCompleted += geoQ_QueryCompleted;
query.QueryAsync();
}
private void geoQ_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
{
try
{
Route myRoute = e.Result;
MessageBox.Show("Completed");
}
catch (TargetInvocationException)
{
/// Unauthorized access exception 0x8004231C
Thread.Sleep(1000); // waiting for completing the query
geoQ_QueryCompleted(sender, e);
}
}
But I am getting Unauthorized access exception 0x8004231C.
I would like to ask you, how can I fix it?
You don't need the key to show offline map. If you have map downloaded on your device, then offline routing should work. You can see the sample to get more details.
Following is the quote from msdn sample,
However, mapping services also work without Internet connectivity when maps are downloaded for offline use.
This may be a very basic problem, but I haven't found any answer for it yet. I'm using Exchange Web Services in a Windows service to monitor new mails sent to our Exchange 2010 server with a pull subscription. It's working all fine and dandy, but the problems is if the server is not available (such as after a power outage), then the subscription times out, and the Windows service needs to be restarted. Is there a way to renew the subscription after a timeout, or to pull EvenType.Status events?
Here's my code so far:
ExchangeService service;
PullSubscription subscriptionInbox;
private void SetService()
{
service = new ExchangeService(ExchangeVersion.Exchange2010);
service.Url = new Uri("myurl");
service.Credentials = new WebCredentials(emailAddress, pass);
}
private void SetSubscription()
{
if (service == null)
{
SetService();
}
subscriptionInbox = service.SubscribeToPullNotifications(
new FolderId[] { WellKnownFolderName.Inbox },
5,
null,
EventType.NewMail, EventType.Modified);
}
private void DoStuff(object sender, EventArgs e)
{
GetEventsResults eventsInbox = subscriptionInbox.GetEvents();
EmailMessage message;
foreach (ItemEvent itemEvent in eventsInbox.ItemEvents)
{
//Do Stuff
}
}
Any ideas how I could go on with this?
When you lose a subscription, it's best to create a new subscription - and not try to recover the interim data. You can resubscribe with the old watermark, but it's cost prohibitive. This link provides some additional context about recovering notifications related to lost subscriptions: http://msdn.microsoft.com/en-us/library/office/dn458788(v=exchg.150).aspx#bk_recover. You may also want to view this Channel 9 video, which discusses recovery from lost subscriptions: http://channel9.msdn.com/Events/Open-Specifications-Plugfests/Windows-Identity-and-Exchange-Protocols-Plugfest-2012/Exchange-Web-Services-Best-Practices-Part-2.
I have a project where I need to create a windows service that, when instructed via a command, will perform various tasks. This server would run on multiple servers and would effectively perform the same kind of tasks when requested.
For example, I would like to have a Web API service that listens for requests from the servers.
The service running on the server would send a query to Web API every 25 secs or so and pass to it its SERVERNAME. The Web API logic will then look up the SERVERNAME and look for any status updates for various tasks... I.E., if a status for a DELETE command is a 1, the service would delete the folder containing log files... if a status for a ZIP command is a 1, the service would zip the folder containing log files and FTP them to a centralized location.
This concept seems simple enough, and I think I need a nudge to tell me if this sounds like a good design. I'm thinking of using .NET 4.5 for the Windows Service, so that I can use the HttpClient object and, of course, .NET 4.5 for the Web API/MVC project.
Can someone please get me started on what a basic Web API woudld look like provide status updates to the Windows services that are running and issue commands to them...
I'm thinking of having a simple MVC website that folks will have a list of servers (maybe based on a simple XML file or something) that they can click various radio buttons to turn on "DELETE", "ZIP" or whatever, to trigger the task on the service.
I do something similar. I have a main Web API (a Windows Service) that drives my application and has a resource called /Heartbeat.
I also have a second Windows Service that has a timer fire every 30 seconds. Each time the timer fires it calls POST /heartbeat. When the heartbeat request is handled, it goes looking for tasks that have been scheduled.
The advantage of this approach is that the service makes the hearbeat request is extremely simple and never has to be updated. All the logic relating to what happens on a heartbeat is in the main service.
The guts of the service are this. It's old code so it is still using HttpWebRequest instead of HttpClient, but that's trivial to change.
public partial class HeartbeatService : ServiceBase {
readonly Timer _Timer = new System.Timers.Timer();
private string _heartbeatTarget;
public HeartbeatService() {
Trace.TraceInformation("Initializing Heartbeat Service");
InitializeComponent();
this.ServiceName = "TavisHeartbeat";
}
protected override void OnStart(string[] args) {
Trace.TraceInformation("Starting...");
_Timer.Enabled = true;
_Timer.Interval = Properties.Settings.Default.IntervalMinutes * 1000 * 60;
_Timer.Elapsed += new ElapsedEventHandler(_Timer_Elapsed);
_heartbeatTarget = Properties.Settings.Default.TargetUrl;
}
protected override void OnStop() {
_Timer.Enabled = false;
}
private void _Timer_Elapsed(object sender, ElapsedEventArgs e) {
Trace.TraceInformation("Heartbeat event triggered");
try {
var httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(_heartbeatTarget);
httpWebRequest.ContentLength = 0;
httpWebRequest.Method = "POST";
var response = (HttpWebResponse)httpWebRequest.GetResponse();
Trace.TraceInformation("Http Response : " + response.StatusCode + " " + response.StatusDescription);
} catch (Exception ex) {
string errorMessage = ex.Message;
while (ex.InnerException != null) {
errorMessage = errorMessage + Environment.NewLine + ex.InnerException.Message;
ex = ex.InnerException;
}
Trace.TraceError(errorMessage);
}
}
}
You can do it with ServiceController.ExecuteCommand() method from .NET.
With the method you can sand custom command to windows' service.
Then in your service you need to implement ServiceBase.OnCustomCommand() to serve incomming custom command event in service.
const int SmartRestart = 8;
...
//APPLICATION TO SEND COMMAND
service.ExecuteCommand(SmartRestart);
...
//SERVICE
protected override void OnCustomCommand(int command)
{
if (command == SmartRestart)
{
// ...
}
}