How to stop UnityWebRequest Download in android?

Viewed 1639

I am trying to figure out how to stop UnityWebRequest download immediately with a button in android application.

Stopping coroutine with StopCoroutine("downLoadFromServer"); does not stop UnityWebRequest. I tried using UnityWebRequest.Dispose(); or UnityWebRequest.Abort(); with no success. Below is the download i'm trying to stop.

private IEnumerator downLoadFromServer()
{

    var url = "https://example.com/app.apk"; 
    var savePath = Path.Combine(Application.persistentDataPath, "data", "app.apk");              

    using (var uwr = UnityWebRequest.Get(url))
    {
        uwr.SetRequestHeader("Authorization", "Basic " + System.Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes("test:test")));
        uwr.SendWebRequest();

        while (!uwr.isDone)
        {
            progressText.text = $"Progress: {uwr.downloadProgress:P}";
            yield return null;
        }

        var yourBytes = uwr.downloadHandler.data;

        progressText.text = $"Done downloading. Size: {yourBytes.Length}";

        //Create Directory if it does not exist
        var directoryName = Path.GetDirectoryName(savePath);
        if (!Directory.Exists(directoryName))
        {
             Directory.CreateDirectory(directoryName);
            progressText.text = "Created Dir";
        }

        try
        {
            //Now Save it
            System.IO.File.WriteAllBytes(savePath, yourBytes);
            Debug.Log("Saved Data to: " + savePath.Replace("/", "\\"));
            progressText.text = "Saved Data";
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Save Data to: " + savePath.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
            progressText.text = "Error Saving Data";
        }
    }

    //Install APK
    installApp(savePath);
}

Thank you, Chris

1 Answers

You are right: Stopping the Coroutine does not cancel the UnityWebRequest, you are just not keeping track of it anymore.

Actually UnityWebRequest.Abort should do exactly that

If in progress, halts the UnityWebRequest as soon as possible.

This method may be called at any time. If the UnityWebRequest has not already completed, the UnityWebRequest will halt uploading or downloading data as soon as possible. Aborted UnityWebRequests are considered to have encountered a system error. Either the isNetworkError or the isHttpError property will return true and the error property will be "User Aborted".

However this makes ofcourse only sense if you actually check the result of the request which currently you aren't doing and you should do anyway!

A way to use it would be to make the uwr a class wide field so you can access it from somewhere else and as said actually add a check if the download succeeded:

private UnityWebRequest uwr;

private IEnumerator downLoadFromServer()
{
    ...

    // NOTE: Remove the var so the class field uwr is assigned to, not only
    // a local variable
    using(uwr = UnityWebRequest.Get(...))
    {
        ...

        // Always check if a request was actually successful before continuing
        if(uwr.isHttpError || uwr.isNetworkError || !string.IsNullOrWhiteSpace(uwr.error))
        {
            Debug.LogWarning($"Download Failed with {uwr.responseCode}, reason: {uwr.error}", this);

            progressText.text = $"Download Failed: {uwr.error}";

            // Cancel this Coroutine
            yield break;
        }

        var yourBytes = uwr.downloadHandler.data;

        ...
    }

    //Install APK
    installApp(savePath);
}

Then you can simply do

public void AbortDownload()
{
    if(uwr != null && !uwr.isDone)
    {
        Debug.Log("Aborting download ...", this);
        uwr.Abort();
    }
    else
    {
        Debug.Log("Not downloading, nothing to do ...", this);
    }
}

which should make the download "fail" and thereby also finish the Coroutine

Related