AIR native extension: Can I call ActionScript 3 method from C/Objective-C? - objective-c

I have an AIR application that uses a native extension to create a series of dialogs the user navigates through. After the user navigates through the dialogs, I need the C/Objective-C side to notify the AIR app that the user finished as well as forward the series of choices the user made.
Is that possible?
IE: the C/ObjC equivalent of
public function evokeMyASMethod(choice0:int,choice1:int):Boolean
{
// context opens the native extension to the AS3 side
var success:Boolean = context.call("myASMethod", choice0, choice1) as Boolean;
return success;
}
An alternate solution is to start a timer in ActionScript that pings the native extension periodically to check whether the user has finished and fetch the values, but that seems so messy that I think I must be missing something obvious.
Any help is much appreciated. Thanks!

What you'll need to do is dispatch "status" events from the native code and then listen for them in your AS3 code.
So firstly in your AS3 code add a listener to your extension context:
context.addEventListener( StatusEvent.STATUS, onStatus);
private function onStatus( event:StatusEvent ):void
{
trace( "code = " + event.code );
trace( "level = " + event.level );
}
The code and level variables are two strings you can pass back from your native code. In your ObjC code you'll use the FREDispatchStatusEventAsync function to fire an event back to your AS3 code:
FREDispatchStatusEventAsync( yourFreContext, (const uint8_t*)"code", (const uint8_t*)"level" );
You just need to change the "code" and "level" strings as you see fit and process them in your onStatus handler.
More information here:
http://help.adobe.com/en_US/air/extensions/WSb464b1207c184b143961a5e412937b5d5c6-7ffc.html
http://help.adobe.com/en_US/air/extensions/WSb464b1207c184b14-62b8e11f12937b86be4-7ff5.html

Related

Dojo callback never called on iconItem

This is my constructor:
iconJs =new dojox.mobile.IconItem({label:'', deletable: false, icon:'images/Tile_Toevoegen.png', transition:'slide', class:'klasIcon', url:'views/klappr/addKlas.html', urlTarget:'addKlas', onClick:function(){alert("test onclick");} , callback: function(){alert("test callback");}});
When I click on the iconItem, the alert "test onclick" works.
But I need the callbackfunction to work.
In the iconItem guide:
**callback**
Function String
A callback function that is called when the transition has been finished. A function reference, or name of a function in context.
The alert "test callback" needs to be called when the transition is done, but it doesn't work. Can someone help me out?
I reproduce with Dojo 1.9.1. In addition to item.callback, there is also item.onOpen which could be helpful, however none of them gets called in this case.
I think this is a Dojo Mobile bug and I suggest that you enter a ticket at https://bugs.dojotoolkit.org .

Windows 8 app: How to pass a parameter on GoBack()?

There are a lot of samples showing how to pass a parameter on navigating to a page in Window 8 (WinRT). But I could not find any hint for passing parameters going back.
Situation: The user navigates to a details page of same data. The data is passed to the page by
Frame.Navigate(typeof(DedtailsPage), data);
How can I pass back the changed data on GoBack()?
Store the reference to data somewhere and retrieve it when you navigate back?
Also note that it's best not to pass objects other than simple strings or values between pages, since only simple types are supported for storing frame navigation state in case your app gets suspended.
I know, that this is a very bad idea, but usualy I use this:
To write:
Frame rootFrame = Window.Current.Content as Frame;
rootFrame.Tag = myObject1;
To read:
Frame rootFrame = Window.Current.Content as Frame;
var myObject2 = rootFrame.Tag;
I've made another choice to handle this.
Keep in mind that I'm a Xamarin developer (not Forms!) so i was looking for a solution which was similar for all platforms: iOS, Android and Windows.
I am a great fun of events, rather than passing objects or storing globals.
So the best choice to pass data from PageB (the child) to PageA (the parent) is to communicate via events.
Some notes: In iOS and Android, when you navigate from a "page" to "page" you can do this by passing an instance of the target object you want to navigate to. In iOS you create an instance of a custom UIViewController. In Android you create an instance of a custom Fragment. Doing this allow you to attach events handler to your instances.
An example:
var controller = new ExtrasViewController();
controller.ExtraSelected += ExtrasFragment_ExtraSelected;
controller.ExtrasCleared += ExtrasFragment_ExtrasCleared;
this.NavigationController.PushViewController(controller, false);
In WinRT Apps you are only allowed to pass "types" of target page to navigate to. So the only way to attach event handlers to your page instance is to use the OnNavigatedFrom method from the calling page. So suppose you are in PageA and want to attach some event handlers to your PageB, before it become active, simply write in your PageA "code behind":
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
var page = e.Content as ExtraBody;
if(page != null)
{
page.ExtraSelected += ExtrasFragment_ExtraSelected;
page.ExtrasCleared += ExtrasFragment_ExtrasCleared;
}
}

Using Tiles templates windows8

I'm trying to use tiles templates(a tile which shows an image and switches to show text)
http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx#TileSquarePeekImageAndText04
The question is: where do I put this XML and how can I call it in XAML?
You don't call it in XAML, you provide it to a TileUpdater instance, as you can see from the documentation for TileUpdateManager below. This simplistic scenario handles a local notification (but there are also scheduled, periodic, and push notifications you can leverage).
Take a look at the App tiles and badges and Push and periodic notifications samples for guidance.
function sendTileTextNotification() {
var Notifications = Windows.UI.Notifications;
// Get an XML DOM version of a specific template by using getTemplateContent.
var tileXml = Notifications.TileUpdateManager.getTemplateContent(Notifications.TileTemplateType.tileWideText03);
// You will need to look at the template documentation to know how many text fields a particular template has.
// Get the text attribute for this template and fill it in.
var tileAttributes = tileXml.getElementsByTagName("text");
tileAttributes[0].appendChild(tileXml.createTextNode("Hello World!"));
// Create the notification from the XML.
var tileNotification = new Notifications.TileNotification(tileXml);
// Send the notification to the calling app's tile.
Notifications.TileUpdateManager.createTileUpdaterForApplication().update(tileNotification);
}

Removing the BackStack Entry in MetroStyle Application

How can I implement removing the backStack Entry in Metro style applications?
frame.SetNavigationState("1,0");
will clear the navigation history for you.
I found this answer useful:
How to clear Backstack of the frame and start afresh
Write your own NavigationService and store the navigationstate in the constructor.
string state;
public NavigationService(Frame mainFrame)
{
state = mainFrame.GetNavigationState();
_mainFrame = mainFrame;
_mainFrame.Navigating += _mainFrame_Navigating;
}
Then implement this method on the service and call it when needed:
public void ClearBackstack()
{
_mainFrame.SetNavigationState(state);
}
It doesn't seem to be possible. If you want to clear the back stack entirely (e.g. if you have a "home" button), you can use the code supplied in the LayoutAwarePage.cs file in the grid sample app.
if (this.Frame != null)
{
while (this.Frame.CanGoBack) this.Frame.GoBack();
}
While this doesn't actually clear the stack, it does take you back to the program's start location and there will be no further back-direction entries in the list. If you want to back out of a dead-end page by pressing a button, you could modify this behaviour to step back a number of pages and effectively remove the back entries.

CoreDispatcher.ProcessEvents() causes an indirect crash?

I have to port some legacy code, that uses modal dialog boxes all over the place to Metro/WinRT (using C++/CX). Because these dialog boxes provide their own message loop (using DialogBoxParam()), the calling code will wait until the user has clicked a button on the message box.
I'm currently trying to write a replacement for the old message box class, that uses XAML and the popup control. To reproduce the same behavior, I have to wait in the calling thread, but also have to keep the UI responsive. I've found out, that CoreDispatcher::ProcessEvents() can be used in a loop, to keep processing events (yeah I realize that this isn't very beautiful, but I don't want to change all of our legacy code to a new threading model). However I'm running into an issue that keeps crashing my app.
Here is a minimal example that reproduces the issue (just create a XAML app and wire this to a button):
void CPPXamlTest::MainPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
bool cancel = false;
auto popup = ref new Popup();
auto button = ref new Button();
button->Content = "Boom";
auto token = (button->Click += ref new RoutedEventHandler([&cancel] (Object ^, RoutedEventArgs ^) { cancel = true; }));
popup->Child = button;
popup->IsOpen = true;
while (!cancel)
{
Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
}
popup->IsOpen = false;
button->Click -= token;
}
This seems to work well for the first one or two tries of opening and closing the popup, using the two buttons. After a few tries however, the application will instantly crash deep in Windows.UI.Xaml.dll, while trying to dereference a null pointer. I can also reproduce this in C# (with practically the same code).
Does anyone have an idea, what is going on in here? Or a suggestion for an alternative approach?
If anyone is interested: I asked the same question a few days later on the MSDN forums and got a response there from a Microsoft employee:
http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/11fa65e7-90b7-41f5-9884-80064ec6e2d8/
Apparently the problem here is the nested message loop that is caused by calling ProcessEvents inside an event handler. It seems that this is not supported by WinRT, but instead of failing in a well-defined manner, this will or may cause a crash.
Alas this was the best and only answer I could find, so I ended up working around the problem, by dispatching the event handler (and a lot of other code) into another thread. I could then emulate the waiting behavior of DialogBox()/DialogBoxParam() (outside the main thread), by waiting on an event that was signaled when the user clicked/tapped a button on my XAML "dialog" popup.
A workaround that works fine for me is to replace the line:
Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
with:
auto myDispatchedHandler = ref new DispatchedHandler([&](){
Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
});
dispatcher->RunAsync(CoreDispatcherPriority::Normal,myDispatchedHandler);
For more info see this post at MSDN.