Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 77050

GC_MINOR: (Nursery full) -> Only on Galaxy S9 Plus of my friend

$
0
0

Hi to everyone,

a few days ago I installed my app on my friend's Samsung Galaxy S9 Plus.
Only on this device, the app is slow.
I think it's an absurd thing, considering that it is the last device released by the Samsung company.

I try to explain what happens, considering that in my app you can download multimedia content (2mb/5mb of files).

The problem appears when, after opening the page where it is possible to search and download the files (a list containing two icons and one label per line appears) I'm pressing the icon to start the download of file.
At that moment, the UI of the app freeze while all other Tasks continue to go (eg Task of download be able to download and save the file without problems).

I immediately thought that the problem was caused by too much work on the main thread (maybe caused by an animation that start as soon as the download starts). [Only on Galaxy S9 Plus of my friend?!]

I also tested the app on the Galaxy S9 Plus, available on browserstack.com, and on their devices, the application works perfectly without problems (even fast).
My friend's phone is fast and it's new (no root or similar).

I'll give you some examples with some images.

Steps:
1. List of files (icon on left, file name, icon on right. This list use FastCells)
2. Click on download (appear a new absolute layout with numer of downloads and progress bar, appear with an animation from bottom to top)
3. If you click on download info layout or swipe download info layout appear a list of separate progress for each file)

These animations work on all devices (Android and iOS), except on the Galaxy S9 Plus of my friend.

To manage the global percentage of downloads, I created an event (DownloadProgressChanged).

I show you some code.
Download method inside Android Service (called by DependencyService.Get().DownloadFile)

private void DownloadFile(string fileName, string url, string source, string id, string uniqueId)
{
    if (NetworkState == NetworkState.ConnectedData || NetworkState == NetworkState.ConnectedWifi)
    {
        // Used inside list of current downloads
        var downloadInfo = new DownloadInfo
        {
            FileName = fileName,
            Progress = 0,
            IsWriting = false, // used to show infinite progress or percentage progress
            UniqueId = uniqueId,
            DownloadStatus = DownloadStatus.Idle // waiting (infinite progress)
        };
        // Add to singleton public list of not exist
        if (!DownloadHandlers.Instance.AtomicCheck(uniqueId))
        {
            DownloadHandlers.Instance.AtomicAdd(downloadInfo);
        }
        else
        {
            downloadInfo = DownloadHandlers.Instance.CurrentDownloadsInfo.First(u => u.UniqueId == uniqueId);
        }
        // Invoke DownloadProgressEvent
        InvokeDownloadProgress();
        try
        {
            var handler = new NativeMessageHandler();
            var httpClient = new HttpClient(handler);
            handler.DisableCaching = true;

            // Change value of IsWriting field
            if (DownloadHandlers.Instance.AtomicCheck(uniqueId))
            {
                DownloadHandlers.Instance.AtomicWriting(uniqueId, true);
            }

            var webApiWrapper = new WebApiWrapper();
            Uri uri = new Uri(url);
            var credentials = XXXXXXXXXXXXXXXXXXXXXXX;
            httpClient = webApiWrapper.ExternalApiRequest(credentials?.access_token);

            // Only response header, because we download the file only after that the stream is ready to write file on disk
            using (var response = httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).Result)
            {
                var filePath = string.Empty;
                // If file not exist, write file to disk
                if (string.IsNullOrEmpty(fileName)) fileName = "Unknown_" + Guid.NewGuid().ToString("N") + ".xxx";
                fileName = Utils.Normalize(WebUtility.HtmlDecode(fileName), true);

                // Get full path where to save file
                if (!DependencyService.Get<IFilesHandler>().GetFilePath(fileName, out filePath))
                {
                    // Based on exception, throw error or retry if 401 unauthorize (with new token)
                    if (!response.IsSuccessStatusCode)
                    {
                        // Check error code and choose what to do
                        _webApiWrapper.HandleWebException(response, () =>
                        {
                            DownloadFile(fileName, url, source, id, uniqueId);
                        }, out ErrorResponse error);

                        if (error != null)
                        {
                            throw new ApiException("Unable to download file", error.Code);
                        }
                        return;
                    }

                    // Open stream to write file
                    using (var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                    {
                        var copyTask = response.Content.CopyToAsync(stream);
                        // TOP ahah
                        var length = response.Content.Headers.ContentLength ?? 15000;
                        while (!copyTask.IsCompleted && !copyTask.IsFaulted && !copyTask.IsCanceled)
                        {
                            // While we receive file data, we calculate the percentage
                            var progress = (double)stream.Position / length;
                            Device.BeginInvokeOnMainThread(() =>
                            {
                                // Set single percentage for current download list
                                if (DownloadHandlers.Instance.AtomicCheck(uniqueId))
                                    DownloadHandlers.Instance.AtomicProgress(uniqueId, progress);

                                // Set status of current download
                                downloadInfo.DownloadStatus = DownloadStatus.Downloading;

                                // Invoke DownloadProgressEvent
                                InvokeDownloadProgress();
                            });

                            Thread.Sleep(100);
                        }
                        // Close stream and Delete file if CopyTask fail
                        if (stream.Length == 0 || copyTask.IsFaulted || copyTask.IsCanceled)
                        {
                            downloadInfo.IsWriting = false;
                            stream.Close();
                            if(File.Exists(filePath)) File.Delete(filePath);
                            throw new Exception("Download Error.");
                        }
                        // Max percentage
                        downloadInfo.Progress = 1d;
                        // Save other data
                        DependencyService.Get<IFilesHandler>().WriteInfoJson(fileName, source, id, uniqueId);
                    }
                }
                else
                {
                    response?.Dispose();
                    AlertError("WarningAlertTitle".Translate(), "FileAlreadyExist".Translate(), "OkButton".Translate());
                }
            }

            // Change value of IsWriting and Status field
            if (DownloadHandlers.Instance.AtomicCheck(uniqueId))
            {
                DownloadHandlers.Instance.AtomicWriting(uniqueId, false);
                DownloadHandlers.Instance.AtomicStatus(uniqueId, DownloadStatus.Done);
            }

            // Download finished
            // Decrease number of current downloads
            Console.WriteLine("INFO: Perfect Download.");
            if (_downloadNumber > 0) _downloadNumber--;
            if (_downloadNumber == 0) _isDownload = false;

            // Invoke DownloadProgressEvent
            InvokeDownloadProgress();
        }
        catch (Exception ex)
        {
            .............
        }
    }
    else
    {
        // No internet connection
    }
}

InvokeDownloadProgress method

private void InvokeDownloadProgress()
{
    // Calculate total progress
    var progress = DownloadHandlers.Instance.TotalProgress();
    // Invoke with EventArgs
    DownloadProgressChanged?.Invoke(null, new DownloadProgressChangedEventArgs
    {
        DownloadNumber = _downloadNumber,
        TotalProgress = progress
    });
}

On form side, page code (OnAppearing)

DependencyService.Get<IServerTasks>().DownloadProgressChanged += DownloadProgressChanged;

where DownloadProgressChanged method

private int _downloadNumber = -1;

private void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
    var downloadNumber = e.DownloadNumber;
    // Invoke main thread async for animation
    Device.BeginInvokeOnMainThread(async () =>
    {
        // Check current downloads
        if (Math.Abs(e.TotalProgress) < 0.0000001 || downloadNumber == 0)
        {
            progressBar.Progress = 0;
            return;
        }

        // Update progress bar value
        progressBar.Progress = e.TotalProgress / downloadNumber;

        // If there is at least one download, change value of label inside download info layout
        if (downloadNumber > 0 && _downloadNumber != downloadNumber)
        {
            _downloadNumber = downloadNumber;
            lbInfoDownload.Text = string.Format("MultipleDownloadInfoText".Translate(), downloadNumber);

            // If download info layout is not visible
            if (!infoDetailedView.IsVisible)
            {
                // Animate layout from bottom to top
                infoDetailedView.TranslationY = infoDetailedView.Height;
                infoDetailedView.IsVisible = true;
                await infoDetailedView.TranslateTo(0, infoDetailedView.Height - iosRow.Height.Value, 350, Easing.Linear);
            }

            // Change margin of List, so that by scrolling we can see all the elements hidden by download info layout
            layoutList.Margin = new Thickness(0, 0, 0, iosRow.Height.Value);
        }
    });
}

There are other methods used to animate the download info layout (touch and swipe) but it is not necessary to show them because the UI freeze before displaying this layout.


Viewing all articles
Browse latest Browse all 77050

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>