Passing partial parameter in a push notification on Windows Phone 8.1 - notifications

I'm trying to send a toast notification with a parameter to a Windows Phone 8.1 device, so when a user taps on the toast the app will show a particular page within the app, as it described in this MSDN article https://msdn.microsoft.com/library/windows/apps/jj662938(v=vs.105).aspx
This is a snippet that I use to add a parameter:
<wp:Param>?cmd=command1 </wp:Param>
this how I read it in the app:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e){
base.OnNavigatedTo(e);
string strVal1 = this.NavigationContext.QueryString["cmd"];
}
After making these changes it works correctly, but only for this first notification. In all subsequent notifications the value of the parameter read within the app is same as it was in the first notification, no matter what I've sent from the server.
Here is an example:
I'm sending a notification to device that has with this parameter in the notification payload: <wp:Param>?cmd=command1 </wp:Param> The value in this.NavigationContext.QueryString("cmd") is command1, as it should be.
Then I send a second notification with this parameter parameter
<wp:Param>?cmd=command2 </wp:Param>
the cmd's value in the this.NavigationContext.QueryString("cmd") is still returned as "command1" instead of command2 as it should be. And it works like that for all subsequent notifications until I force-restart the app.
Here is what I've tried:
Checked the Uri value in the NavigationEventArgs argument of the OnNavigatedTo event and it's same as what I see in the NavigationContext.
Double checked notification payload sent from the server (it's correct)
Checked msdn/stackoverflow/google.
Checked on both 8.1 emulator and the device (it works the same)
Questions:
Do I have to do something in the app (idk, clear NavigationContext or something), so it will be different for the next notification?
Does anyone actually has a live-app that uses partial arguments (not server-driven navigation with full url, but a partial url passed to the app + corresponding navigation from within the app) and it works for multiple subsequent notifications?

Figured out what the problem was. Two OnNavigated events are fired when app is relaunched. First one has a type of System.Windows.Navigation.NavigationMode.Reset and it has the data of the old page being reset (in my case, with the data from old notification). The second one is System.Windows.Navigation.NavigationMode.New and has the data from the new notification.
A simple check of navigation mode to make sure it's of the type .New fixed the issue:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e){
base.OnNavigatedTo(e);
if (e.NavigationMode == System.Windows.Navigation.NavigationMode.New)){
// custom navigation logic based on the data within <wp:Param/>
}
}

Related

watchOS background refresh not accessing CoreData?

I have a watch companion app that accesses CoreData through CloudKit and then chooses a random string from the data.
It works perfectly, all of that is setup exactly as needed. So I know all of that is working.
The issue now is I am wanting the Watch complication to update sporadically with an updated random string from that data.
Here is what I have confirmed is working:
the complication can update with the assigned variable correctly
this variable can be assigned manually by opening the app and pressing a button
background scheduling and refreshing is confirmed to work, I tested with print statements.
The issue now is that the goal is to make the function run with the background refresh. This function takes that data from CoreData, picks a random string, and assigns it to the variable. That variable is then displayed on the watch face complication and in the app.
The function has an if statement that says
if (the fetched coredata) .isEmpty {
(Variable) = “No Data” }
And the watch complication is showing “No Data.”
This indicates that this function is running with the background refresh but is not accessing the CoreData and is staying empty. This exact same function works fine when manually called inside the app.
TL;DR I have isolated and confirmed that CoreData is not being accessed when running a function in the background schedule on watchOS.
How do I fix this?

UI element updates does not work when purchase completed - Google billing client 4

I have changed over to Google billing client 4.0 library. Since then when purchase is completed, my ui elements updates does not work.
I was trying to check if they are not in UThread anymore or something, but it is not working properly still.
billingClient!!.acknowledgePurchase(
acknowledgePurchaseParams
) { billingResult ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
saveSubscription(purchase.purchaseToken, sku)
mainAct?.runOnUiThread {
Toast.makeText(context , "Vásárlás sikeres", Toast.LENGTH_SHORT)
.show()
delegate?.purchaseSuccess(
actProduct,
prevProduct,
purchase.purchaseToken
)
}
}
}
When the acknowledge is done, my UI elements should be updated. There is a menu item should be enabled and in the purchase page a textfield should show that the item is purchased. The code is running, but the UI elements are not updated.
Once I move to a different fragment, the menu item turns to enabled, so it seems to me that somehow the UI is not refreshed.
In the code mainAct is the context to the MainActivity.
Any idea?
The code was running properly on Billing library 3.0.3 and runOnUIThread was not needed at all.
Still getting weird behaviour with this library. I was setting up the billing at the same time as my users log in to the app and go from the login page to the first fragment. This fragment has a recyclerview and this recycler view was filled with data from the web. The recycler view was randomly not showing the elements, even if they were loaded and the adapter was properly updated.
One you moved to another fragment and back the recycler view was showing the data properly.
As I said, the first time call when the billing server is approached the UIThread is messed up and even if data labels or menus are updated, the updates were not showed.
So something is definitely wrong with this library.
Any idea?
This behaviour is a bit weird. The documentation is saying the most of the billing library functions can be run from any thread. Only few needs to be run on UIThread. AcknowlegdePurchase should be running on AnyThread.
I have put the Toasts into runOnUIThread and the inside the delegate functions all commands I have also put inside a runOnUIThread closure.
Now it works as on billing library 3.0.3. But the documentation was not telling anything about any of these changes, so it is really unclear, why the behaviour has changed that much between the two libraries.

Xamarin Xaml force update interface elements

The post has been rewritten to better fit the current problem.
I have a button x:Name="selectVesselButton". On button click, it tries to establish a connection to a server, which takes a sec or two for to do. Originally, I wanted the button to be grayed out while it was downloading and deserializing the json file from the connection.
My old code (before async, and trying to update the button):
// disabling the button to prevent spam clicking.
string buttonText = selectVesselButton.Text;
selectVesselButton.IsEnabled = false;
selectVesselButton.Text = "loading...";
// retrieve data for speed page.
RetrieveData();
// redirect to next info block if build was successfull.
FocusSpeedblock();
// enabling the button again.
selectVesselButton.Text = buttonText;
selectVesselButton.IsEnabled = true;
The issue with this code was that the button visuals did not update until the RetrieveData() was finished, defeating the purpose of doing that at all. This was because the code for updating the interface and the code for downloading and deserializing the object were both on the same thread.
However, following Ivan's advice, I made the downloading and deserializing Async, which fixed this issue (more like moved it).
This works fairly well, but I am still having some trouble updating the interface automatically. I have some labels that need to be updated based on the json file output. The value of the labels update on the background, but only update visually once I interact with the labels (I.E. scrolling the scrollview they are on). Check edit 3 for more detail on that.
EDIT 3:
When the second thread is finished, it should call the UpdateSpeedLabels() and update some labels. However, they update in codebehind, without instantly updating the interface. They only update if I interact with those labels.
The preferred way of doing this on Xamarin is with data binding. As you opted out of this it is still possible.
What you need is to ensure that your long task is not running in the UI thread as it blocks it and prevent its updates. You do this by using Task.Run(() => { your task code }); . However you can't update your user interface inside the Task.Run as it is not running on the UI thread and it would crash the app, so you need to use Device.BeginInvokeOnMainThread(() => { your UI code }); inside Task.Run for that part.

How can I react to a message with a pub/sub bot

I have created a Card with a button and a onClick action that successfully sends a message to my client with type "CARD_CLICKED".
When I try to respond to this message with either a type "NEW_MESSAGE" or "UPDATE_MESSAGE" message, this is displayed as a new message, while the API tries for three times to send that CARD_CLICKED event to my bot until it gives up with the visual error: "Unable to contact [bot]. Try again later."
I guess this is similar to
Interactive button doesn't work properly when using pub/sub
Interactive cards hangout chat Api
but I am using a golang client and the answer to these questions didn't help me...
My code to respond to the "CARD_CLICKED" message:
func handleClick(message *chat.DeprecatedEvent) *chat.Message {
log.Debugf("User %s instructed me to execute %s", message.User.DisplayName, message.Action.ActionMethodName)
response := &chat.Message{
ActionResponse: &chat.ActionResponse{Type: "UPDATE_MESSAGE"},
Thread: &chat.Thread{Name: message.Message.Thread.Name},
Space: &chat.Space{Name: message.Message.Space.Name, Type: message.Message.Space.Type},
Text: "CARD CLICKED!",
}
return response
}
My code is based on this project: https://github.com/jforman/hangbot
Found out what the main issue was... I was calling the .Create() function - which created a new message and thus - even though the Action Response was set correctly - this was not interpreted as a response to the click event:
https://github.com/jforman/hangbot/blob/master/hangbot.go#L79
After I switched to calling .Update() - Chat would not display the "Unable to contact" message about my bot any more.
What remains is that the click event is still sent to me three times, but I'm filtering events now based on the eventTime, which works ok for now.

How do I make Message targets be the only recipent of a targeted Message?

First time poster.
I'm using MVVM-Light with Silverlight 4 and RIA Services. This has been a learning experience! But so far, it's working beautifully. I was wondering two things. Right now, I'm using the Messenger framework to pass EntityObjects back to the ViewModel. For instance, I need to open a View Model with a specific "Course" object. So I instantiate the View, and the View sends a Message to the ViewModel with the Course. I've got a couple questions.
First question: Is this the best way to do this? I don't want to use Prism or Unity or any of those other things because I don't have the time to learn them. (This was, for me, the big draw of MVVM Light. The Light part.) But I couldn't see any other way to pass parameters to the VM Locator.
The second part is, this means I am sending messages from the View to that View's specific ViewModel. My messages look like this:
Tuple<Models.Course, Services.VWDS> courseDomainContextTuple = new Tuple<Models.Course, Services.VWDS>(Course, DomainContext);
NotificationMessage<Tuple<Models.Course, Services.VWDS>> message = new NotificationMessage<Tuple<Models.Course, Services.VWDS>>(this, this.DataContext, courseDomainContextTuple, Models.MessageString.EditCourse);
Messenger.Default.Send<NotificationMessage<Tuple<Models.Course, Services.VWDS>>>(message);
So, as you can see, I'm bundling the Course and the DomainContext (Ah RIA. Why won't you let me get the Context from the EntityObject?) and sending them to the ViewModel (which is "this.DataContext") - and yes, I know I should make a class for that message.
Here's the problem - every object that gets a Course and a DomainContext receives that message, not just the VM that I've designated the Target.
So, second question: Is that by design, or is that a bug, or am I doing something wrong?
Thanks!
To answer your second question, if you're sending a NotificationMessage of a specific type, anything registering for that same message type will receive the message. If you want to limit who receives the message, either create a new message class inheriting from MessageBase or NotificationMessage or whatever, send your message with a Token, or have an if statement in your message receive handler to filter out messages you don't care about.
Messaging is more useful when you need to communicate from one ViewModel to another, or you need to send a message where zero to many things can take action on it. From your View's code behind, I think you should just call your ViewModel directly. Its easy enough - here's how I usually do it in my code.
public partial class ExampleView : UserControl
{
private IExampleViewModel ViewModel
{
get { return this.DataContext as IExampleViewModel; }
}
public ExampleView()
{
InitializeComponent();
// Call directly to my View Model
ViewModel.SomeMethod();
// Register for View Model's event
ViewModel.SomeEvent += ViewModel_SomeEvent;
}
private void ViewModel_SomeEvent(object sender, EventArgs e)
{
// do stuff
}
}
I also included in the example how I handle communications from the ViewModel back to the View - through events.