[WinPhone] Display Image from StorageFolder

Hi all,
I'm currently trying to display an Image that is being saved to the StorageFolder of the App on Windows Phone. I'm using DependecyService to Save the Image, which is working on all three platforms. However I'm not able to display the Image on WinPhone, while on Android and iOS it is working as expected.

I hope someone here has an idea. Here's my simplified code

//Page where Image is displayed
public class ShowImagePage : ContentPage
{
    ShowImagePage()
    {
        //Initialize view and controls

        //Set ImageSource
        var storage = DependecyService.Get<IStorage>();
        logo.Source = ImageSource.FromFile(storage.GetLogo(filename));
        //Add logo to StackLayout and stuff
    }
}

Here is the code from the Platform projects

//On Android
public string GetLogo(string fileName)
{
    var directory = Enviroment.GetFolderPath(Enviroment.SpecialFolder.Personal);
    return Path.Combine(directory, fileName);
}

//On iOS
public string GetLogo(string fileName)
{
    var directory = Enviroment.GetFolderPath(Enviroment.SpecialFolder.Personal);
    return Path.Combine(directory, fileName + ".png");
}

//On WinPhone
public string GetLogo(string fileName)
{
    GetFileInfo(fileName);
    //Private property
    return _filePath;
}

private async void GetFileInfo(string fileName)
{
    var fileInfo = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
    _filePaht = fileInfo.Path;
}

So on WinPhone I'm getting the complete path to the Image. Which looks like this:
fileInfo.Path = "C:\Data\Users\DefApps\AppData\Local\Packages\5fefb51f-e540-47c1-8b17-151ab4b91e99_fhz98wmef0kew\LocalState\IMG_20150928_111909.jpg"

But the Image isn't getting displayed. Fun fact: Deleting the Image from the StorageFolder is no Problem.
I hope someone can help me here :)

Best Answers

  • ShantimohanElchuriShantimohanElchuri US ✭✭✭✭✭
    Accepted Answer

    I don't think it is necessary to get the file to just get its path when it is in the app's private space. Once I did the following:

    Windows.Storage.Storagefolder localFolder = ApplicationData.Current.LocalFolder;
    string path = localFolder.Path;
    string imagePath = path + filename;
    _image.Source = ImageSource.FromFile(imagePath);
    

Answers

  • tkowalczyktkowalczyk PLMember, University ✭✭

    Maybe it is because you are using here async void which is not good practice and the image is not loaded properly?

  • RaphaelSchindlerRaphaelSchindler USMember ✭✭✭

    @tkowalczyk Thanks for your answer. I didn't knew that async void is considered bad practice. So I made my research on that. You learn something every day :smile:

    Now I tried to change my code to async Task pattern, but sadly it doesn't fix my problem.

    //This is in the ShowImagePage
    public class ShowImagePage : ContentPage
    {
        public ShowImagePage()
        {
            //Initialize view and controls
    
            //Create button
            var changeImageButton = new Button
            {
                Text = "Change Image"
            };
    
            changeImageButton += async (obj, sender) => 
            {
                await ChangeImageButtonOnClicked();
            };
        }
    
        private async Task<bool> ChangeImageButtonOnClicked()
        {
            //Let the user pick the image.
    
            //Save image. This works on all Platforms.
    
            //Set image to Image Control
            var storageService = DependencyService.Get<IStorage>();
    
            switch(Device.OS)
            {
                case TargetPlatform.Android:
                case TargetPlatform.iOS:
                    _image.Source = ImageSource.FromFile(storageService.GetLogo(filename));
                    break;
                case TargetPlatform.WinPhone:
                    var imagePath = await storageService.GetLogoPathAsync(filename);
                    _image.Source = ImageSource.FromFile(imagePath);
            }
            return true;
        }
    }
    
    //Storage Service. Platform code
    public async Task<string> GetLogoPathAsync(string fileName)
    {
        var fileInfo = await Application.Current.LocalFolder.GetFileAsync(fileName);
        return fileInfo.Path;
    }
    
  • ShantimohanElchuriShantimohanElchuri USMember ✭✭✭✭✭
    Accepted Answer

    I don't think it is necessary to get the file to just get its path when it is in the app's private space. Once I did the following:

    Windows.Storage.Storagefolder localFolder = ApplicationData.Current.LocalFolder;
    string path = localFolder.Path;
    string imagePath = path + filename;
    _image.Source = ImageSource.FromFile(imagePath);
    
  • RaphaelSchindlerRaphaelSchindler USMember ✭✭✭

    @ShantimohanElchuri Thanks for your answer. It worked :smile:

    But I'm unsure if I save the file correctly. With my code I can save the Image one time. If I delete it then I get a AccessDenied Exception. And when I try to save it a second time it also throws an AccessDenied Exception.

    May you please take a look at my code and maybe tell me whats wrong with it

    private static StorageFolder Folder => Application.Current.LocalFolder;
    
    public bool Save(string filename, MediaFile data)
    {
        try
        {
            byte[] fileAsBytes;
    
            using(var stream = new MemoryStream)
            {
                data.Source.CopyTo(stream);
                fileAsBytes = stream.ToArray();
            }
    
            return WriteToDisk(filename, fileAsBytes);
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex.Message + " : " + ex.StackTrace);
            return false;
        }
    }
    
    private async Task<bool> WriteToDisk(string filename, byte[] fileAsBytes)
    {
        try
        {
            //Excpetion happens on this line of code
            var file = await Folder.CreateFileAsync(filename, CreationCollisionOptions.ReplaceExisting);
    
            using(var stream = await file.OpenStreamForWriteAsync())
            {
                stream.Write(fileAsBytes, 0, fileAsBytes.Length);
                stream.Flush();
            }
            return true;
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex.Message + " : " + ex.StackTrace);
            return false;
        }
    }   
    
  • ShantimohanElchuriShantimohanElchuri USMember ✭✭✭✭✭

    I suppose it may be due to not doing file.Close() before exiting the method. Either add file.Close() before return true; or use,

    using (var file = ...)
    {
        using (var stream = )
        {
            ... ... ...
        }
    }
    
    return true;
    
  • RaphaelSchindlerRaphaelSchindler USMember ✭✭✭

    @ShantimohanElchuri Hmm this is not working. Getting this error message. And StorageFile doesn't have Close()

    Cannot implicitly convert type Windows.Storage.StorageFile to System.IDisposable

  • VaibhavMVaibhavM USMember ✭✭

    @ShantimohanElchuri I am getting error for StorageFolder class. Can you please tell me which package is to be install for this ?

Sign In or Register to comment.