Xamarin.Forms: Как загрузить изображение, сохранить его локально и отобразить на экране? - PullRequest
2 голосов
/ 07 января 2020

У меня проблема с открытием файла JPG в собственном приложении на Android. Я использую новейшую версию Xamarin Essentials, есть некоторая функциональность под названием Launcher. Вот мой код

await Launcher.TryOpenAsync("file:///" + localPath);

Мой локальный путь - это файл, который хранится в Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);.

Когда я пытаюсь открыть этот файл, я получаю сообщение об ошибке:

file:////data/user/0/mypackagename/files/.local/share/Screenshot.jpg exposed beyond app through Intent.getData()

Я нашел несколько решений здесь для stackoverflow, но я не хочу использовать Intent, потому что мое приложение разработано, чтобы быть кроссплатформенным (я хотел бы избежать кодирования нативной платформы, если это возможно).

Launcher throws ошибка на iOS также:

canOpenURL: failed for URL: ** -- file:///" - error: "This app is not allowed to query for scheme file

Что я здесь не так делаю?

1 Ответ

7 голосов
/ 07 января 2020

Шаг 1. Загрузка изображения

Мы можем использовать HttpClient для загрузки изображения.

HttpClient.GetByteArrayAsync извлечет данные изображения и сохранит их в памяти.

В DownloadImage ниже мы получим изображение в виде byte[].

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }
}

Шаг 2 Сохранение изображения на диск

Теперь, когда мы загрузили изображение, мы сохранит его на диск.

Xamarin.Essentials.Preferences позволяет нам сохранять элементы на диск, используя пары ключ-значение. Поскольку byte[] - это просто указатель на память, нам нужно сначала преобразовать byte[] в base64-строку, прежде чем мы сможем сохранить его на диск.

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }

    public static void SaveToDisk(string imageFileName, byte[] imageAsBase64String)
    {
        Xamarin.Essentials.Preferences.Set(imageFileName, Convert.ToBase64String(imageAsBase64String));
    }
}

Шаг 3 Получить изображение для отображения

Теперь, когда мы загрузили изображение и сохранили его на диск, нам нужно иметь возможность извлечь изображение с диска, чтобы отобразить его на экране.

GetFromDisk ниже возвращает образ с диска и преобразует его в Xamarin.Forms.ImageSource.

static class ImageService
{
    static readonly HttpClient _client = new HttpClient();

    public static Task<byte[]> DownloadImage(string imageUrl)
    {
        if (!imageUrl.Trim().StartsWith("https", StringComparison.OrdinalIgnoreCase))
            throw new Exception("iOS and Android Require Https");

        return _client.GetByteArrayAsync(imageUrl);
    }

    public static void SaveToDisk(string imageFileName, byte[] imageAsBase64String)
    {
        Xamarin.Essentials.Preferences.Set(imageFileName, Convert.ToBase64String(imageAsBase64String));
    }

    public static Xamarin.Forms.ImageSource GetFromDisk(string imageFileName)
    {
        var imageAsBase64String = Xamarin.Essentials.Preferences.Get(imageFileName, string.Empty);

        return ImageSource.FromStream(() => new MemoryStream(Convert.FromBase64String(imageAsBase64String)));
    }
}

Пример: использование ImageService в Xamarin.Forms.ContentPage

class App : Application
{
    public App() => MainPage = new MyPage();
}

class MyPage : ContentPage
{
    readonly Image _downloadedImage = new Image();

    public MyPage()
    {
        Content = _downloadedImage;
    }

    protected override  async void OnAppearing()
    {
        const string xamrainImageUrl = "https://cdn.dribbble.com/users/3701/screenshots/5557667/xamarin-studio-1_2x_4x.png"
        const string xamarinImageName = "XamarinLogo.png";

        var downloadedImage = await ImageService.DownloadImage(xamrainImageUrl);

        ImageService.SaveToDisk(xamarinImageName, downloadedImage);

        _downloadedImage.Source = ImageService.GetFromDisk(xamarinImageName);
    }
}

enter image description here

...