Загрузить изображение формы PersistenceDataPath - PullRequest
0 голосов
/ 26 марта 2019

Я создаю приложение для Android, которое должно вначале загружать данные из базы данных MySQL и некоторые изображения с сервера.После этого пользователь будет находиться снаружи, поэтому приложение будет работать в автономном режиме.

Я сделал код, чтобы сохранить все данные базы данных (это работает) и образ с сервера на ApplicationPersistenceDataPath (не работает),Я уже ищу, как мне это сделать.Код, который я имею, не выдает никакой ошибки.Но когда я попытался отобразить его в приложении, изображение было пустым.Вот когда я посмотрел в папку, где хранятся изображения, и я не могу открыть их.

Это метод, который я должен сохранить изображения:

IEnumerator loadBgImage(string url, string file_name)
    {
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            yield return www.Send();
            if (www.isNetworkError || www.isHttpError)
            {
                print("erro");
            }
            else
            {
                string savePath = string.Format("{0}/{1}", Application.persistentDataPath, file_name);
                if (!File.Exists(savePath))
                {
                    System.IO.File.WriteAllText(savePath, www.downloadHandler.text);
                }
            }
        }
    }

И этокод для отображения файла изображения в изображении:

string path = Application.persistentDataPath + "/" + nomeImagem;
imagem.GetComponent<SpriteRenderer>().sprite = LoadSprite(path);

Этот метод называется:

    private Sprite LoadSprite(string path)
    {
        if (string.IsNullOrEmpty(path)) return null;
        if (System.IO.File.Exists(path))
        {            
            byte[] bytes = File.ReadAllBytes(path);
            Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
            texture.filterMode = FilterMode.Trilinear;
            texture.LoadImage(bytes);
            Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);

        }
        return null;
    }

Мне действительно нужно сначала сохранить изображения, а затем отобразить их в автономном режиме.Может кто-нибудь сказать мне, что я делаю не так?

Обновление После того, как я следую советам @ derHugo, вот код, который я должен сохранить для изображений:

IEnumerator loadBgImage(string url, string file_name)
    {
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            yield return www.Send();
            if (www.isNetworkError || www.isHttpError)
            {
                print("erro");
            }
            else
            {
                var savePath = Path.Combine(Application.persistentDataPath, file_name);
                var data = www.downloadHandler.data;
                using (var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
                {
                    fs.Write(data, 0, data.Length);
                }
            }
        }
    }

Это работает, но я все еще не вижу изображения при запуске приложения.В методе показа спрайта я добавил возврат созданного спрайта.

Второе обновление

Я снова следую советам @derHugo и вместо этого использую rawImageизображения.И теперь он работает как на редакторе Unity, так и на устройстве Android.Это метод, который я использую:

private void LoadSprite(string path)
    {
        if (string.IsNullOrEmpty(path)) print("erro");
        if (System.IO.File.Exists(path))
        {
            byte[] bytes = File.ReadAllBytes(path);
            Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
            texture.filterMode = FilterMode.Trilinear;
            texture.LoadImage(bytes);
            imagem.texture = texture;
        }
    }

1 Ответ

1 голос
/ 26 марта 2019

Обычно вместо системных путей лучше использовать Path.Combine, например

var path = Path.Combine(Application.persistentDataPath, FileName);

!Возможно, ваше целевое устройство просто не понимает / как разделитель пути.


И либо напишите также, если файл уже существует (возможно, более новая версия? И вы уже загрузили его в любом случае) илиВам даже не следует начинать загрузку, если она уже существует для экономии пропускной способности.


Я также думаю, что WriteAllText не совсем правильное решение для двоичных данных изображения, поскольку www.downloadHandler.text уже

интерпретируется как строка UTF8

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

Вам лучше использовать

www.downloadHandler.data

, который вместо этого возвращает необработанный byte[] и, например, File.WriteAllBytes (только для UWP) или правильный FileStream для записи этого byte[] в файл.Что-то вроде

var data = www.downloadHandler.data;
File.WriteAllBytes(path, data);

или

var data = www.downloadHandler.data;
using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write))
{
    fs.Write(data, 0, data.Length);
}

Чем белое изображение на сцене обычно означает, что спрайт равен null.

Если его нетопечатка, чем ваш LoadSprite всегда возвращает null.Вы забыли вернуть созданные sprite

private Sprite LoadSprite(string path)
{
    if (string.IsNullOrEmpty(path)) return null;
    if (System.IO.File.Exists(path))
    {            
        byte[] bytes = File.ReadAllBytes(path);
        Texture2D texture = new Texture2D(900, 900, TextureFormat.RGB24, false);
        texture.filterMode = FilterMode.Trilinear;
        texture.LoadImage(bytes);
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);

        // You should return the sprite here!
        return sprite;
    }
    return null;
}

Однако учтите, что лучший способ загрузки также локальных изображений на самом деле UnityWebRequestTexture.В качестве URL-адреса также используется локальный путь к файлу и

. Использование этого класса значительно сокращает перераспределение памяти по сравнению с загрузкой необработанных байтов и созданием текстуры вручную в сценарии.Кроме того, преобразование текстур будет выполняться в рабочем потоке.

Но также

Поддерживаются только форматы JPG и PNG.

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

Однако это будет асинхронно, поэтому вам придется подождать текстуру, чтобысоздать спрайт.Поэтому вместо перенастройки Sprite я бы предпочел передать ссылку на соответствующий компонент Image и напрямую заменить его sprite.Что-то вроде

private IEnumerator LoadLocalTexture(string path, Image receivingImage)
{
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
    yield return www.SendWebRequest();

    if(www.isNetworkError || www.isHttpError) 
    {
        Debug.Log(www.error);
    }
    else 
    {
        var texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
        var sprite = Sprite.Create(texture, new Rect(0, 0, 8, 8), new Vector2(0.5f, 0.0f), 1.0f);

        receivingImage.sprite = sprite;
    }
}

Если вы не обязаны использовать на самом деле Sprites, я бы всегда рекомендовал вместо этого использовать RawImage компоненты, которые вместо этого могут напрямую использовать Texture2D!И затем сделать что-то вроде

private IEnumerator LoadLocalTexture(string path, RawImage receivingImage)
{
    UnityWebRequest www = UnityWebRequestTexture.GetTexture(path);
    yield return www.SendWebRequest();

    if(www.isNetworkError || www.isHttpError) 
    {
        Debug.Log(www.error);
    }
    else 
    {
        var texture = ((DownloadHandlerTexture)www.downloadHandler).texture;

        receivingImage.texture = texture;
    }
}

, но также

Примечание: имейте в виду, что использование RawImage создает дополнительный вызов отрисовки с каждым присутствующим RawImage, поэтому лучше использовать еготолько для фона или временно видимой графики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...