Downloaded textures blank after resuming Game

A few of the Textures in my game are downloaded at runtime from a website. Here is the code I use to download and store the texture:

    /// <summary>
    /// The texture used to render the sprite.
    /// </summary>
    private Texture2D mTexture;

    /// <summary>
    /// Downloads a texture based on a URL path, and stores it in this sprites texture.
    /// </summary>
    /// <param name="URL">The path to the file.</param>
    private void DownloadTexture(String URL)
    {
        HttpWebRequest request = HttpWebRequest.Create(new Uri(URL)) as HttpWebRequest;

        request.BeginGetResponse((ar) =>
        {
            HttpWebResponse response = request.EndGetResponse(ar) as HttpWebResponse;
            using (Stream stream = response.GetResponseStream())
            {
                using (MemoryStream ms = new MemoryStream())
                {
                    int count = 0;
                    do
                    {
                        byte[] buf = new byte[1024];
                        count = stream.Read(buf, 0, 1024);
                        ms.Write(buf, 0, count);
                    } while (stream.CanRead && count > 0);

                    ms.Seek(0, SeekOrigin.Begin);

                    mTexture = Texture2D.FromStream(GameObjectManager.pInstance.pGraphicsDevice, ms);
                }
            }
        }, null);
    }

I updated MonoGame.Android a while back to fix the issue with all textures turning black on resume. This one seems to be specific to these downloaded textures.

Here is what the texture data looks like after resuming the app:

Comparing that with the working version (prior to resume) I can see that glTexture has changed from 470 to -1 (the value on construction). So perhaps these textures get rebuilt or something behind the scenes?

I noticed this in the log:

[MonoGame] End reloading graphics content

Which seems to imply that graphic content had to be reloaded on resume. Perhaps I need to re-download all textures again too?

Yes, you have to reload textures that you load from streams (web) or create dynamically (.SetData(),RenderTargets). You can for example cache the web content to disk to avoid additional request.
ContentManager reload it’s textures automatically.

1 Like

Thanks @nkast! I ended up just overriding OnActivated from Microsoft.Xna.Framework.Game, and redownloading the content there:

protected override void OnActivated(object sender, EventArgs args)  

For the small amount of downloaded content I have, I think this makes more sense than caching (it also ensures the content is up to date in case the user resumes after a long period).

I wonder though, is there a way to hook into the ContentManager’s reload functionality, so that whenever it decided it needs to reload content, I could do the same? Ensuring that they are always in sync.

Usually I use the GraphicsDevice.DeviceReset but I guess OnActivated will work too.

ContentManager reloads textures from .XNBs, it keeps the filename for that, it has no knowledge of how or from where you load your textures.
You could write a URLTexture class to reload web content automatically or to save then onSuspend and restore them onResume.

You can sub-class the content manager and override one of the methods (called something like ReloadGraphicsResources()). I’ve done this myself but if you’re not actually using the ContentManager to load those textures, it would probably make more sense to hook into GraphicsDevice.DeviceReset. This would be better than OnActivated because often the game can be Deactivated and Activated without losing the GL context, so not requiring textures to be reloaded.