Push Notification inside ScheduledAgent in Windows Phone 8 - windows-phone-7

I would like to achieve a similar task, in which I want to re-establish my push notification channel using background agent. Is it possible?
I am using the following code inside my ScheduledAgent, but its not working. If I cannot access the channel APIs, is there any alternative to that? How have popular apps like whats-app and others been able to achieve this? Please help me.
Can you advise me an alternative? How can I update my user that there is something new for him from my server without using this approach?
protected override void OnInvoke(ScheduledTask task)
{
//TODO: Add code to perform your task in background
HttpNotificationChannel pushChannel = HttpNotificationChannel.Find("HikeApp");
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel("HikeApp");
// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.Open();
pushChannel.BindToShellTile();
pushChannel.BindToShellToast();
}
else
{
// the channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
}
#if DEBUG_AGENT
ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(1));
#endif
NotifyComplete();
}

As per the list of Unsupported APIs in Background Agents, it is not possible to do anything in the Microsoft.Phone.Notification namespace, which includes everything to do with push notifications, from a scheduled agent.

Related

Outlook VSTO AddIn How to avoid RaceOnRCWCleanup

What I am trying to achieve is to also handle drag and drop events on the calendar properly using the AppProperty Change event on the Inspector:
I update the currentAppointmentItem whenever the user interacts with the interface (Explorer.SelectionChange, NewInspector, CloseInspector, etc.)
I update the currentInspector whenever the user interacts with the interface (SelectionChange, NewInspector, CloseInspector)
Update means that I try to set/unset the event handlers appropriately and to Marshal.ReleaseComObject accordingly. Finally to null the reference.
But when the user just clicks on an AppointmentItem in the calendar no Inspector window is created. Thus I wouldn't be able to catch AppPropertyChange Events. So I decided to call GetInspector on the selected AppointmentItem in case it is not null. I try to use this to receive changes on the AppProperty Event so I can handle drag and drop events on the calendar properly
The problem: From the Microsoft documentation I understand whenever you lose a reference to currentAppointmentItem you should also use Marshal.ReleaseComObject otherwise you risk other problems.
Now I experience exceptions which I cannot catch: RaceOnRCWCleanup ... it seems that I try to release a COM object which is still in use (probably by Outlook). How can I avoid that? Is it correct to Marshal.ReleaseComObject(currentAppointmentItem)
I registered on the SelectionChange Event on the Outlook.Explorer. In there I try to register the currentAppointment with:
[...]
log.Info("Selection_Change");
if (currentExplorer == null)
{
return;
}
try
{
log.Info("Selection_Change: " + currentExplorer.Caption);
Outlook.MAPIFolder selectedFolder = currentExplorer.CurrentFolder;
if (currentExplorer.Selection.Count > 0)
{
Object selObject = currentExplorer.Selection[1];
if (selObject is Outlook.AppointmentItem)
{
currentAppointmentItem = (Outlook.AppointmentItem)selObject;
Inspectors_NewInspector(currentAppointmentItem.GetInspector);
}
[...]
Please Note: INspectors_NewInspector is also called on the Inspectors Collection.
The code of NewInspector is like
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
try
{
log.Info("Inspectors_NewInspector");
// This function (apparently) gets kicked off whenever a user opens a new or existing item
// in Outlook (Calendar appointment, Email, etc).
// We can intercept it, modify it's properties, before letting our Ribbon know about its existance.
//
if (Inspector != null)
{
log.Info("Inspectors_NewInspector: " + Inspector.Caption);
unregisterCurrentInspector();
currentInspector = Inspector;
object item = Inspector.CurrentItem;
if (item == null)
return;
if (!(item is Outlook.AppointmentItem))
return;
unregisterCurrentAppointmentItem();
currentAppointmentItem = (Outlook.AppointmentItem)item;
currentAppointmentItem.PropertyChange += AppPropertyChanged; // Handle situations where the
// user tries to convert an appointment w/ an agreedo protocol to a recurring appointment.
// This needs to be avoided .
currentAppointmentItem.CustomPropertyChange += AppPropertyChanged;
}
((Microsoft.Office.Interop.Outlook.InspectorEvents_10_Event)Inspector).Close += Inspector_Close;
} catch (Exception ex)
{
log.Error(ex.Message);
}
}
the unregisterCurrentApppointmentItem :
private void unregisterCurrentAppointmentItem()
{
try
{
log.Info("unregisterCurrentAppointmentItem");
if (currentAppointmentItem != null)
{
currentAppointmentItem.PropertyChange -= AppPropertyChanged; // Handle situations where the
currentAppointmentItem.CustomPropertyChange -= AppPropertyChanged;
Marshal.ReleaseComObject(currentAppointmentItem);
currentAppointmentItem = null;
}
} catch (Exception ex)
{
log.Error(ex.Message);
}
}
the unregisterCurrentInspector:
private void unregisterCurrentInspector()
{
log.Info("unregisterCurrentInspector");
if (currentInspector != null)
{
((Microsoft.Office.Interop.Outlook.InspectorEvents_10_Event)currentInspector).Close -= Inspector_Close;
Marshal.ReleaseComObject(currentInspector);
currentInspector = null;
}
}
Any advice on this?
What I already tried / taken into account:
Outlook Addin: Moving Appointment in Calendar does not reflect new date/time in AppointmentItem (catch Calendar.ItemChange)
VSTO Outlook Plugin: Cannot get AppointmentItem in Item_Change event when recurring appointment is dragged and dropped by user
First of all, there is no need to simulate the NewInspector event. Instead, you need to set up event handlers correctly. It seems you just need to implement an inspector or explorer wrappers. See Implement a wrapper for inspectors and track item-level events in each inspector for more information.
it seems that I try to release a COM object which is still in use (probably by Outlook). How can I avoid that? Is it correct to Marshal.ReleaseComObject(currentAppointmentItem)
Yes, it is. But you should really use this method against objects retrieved in your code by calling properties and methods. You SHOULD NOT release objects passed as parameters by the Office applications. Take a look a the When to release COM objects in Office add-ins developed in .NET article which explains possible pitfalls and give answers to the most widely spread questions.
Why do you even need the Inspector object? Are you only using the Inspector.Close event?
Use AppointmentItem.Close / Write events.

Correct syntax for writing NativeScript plugin

I'm learning about NativeScript plugins and am trying to get the PubNub iOS SDK working. So far (with the TypeScript below), I am able to successfully configure, subscribe to channels, and publish messages. I'm trying to receive messages as well by converting the "// Handle new message..." section to TypeScript as well, but haven't been able to get it working. How would I write this?
Objective-C:
// Initialize and configure PubNub client instance
PNConfiguration *configuration = [PNConfiguration configurationWithPublishKey:#"demo" subscribeKey:#"demo"];
self.client = [PubNub clientWithConfiguration:configuration];
[self.client addListener:self];
// Subscribe to demo channel with presence observation
[self.client subscribeToChannels: #[#"my_channel"] withPresence:YES];
// Handle new message from one of channels on which client has been subscribed.
- (void)client:(PubNub *)client didReceiveMessage:(PNMessageResult *)message {
NSLog(#"Received message");
}
// Publish message
[self.client publish: #{#"message": #"this is my message"}
toChannel: #"my_channel" withCompletion:^(PNPublishStatus *status) {
}];
Typescript:
// Initialize and configure PubNub client instance
this.config = PNConfiguration.configurationWithPublishKeySubscribeKey("demo", "demo");
this.client = PubNub.clientWithConfiguration(this.config);
this.client.addListener();
// Subscribe to demo channel with presence observation
this.client.subscribeToChannelsWithPresence(channels, true);
// Handle new message from one of channels on which client has been subscribed.
?
// Publish message
this.client.publishToChannelWithCompletion(msgObj, channel, function(publishStatus) {
console.log(publishStatus.data)
})
Looks like you are missing the PNObjectEventListener delegate here. You should implement the delegate and pass it's instance to addListener function for the didReceiveMessage callback to be invoked upon a new message.
For example here you can see how the core framework implements UITextViewDelegate for TextView so it could be notified upon changes and other events.
Since you are using TypeScript, take advantage of typings for your PubNub library so it may be easy for you to get find the right syntax.

ViewChanged suppress on Windows Phone 8.1

There is a way to fire the event ViewChanged (that was present in previous WP8) within an Windows Phone 8.1 app? I use Windows.UI.Xaml.Controls.Maps and I will manage the map when the view animation finishes.
You can try to use on of these events of the MapControl class:
ManipulationStarted: http://msdn.microsoft.com/en-us/library/hh702372.aspx
CenterChanged: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.controls.maps.mapcontrol.centerchanged.aspx
ZoomLevelChanged: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.controls.maps.mapcontrol.zoomlevelchanged.aspx
But the best event would be ManipulationCompleted: http://msdn.microsoft.com/en-us/library/windows.ui.xaml.uielement.manipulationcompleted.aspx
I've found that the LoadingStatusChanged event does what you want, provided you check the LoadingStatus first.
mapControl.LoadingStatusChanged += MapLoadingStatusChanged;
private void MapLoadingStatusChanged(MapControl sender, object args)
{
if (sender.LoadingStatus == MapLoadingStatus.Loaded)
{
// code here will only get hit when the map finishes drawing after a pan/zoom
}
}

Windows Phone Toast notification not firing at specified time

I am creating an app with a timer in it. I want to display a toast notification(or some sort of notification) if the person leaves the app so they know the timer is over. I used the "PeriodicTask" using ".FromSeconds", but it seemed it didn't fire it at the specified time.
PeriodicTask periodicTask = new PeriodicTask("TaskTest");
periodicTask.Description = "Task";
try
{
IsolatedStorageSettings.ApplicationSettings["TimerForSchedule"] = TimeNum;
ScheduledActionService.Add(periodicTask);
ScheduledActionService.LaunchForTest("TaskTest", TimeSpan.FromSeconds(((TimeNum*60))));
}
On the "OnInvoke" method for the scheduled agent project, I have the following:
protected override void OnInvoke(ScheduledTask task)
{
if (task.Name == "TaskTest")
{
int time = Convert.ToInt32(IsolatedStorageSettings.ApplicationSettings["TimerForSchedule"]);
bool periodic = (bool)(task is PeriodicTask);
ShellToast toast = new ShellToast();
toast.Title = "Done";
toast.Content = "Timer is over";
toast.Show();
}
NotifyComplete();
ScheduledActionService.Remove("TaskTest");
}
Everything seems to fire properly because I DO get a notification, but I do not get it at the expected time.
Any help would be appreciated.
Is your app running in the foreground? If so, the ShellToast won't show up. Your app must be in the background for it to show up. Read more about that and potential workaround at my other # How can I create a shelltoast?
I think that the time you set to run your PeriodicTask is just a hint for the OS, it does not mean that it will fire it exactly at that time.

How to pass window handle to wndproc?

I have written this code in c# application for tracking messages ...
protected override void WndProc(ref Message m)
{
// Listen for operating system messages.
switch (m.Msg)
{
case WM_CHAR:
FileStream fs = new FileStream("d:/Type.txt",FileMode.Append,FileAccess.Write);
//set up a streamwriter for adding text
StreamWriter sw = new StreamWriter(fs);
sw.BaseStream.Seek(0, SeekOrigin.End);
int no=(int)m.WParam;
sw.Write(Convert.ToChar(no));
sw.Flush();
sw.Close();
break;
}
base.WndProc(ref m);
}
I want to track messages for different window so how can I pass different window handle to wndproc ? please help me...
You'd have to register global keyboard hook instead of passing different handle. This article shows how to do that. Basic idea behind that is that you register your function for polling all keyboard-related system events (for every message) and filter out only those you need.
The functionality is achieved with SetWindowsHookEx winapi function.
You can filter all the messages in the application by calling Application.AddMessageFilter(IMessageFilter filter) at the beginning of your program.
The IMessageFilter interface has just one method:
bool PreFilterMessage(ref Message m);
That is called for every message handled by the application. There you can use m.HWnd to identify the different windows of your program.

Resources