I'm working on an App for Win8 which should include the possibility of saving contact information. The service I use offers VCard support so I decided on using them. I can succesfully download and save them, only opening them automatically doesn't work. The files are "correct", and can be opened from the explorer without any problem. Any ideas why LaunchFileAsync isn't working?
Here's a dump of the code:
private async void SaveContactSelected()
{
IRandomAccessStreamReference img = RandomAccessStreamReference.CreateFromUri(SelectedItem.Image.UriSource);
StorageFile file = await StorageFile.CreateStreamedFileFromUriAsync(SelectedItem.Title.Replace(' ', '_')+".vcf", new Uri(SelectedItem.VCardUrl), img);
var stream = await file.OpenReadAsync();
uint size = Convert.ToUInt32(stream.Size);
IBuffer buffer = await stream.ReadAsync(new Windows.Storage.Streams.Buffer(size), size, InputStreamOptions.None);
if(!stream.CanRead)
{
//TODO: Error handling
return;
}
FileSavePicker savePicker = new FileSavePicker();
savePicker.FileTypeChoices.Add("vcard", new List<string> { ".vcf" });
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.SuggestedFileName = SelectedItem.Title.Replace(' ', '_') + ".vcf";
StorageFile saveDestination = await savePicker.PickSaveFileAsync();
if (saveDestination != null)
{
CachedFileManager.DeferUpdates(saveDestination);
await FileIO.WriteBufferAsync(saveDestination, buffer);
FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
if (status == FileUpdateStatus.Complete)
{
bool succ = await Launcher.LaunchFileAsync(saveDestination, new LauncherOptions() { DisplayApplicationPicker=true });
return;
}
else
{
//TODO: Error handling
}
}
}
An here a dump of the relevant parts of the manifest:
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="MyApp.App">
<VisualElements DisplayName="MyApp.com" Logo="Assets\Images\Logo.png" SmallLogo="Assets\Images\SmallLogo.png" Description="MyApp.com Description TODO" ForegroundText="dark" BackgroundColor="#464646">
<DefaultTile ShowName="allLogos" WideLogo="Assets\Images\LogoWide.jpg" />
<SplashScreen Image="Assets\Images\SplashScreen.png" BackgroundColor="#FFFFFF" />
<InitialRotationPreference>
<Rotation Preference="landscape" />
</InitialRotationPreference>
</VisualElements>
<Extensions>
<Extension Category="windows.search" />
<Extension Category="windows.fileTypeAssociation">
<FileTypeAssociation Name="vcard">
<DisplayName>V-Card</DisplayName>
<EditFlags OpenIsSafe="true" />
<SupportedFileTypes>
<FileType ContentType="text/x-vcard">.vcf</FileType>
</SupportedFileTypes>
</FileTypeAssociation>
</Extension>
</Extensions>
</Application>
Edit: Added manifest dump for more clarity.
While dealing with this error:
Two things I discovered. First, a reference to some odd safety check done by Windows (which wasn't what caused it for me: https://social.msdn.microsoft.com/Forums/en-US/c0625345-5d57-4e40-b446-85db4c6ef355/why-does-windowssystemlauncherlaunchfileasync-fail-with-file-from-my-local-folder?forum=winappswithhtml5).
Second, which was my problem, was that I wasn't on the UI thread! Switching so LaunchFileAsync was on the UI thread made it suddenly work just fine.
Do you have any application that handles VCard format? I think an applications Package.appxmanifest would need to include a section like this:
If you look at the Mail app here - it does not seem to have such a section.
"c:\Program Files\WindowsApps\microsoft.windowscommunicationsapps_16.4.4206.722_x64__8wekyb3d8bbwe\AppxManifest.xml"
*EDIT
The Mail app actually has a section that mentions <SupportsAnyFileType/>, but it is in the ShareTarget section, not a FileTypeAssociation one.
*EDIT 2
It seems like there is built in support for VCF files in Windows and this works fine for me, assuming you have TestCard.vcf file in your Documents library, have the capability to open DocumentsLibrary declared in the manifest and File Type Association declared to open .vcf files (Content type: text/vcard, File type: .vcf).