QLPreview works in Simulator, but only shows Title and File Type on device

MattHenthornMattHenthorn USMember ✭✭
edited July 2018 in Xamarin.iOS

Hello,

I'm using a UIDocumentMenuViewController to allow the selection of files. File metadata, along with the File's URL are stored and displayed in a table.
When a table row is selected, I need to display a preview of the selected file. I'm using the QLPreviewItem class to do this and it works exactly as expected from a simulator, but simply shows the title I pass to the class along with the file type when I deploy to a device.

Here's my document picker event handler:

 private void DocumentPicker_DidPickDocumentAtUrls(object sender, UIDocumentPickedAtUrlsEventArgs e)
    {
        var securityEnabled = e.Urls[0].StartAccessingSecurityScopedResource();

        NSFileCoordinator fileCoordinator = new NSFileCoordinator();
        NSError err;

        fileCoordinator.CoordinateRead(e.Urls[0], 0, out err, (NSUrl newUrl) => {
            NSData data = NSData.FromUrl(newUrl);
            Console.WriteLine("Data: {0}", data);

            //Save new attachment with newUrl.Path
        });

        e.Urls[0].StopAccessingSecurityScopedResource();
    }

Here's my QL code:

QLPreviewController qlPreview = new QLPreviewController();
qlPreview.DataSource = new PreviewDataSource(NSUrl.FromFilename(URLString)); //This is the URL we saved from the event handler
parent.PresentViewController(qlPreview, true, null);

 public class PreviewItem : QLPreviewItem
 {
    public string Title { get; set; }
    public NSUrl Url { get; set; }
    public override string ItemTitle { get { return Title; } }
    public override NSUrl ItemUrl { get { return Url; } }
 }

public class PreviewDataSource : QLPreviewControllerDataSource
{
    private NSUrl _url;

    public PreviewDataSource(NSUrl url)
    {
        _url = url;
    }

    public override nint PreviewItemCount(QLPreviewController controller)
    {
        return 1;
    }

    public override IQLPreviewItem GetPreviewItem(QLPreviewController controller, nint index)
    {
        return new PreviewItem { Title = "Document Preview", Url = _url };
    }
}

Sorry for the code formatting. Not sure how to get it right on here.

Any ideas where I'm going wrong?

Thanks!

Best Answer

Answers

  • MattHenthornMattHenthorn USMember ✭✭

    Yep, that ended up being the problem. I had tried that solution early on, but must have had something dumb in which part of the file path/URL I was using for retrieval. I tried it again after I'd exhausted everything else and got it working.

    Here's what I ended up with (QLPreview code unchanged from above)

    private void DocumentPicker_DidPickDocumentAtUrls(object sender, UIDocumentPickedAtUrlsEventArgs e)
    {
    var securityEnabled = e.Urls[0].StartAccessingSecurityScopedResource();

            NSFileCoordinator fileCoordinator = new NSFileCoordinator();
            NSError err;
    
            fileCoordinator.CoordinateRead(e.Urls[0], 0, out err, (NSUrl newUrl) => {
    
                var data = NSData.FromUrl(newUrl);
                byte[] dataBytes = new byte[data.Length];
                System.Runtime.InteropServices.Marshal.Copy(data.Bytes, dataBytes, 0, Convert.ToInt32(data.Length));
    
                SaveFile(newUrl.LastPathComponent, dataBytes);
            });
    
            // IMPORTANT! You must release the security lock established
            // above.
            e.Urls[0].StopAccessingSecurityScopedResource();
        }
    

    public async void SaveFile(String filename, byte[] decompressed)
    {
    try
    {
    var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    var path = Path.Combine(documentsPath, filename); //This is the path we use when creating the qlPreview Datasource
    File.WriteAllBytes(path, decompressed);
    }
    catch(Exception ex)
    {
    var x = 1;
    }
    }

  • MattHenthornMattHenthorn USMember ✭✭

    Yep, that ended up being the problem. I had tried that solution early on, but must have had something dumb in which part of the file path/URL I was using for retrieval. I tried it again after I'd exhausted everything else and got it working.

    Here's what I ended up with (QLPreview code unchanged from above)

    private void DocumentPicker_DidPickDocumentAtUrls(object sender, UIDocumentPickedAtUrlsEventArgs e)
    {
    var securityEnabled = e.Urls[0].StartAccessingSecurityScopedResource();

            NSFileCoordinator fileCoordinator = new NSFileCoordinator();
            NSError err;
    
            fileCoordinator.CoordinateRead(e.Urls[0], 0, out err, (NSUrl newUrl) => {
    
                var data = NSData.FromUrl(newUrl);
                byte[] dataBytes = new byte[data.Length];
                System.Runtime.InteropServices.Marshal.Copy(data.Bytes, dataBytes, 0, Convert.ToInt32(data.Length));
    
                SaveFile(newUrl.LastPathComponent, dataBytes);
            });
    
            // IMPORTANT! You must release the security lock established
            // above.
            e.Urls[0].StopAccessingSecurityScopedResource();
        }
    

    public async void SaveFile(String filename, byte[] decompressed)
    {
    try
    {
    var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
    var path = Path.Combine(documentsPath, filename); //This is the path we use when creating the qlPreview Datasource
    File.WriteAllBytes(path, decompressed);
    }
    catch(Exception ex)
    {
    var x = 1;
    }
    }

Sign In or Register to comment.