How can I open a .pdf file in the browser from a Xamarin UWP project? - c#

I have a Xamarin Project where I generate a .pdf file from scratch and save it in my local storage. This works perfectly fine and can find it and open it in the disk where I saved it. However, I need to open the .pdf file immediately after creation programmatically.
I already tried different variations using Process and ProcessStartInfo but these just throw errors like "System.ComponentModel.Win32Exception: 'The system cannot find the file specified'" and "'System.PlatformNotSupportedException'".
This is basically the path I am trying to open using Process.
var p = Process.Start(#"cmd.exe", "/c start " + #"P:\\Receiving inspection\\Inspection Reports\\" + timestamp + ".pdf");
I also tried ProcessStartInfo using some variations but I'm getting the same errors all over and over.
var p = new Process();
p.StartInfo = new ProcessStartInfo(#"'P:\\Receiving inspection\\Inspection Reports\\'" + timestamp + ".pdf");
p.Start();

The better way is that use LaunchFileAsync method to open file with browser. You could create FileLauncher DependencyService to invoke uwp LaunchFileAsync method from xamarin share project.
Interface
public interface IFileLauncher
{
Task<bool> LaunchFileAsync(string uri);
}
Implementation
[assembly: Dependency(typeof(UWPFileLauncher))]
namespace App14.UWP
{
public class UWPFileLauncher : IFileLauncher
{
public async Task<bool> LaunchFileAsync(string uri)
{
var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(uri);
bool success = false;
if (file != null)
{
// Set the option to show the picker
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
// Launch the retrieved file
success = await Windows.System.Launcher.LaunchFileAsync(file, options);
if (success)
{
// File launched
}
else
{
// File launch failed
}
}
else
{
// Could not
}
return success;
}
}
}
Usage
private async void Button_Clicked(object sender, EventArgs e)
{
await DependencyService.Get<IFileLauncher>().LaunchFileAsync("D:\\Key.pdf");
}
Please note if you want to access D or C disk in uwp, you need add broadFileSystemAccess capability. for more please refer this .
Update
If the UWP files are network based, not local zone based, you could use Xamarin.Essentials to open file with browser. And you must specify the privateNetworkClientServer capability in the manifest. For more please refer this link.

Related

PCLStorage NuGetPackage not allow creating folder or file on device

I have a problem with creating folder with nuget package PCLStorage, I cannot create folder.
Nothing appear inside my files folder. I,m using my device not emulator there is android version 8.0
public async Task WriteDataAsync(string filename, string data)
{
string folderName = "SignatureSotrage";
IFolder folder = FileSystem.Current.LocalStorage;
folder = await folder.CreateFolderAsync(folderName, CreationCollisionOption.ReplaceExisting);
}
Here is a code where I run this function:
public ICommand AddCustomerCommand => new Command(async () =>
{
Signature = await SignatureFromStream();
// Signature should be != null
var customer = new Customer()
{
FullName = this.FullName,
IsAccepted = this.IsAccepted,
Birthday = this.Birthday
};
if(Signature != null)
{
customer.Image = this.Signature.ToString();
}
else
{
await Application.Current.MainPage.DisplayAlert("Błąd", "Nie wszystkie pola zostały poprawnie wypełnione", "OK");
return;
}
await DependencyService.Get<IFileHelper>().WriteDataAsync("signature.txt", "this is file");
//_context.Customers.Add(customer);
//_context.SaveChanges();
});
did you debug your code & check if the file/folder is actually getting created by your code or else it enters the catch block and goes with the normal flow?
Check for UserPermissions every time for reading & write permission before doing any operations on the storage. You can add the Nugget packet Plugin.Permission it handles everything for you, it adds both the permission in the manifest.
For checking user permissions always try calling CheckForStoragePermissions() before performing any operations on storage.(*DialogService is CustomDialogBox)
if( !await CheckForStoragePermissions() )
{
DialogService.Alert("Invalid Permission", "User declined permission for this action");
return;
}
private async Task<bool> CheckForStoragePermissions()
{
PermissionStatus storagePermissionStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Storage);
if (storagePermissionStatus != PermissionStatus.Granted)
{
Dictionary<Permission, PermissionStatus> storagePermissionResult = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Storage);
if (storagePermissionResult.ContainsKey(Permission.Storage))
{
storagePermissionStatus = storagePermissionResult[Permission.Storage];
}
}
return storagePermissionStatus == PermissionStatus.Granted;
}
I test the sample code on GitHub. https://github.com/dsplaisted/PCLStorage
Based on my test the folder path would like:
/data/user/0/PCLStorage.Test.Android/files/
It is a internal storage. You couldn't see the files without root permission. https://learn.microsoft.com/en-us/xamarin/android/platform/files/#working-with-internal-storage
If you want to see the files in internal storage, you could use adb tool. Please refer to the way in the link. How to write the username in a local txt file when login success and check on file for next login?

UWP Check If File Exists

I am currently working on a Windows 10 UWP App.
The App needs to Check if a certain PDF File exists called "01-introduction", and if so open it.
I already have the code for if the file does not exist.
The Code Below is what i currently have:
try
{
var test = await DownloadsFolder.CreateFileAsync("01-Introduction.pdf", CreationCollisionOption.FailIfExists);
}
catch
{
}
This code Does not work correctly because to check if the file exists here, I attempt to create the file. However if the file does not already exist an empty file will be created. I do not want to create anything if the file does not exist, just open the PDF if it does.
If possible, i would like to look inside a folder which is in the downloads folder called "My Manuals".
Any help would be greatly appreciated.
public async Task<bool> IsFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
But not support Win8/WP8.1
https://blogs.msdn.microsoft.com/shashankyerramilli/2014/02/17/check-if-a-file-exists-in-windows-phone-8-and-winrt-without-exception/
There are two methods
1) You can use StorageFolder.GetFileAsync() as this is also supported by Windows 8.1 and WP 8.1 devices.
try
{
StorageFile file = await DownloadsFolder.GetFileAsync("01-Introduction.pdf");
}
catch
{
Debug.WriteLine("File does not exits");
}
2) Or you can use FileInfo.Exists only supported for windows 10 UWP.
FileInfo fInfo = new FileInfo("01-Introduction.pdf");
if (!fInfo.Exists)
{
Debug.WriteLine("File does not exits");
}
System.IO.File.Exists is UWP way too. I test now in Windows IOT. it just works.
This helped me in my case:
ApplicationData.Current.LocalFolder.GetFileAsync(path).AsTask().ContinueWith(item => {
if (item.IsFaulted)
return; // file not found
else { /* process file here */ }
});
This worked for me running my UWP C# app on Windows 10...
StorageFolder app_StorageFolder = await StorageFolder.GetFolderFromPathAsync( #App.STORAGE_FOLDER_PATH );
var item = await app_StorageFolder.TryGetItemAsync(relative_file_pathname);
return item != null;
public override bool Exists(string filePath)
{
try
{
string path = Path.GetDirectoryName(filePath);
var fileName = Path.GetFileName(filePath);
StorageFolder accessFolder = StorageFolder.GetFolderFromPathAsync(path).AsTask().GetAwaiter().GetResult();
StorageFile file = accessFolder.GetFileAsync(fileName).AsTask().GetAwaiter().GetResult();
return file != null;
}
catch
{
return false;
}
}
You can use System.IO.File.
Example:
// If file located in local folder. You can do the same for other locations.
string rootPath = ApplicationData.Current.LocalFolder.Path;
string filePath = Path.Combine(rootPath, "fileName.pdf");
if (System.IO.File.Exists(filePath))
{
// File exists
}
else
{
// File doesn't exist
}
I'm doing a Win10 IoT Core UWP app and I have to check the file length instead of "Exists" because CreateFileAsync() already creates an empty file stub immediately. But I need that call before to determine the whole path the file will be located at.
So it's:
var destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("MyFile.wow", ...);
if (new FileInfo(destinationFile.Path).Length > 0)
return destinationFile.Path;
In this way System.IO.File.Exists(filePath) I cannot test DocumentLibrary
because KnownFolders.DocumentsLibrary.Path return empty string
Next solution is very slow await DownloadsFolder.GetFileAsync("01-Introduction.pdf")
IMHO the best way is collect all files from folder and check the file name exist.
List<StorageFile> storageFileList = new List<StorageFile>();
storageFileList.AddRange(await KnownFolders.DocumentsLibrary.GetFilesAsync(CommonFileQuery.OrderByName));
bool fileExist = storageFileList.Any(x => x.Name == "01-Introduction.pdf");
CreateFileSync exposes an overload that let's you choose what to do if an existing file with the same name has been found in the directory, as such:
StorageFile localDbFile = await DownloadsFolder.CreateFileAsync(LocalDbName, CreationCollisionOption.OpenIfExists);
CreationCollisionOption is the object that you need to set up. In my example i'm opening the file instead of creating a new one.
Based on another answer here, I like
public static async Task<bool> DoesFileExist(string filePath) {
var directoryPath = System.IO.Path.GetDirectoryName(filePath);
var fileName = System.IO.Path.GetFileName(filePath);
var folder = await StorageFolder.GetFolderFromPathAsync(directoryPath);
var file = await folder.TryGetItemAsync(fileName);
return file != null;
}
You can use the FileInfo class in this case. It has a method called FileInfo.Exists() which returns a bool result
https://msdn.microsoft.com/en-us/library/system.io.fileinfo.exists(v=vs.110).aspx
EDIT:
If you want to check for the files existence, you will need to create a StorageFile object and call one of the GetFile.... methods. Such as:
StorageFile file = new StorageFile();
file.GetFileFromPathAsync("Insert path")
if(file == null)
{
/// File doesn't exist
}
I had a quick look to find the download folder path but no joy, but the GetFile method should give you the answer your looking for
On Window 10, for me, this is the most "elegant" way:
private static bool IsFileExistent(StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
Or, as an extension if you prefer and will use it widely:
static class Extensions
{
public static bool Exists(this StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
}

Closed Captions resolving error System.UnauthorizedAccessException

So, I'm trying to implement closed captions support to my UWP video player (using MediaElement), I've followed this example to do so.
I'm getting an error when resolving it called "Error resolving track due to error NetworkError System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
I do it like this: I open a file using filepicker and then get the SRT of the video that was picked. After that I show it. Unfortunately, nothing appears.
Here is my OpenButton function:
private async void BtnOpenMedia_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.ViewMode = PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;
filePicker.FileTypeFilter.Add(".mp4");
filePicker.FileTypeFilter.Add(".wmv");
filePicker.FileTypeFilter.Add(".mpg");
filePicker.FileTypeFilter.Add(".mpeg");
filePicker.FileTypeFilter.Add("*");
StorageFile storageFile = await filePicker.PickSingleFileAsync();
if (storageFile != null && mElement != null)
{
string strSource = Path.GetDirectoryName(storageFile.Path) + #"\" + storageFile.DisplayName + ".srt";
var mediaSource = MediaSource.CreateFromStorageFile(storageFile);
var ttsStream = TimedTextSource.CreateFromUri(new Uri(strSource));
ttsStream.Resolved += TtsStream_Resolved;
mediaSource.ExternalTimedTextSources.Add(ttsStream);
var mediaPlayback = new MediaPlaybackItem(mediaSource);
mElement.SetPlaybackSource(mediaPlayback);
}
}
Here is my resolve function:
private void TtsStream_Resolved(TimedTextSource sender, TimedTextSourceResolveResultEventArgs args)
{
if (args.Error != null)
{
var ignoreAwaitWarning = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
var msg = new MessageDialog("Error resolving track " + " due to error " + args.Error.ErrorCode + " " + args.Error.ExtendedError);
await msg.ShowAsync();
});
return;
}
}
P.S: Also, I don't know if this is duplicated or not, that's why I'm adding it in this but I've done my research and found nothing. How to preview frames of MediaElement ? For example like YouTube you can preview thumbnails in the slider, I don't know how to achieve that, thanks!
You used a FileOpenPicker to select the Video file, but use a Path to access the .srt file. The .srt file is also in the Video file's folder. I reproduced your problem here:
The error message is clear, you have no access to this file, this file indicates the .srt file, so the problem is where did you store this .srt file. Just have a test, seems TimedTextSource.CreateFromUri(Uri) | createFromUri(Uri) method does not support to access the files in the local machine, but you can use TimedTextSource.CreateFromStream(IRandomAccessStream) | createFromStream(IRandomAccessStream) method for example like this:
if (storageFile != null && mElement != null)
{
//string strSource = Path.GetDirectoryName(storageFile.Path) + #"\" + storageFile.DisplayName + ".srt";
var fileSource = await KnownFolders.VideosLibrary.GetFileAsync(storageFile.DisplayName + ".srt");
IRandomAccessStream strSource = await fileSource.OpenReadAsync();
var mediaSource = MediaSource.CreateFromStorageFile(storageFile);
//var ttsStream = TimedTextSource.CreateFromUri(new Uri(strSource));
var ttsStream = TimedTextSource.CreateFromStream(strSource);
ttsStream.Resolved += TtsStream_Resolved;
mediaSource.ExternalTimedTextSources.Add(ttsStream);
var mediaPlayback = new MediaPlaybackItem(mediaSource);
mediaPlayback.TimedMetadataTracksChanged += (sender1, args) =>
{
mediaPlayback.TimedMetadataTracks.SetPresentationMode(0, TimedMetadataTrackPresentationMode.PlatformPresented);
};
mElement.SetPlaybackSource(mediaPlayback);
}
When using this code, the .srt file and video file should in the Video lib and the capability "Videos Library" should be enabled in the manifest.
In an UWP app, you can only access the files in known folder like picture lib, music lib and video lib and doc lib or local folder of your app, if your video is not in these folders, you should also handle the exception when access is denied in this scenario.
How to preview frames of MediaElement ? For example like YouTube you can preview thumbnails in the slider.
For this question, I can't find any ready-made sample for you, but I think the scenario 4 of official Media editing sample can be a direction, it shows a overlay layer on MediaElement, maybe you can set the "baseVideoFile" and the "overlayVideoFile" with the same source. The problem is when and where to show this overlay layer, it's related to the transport control of MediaElement. This is for now just a mind, you can have a try.

How to allow usage of FilePicker in WindowsStore App?

Using c#, Windows Store App, VS 2013
Try to open File Picker, using next simple code:
private async void OkBtnClick(IUICommand command)
{
if (this.EnsureUnsnapped())
{
FileOpenPicker fop = new FileOpenPicker();
fop.FileTypeFilter.Add(".png");
fop.FileTypeFilter.Add(".jpg");
fop.FileTypeFilter.Add(".jpeg");
fop.ViewMode = PickerViewMode.Thumbnail;
fop.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
StorageFile requestedFile = await fop.PickSingleFileAsync();
if (requestedFile != null)
{
//TODO:
}
}
}
internal bool EnsureUnsnapped()
{
// FilePicker APIs will not work if the application is in a snapped state.
// If an app wants to show a FilePicker while snapped, it must attempt to unsnap first
bool unsnapped = ((ApplicationView.Value != ApplicationViewState.Snapped)
|| ApplicationView.TryUnsnap());
if (!unsnapped)
{
Extensions.NotifyUser("Cannot unsnap app...", statusNotificationBlock);
}
return unsnapped;
}
Also add capability in appmanifest file for Pictures Library:
But during running got exception : System.UnauthorizedAccessException on line StorageFile requestedFile = await fop.PickSingleFileAsync();.
Question: Why I got this exception if all required access provided, Also i try to launch VS2013 with Administrator rights - result - same.
For creating this code use this article

Open PDF using C#-- Windows 8 Store Application

I want to be able to open a PDF using the native Windows Reader Application when a user clicks on a button. So far I am able to use the following code to successfully open files that end with the (.PNG) extension. However, when I let the link to open the (.PDF) file I get the following error.
The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
The file destination is correct.
Here is my code:
private async void btnLoad_Click(object sender, RoutedEventArgs e)
{
// Path to the file in the app package to launch
string imageFile = #"Data\Healthcare-Flyer.pdf";
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFile);
if (file != null)
{
// Set the option to show the picker
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
// Launch the retrieved file
bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
if (success)
{
// File launched
}
else
{
// File launch failed
}
}
else
{
// Could not find file
}
}
}
When you add PDF document in project, you have to change it's build action.
Right click on PDF document.
Click on properties.
Change Build Action from None to Content

Categories