Reputation: 24460
I am attempting to use NFC in an Windows Phone 8 application, which uses the MvvmCross framework. Now normally you subscribe to receive NFC events on WP8 by adding an Extension
to the WMAppManifest.xml
like so:
<Extensions>
<Protocol Name="my-resource" NavUriFragment="encodedLaunchUri=%s" TaskId="_default" />
</Extensions>
This will launch the _default
task, if it finds a uri starting with my-resource://
, which on a fresh project is the MainPage.xaml
. In this case I have set it to Views\ScanView.axml
, which is a MvxPhonePage
.
Then to get the data in the _default
task, you would override OnNavigatedTo
and grab the e.Uri
, which is the data from the NFC tag. I.e.: /Protocol?encodedLaunchUri=my-resource://ni?EkkeEkkeEkkeEkkePtangyaZiiinngggggggNi
.
Now it seems that the MvxPhonePage
overrides OnNavigatedTo
on its own and uses it for some save states. So my question is. How do I get original Uri instead of the saved state?
Can I just work around it by using the MainPage.axml
and then when I am done loading the NFC stuff navigate to Views\ScanView.axml
?
Upvotes: 1
Views: 282
Reputation: 24460
I solved the problem by creating a custom AppStart
which is briefly described in this Slide Deck, which Stuart Lodge told me to look at.
So in my ScanViewModel
I added an Init(string url)
method, which handles navigation with extra parameters, in this case my wanted Url, and then I can handle it as I want there.
In App.xaml.cs
where you normally call the Start()
method of the AppStart
I added some conditions:
var start = Mvx.Resolve<IMvxAppStart>();
var url = navigatingCancelEventArgs.Uri.ToString();
if(url.StartsWith(@"/Protocol?encodedLaunchUri=my-resource")
start.Start(url.SubString("/Protocol?encodedLaunchUri=".Length));
else
start.Start();
Then I had to create my own AppStart
:
public class MyCustomAppStart : MvxNavigatingObject, IMvxAppStart
{
public void Start(object hint = null)
{
if(hint is string)
ShowViewModel<ScanViewModel>(new {url = (string)hint});
else
ShowViewModel<ScanViewModel>();
}
}
Which I instantiate in the MvxApplcation
Initialize
method:
RegisterAppStart(new MyCustomAppStart());
Then I get the desired Url in Init
in the ViewModel:
public void Init(string url)
{
//Whatever I want, whatever I need
}
Upvotes: 2
Reputation: 9604
Another alternative is to define a custom UriMapper
to catch and validate the external launch URI, and then return the URI of the actual page you want to launch. That way you keep the external launch logic away from your page navigation logic.
See UriMapperBase docs for the basics. You'll need to add the UriMapper
to your PhoneApplicationFrame
at the correct point.
In App.xaml.cs:
// Do not add any additional code to this method
// ;)
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
// TODO: Add custom UriMapper here
RootFrame.UriMapper = new MyCustomUriMapper();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// ...
}
Upvotes: 0