/// <summary> /// This is the main thread for the Downloader. /// This thread is responsible for queuing up downloads and other goodness. /// </summary> /// <param name="intent"> /// The intent that was recieved. /// </param> protected override void OnHandleIntent(Intent intent) { Log.Debug(Tag,"DownloaderService.OnHandleIntent"); this.IsServiceRunning = true; try { var pendingIntent = (PendingIntent)intent.GetParcelableExtra(DownloaderServiceExtras.PendingIntent); if (null != pendingIntent) { this.downloadNotification.PendingIntent = pendingIntent; this.pPendingIntent = pendingIntent; } else if (null != this.pPendingIntent) { this.downloadNotification.PendingIntent = this.pPendingIntent; } else { Log.Debug(Tag,"LVLDL Downloader started in bad state without notification intent."); return; } // when the LVL check completes, a successful response will update the service if (IsLvlCheckRequired(this.packageInfo)) { this.UpdateLvl(this); return; } // get each download List<DownloadInfo> infos = DownloadsDatabase.GetDownloads(); this.BytesSoFar = 0; this.TotalLength = 0; this.fileCount = infos.Count(); foreach (DownloadInfo info in infos) { // We do an (simple) integrity check on each file, just to // make sure and to verify that the file matches the state if (info.Status == DownloadStatus.Success && !Helpers.DoesFileExist(this, info.FileName, info.TotalBytes, true)) { info.Status = DownloadStatus.None; info.CurrentBytes = 0; } // get aggregate data this.TotalLength += info.TotalBytes; this.BytesSoFar += info.CurrentBytes; } this.PollNetworkState(); if (this.connectionReceiver == null) { // We use this to track network state, such as when WiFi, Cellular, etc. is enabled // when downloads are paused or in progress. this.connectionReceiver = new InnerBroadcastReceiver(this); var intentFilter = new IntentFilter(ConnectivityManager.ConnectivityAction); intentFilter.AddAction(WifiManager.WifiStateChangedAction); this.RegisterReceiver(this.connectionReceiver, intentFilter); } // loop through all downloads and fetch them int types = Enum.GetValues(typeof(ApkExpansionPolicy.ExpansionFileType)).Length; for (int index = 0; index < types; index++) { DownloadInfo info = infos[index]; Log.Debug(Tag,"Starting download of " + info.FileName); long startingCount = info.CurrentBytes; if (info.Status != DownloadStatus.Success) { var dt = new DownloadThread(info, this, this.downloadNotification); this.CancelAlarms(); this.ScheduleAlarm(ActiveThreadWatchdog); dt.Run(); this.CancelAlarms(); } DownloadsDatabase.UpdateFromDatabase(ref info); bool setWakeWatchdog = false; DownloaderState notifyStatus; switch (info.Status) { case DownloadStatus.Forbidden: // the URL is out of date this.UpdateLvl(this); return; case DownloadStatus.Success: this.BytesSoFar += info.CurrentBytes - startingCount; if (index < infos.Count() - 1) { continue; } DownloadsDatabase.UpdateMetadata(this.packageInfo.VersionCode, DownloadStatus.None); this.downloadNotification.OnDownloadStateChanged(DownloaderState.Completed); return; case DownloadStatus.FileDeliveredIncorrectly: // we may be on a network that is returning us a web page on redirect notifyStatus = DownloaderState.PausedNetworkSetupFailure; info.CurrentBytes = 0; DownloadsDatabase.UpdateDownload(info); setWakeWatchdog = true; break; case DownloadStatus.PausedByApp: notifyStatus = DownloaderState.PausedByRequest; break; case DownloadStatus.WaitingForNetwork: case DownloadStatus.WaitingToRetry: notifyStatus = DownloaderState.PausedNetworkUnavailable; setWakeWatchdog = true; break; case DownloadStatus.QueuedForWifi: case DownloadStatus.QueuedForWifiOrCellularPermission: // look for more detail here notifyStatus = this.wifiManager != null && !this.wifiManager.IsWifiEnabled ? DownloaderState.PausedWifiDisabledNeedCellularPermission : DownloaderState.PausedNeedCellularPermission; setWakeWatchdog = true; break; case DownloadStatus.Canceled: notifyStatus = DownloaderState.FailedCanceled; setWakeWatchdog = true; break; case DownloadStatus.InsufficientSpaceError: notifyStatus = DownloaderState.FailedSdCardFull; setWakeWatchdog = true; break; case DownloadStatus.DeviceNotFoundError: notifyStatus = DownloaderState.PausedSdCardUnavailable; setWakeWatchdog = true; break; default: notifyStatus = DownloaderState.Failed; break; } if (setWakeWatchdog) { this.ScheduleAlarm(WatchdogWakeTimer); } else { this.CancelAlarms(); } // failure or pause state this.downloadNotification.OnDownloadStateChanged(notifyStatus); return; } this.downloadNotification.OnDownloadStateChanged(DownloaderState.Completed); } catch (Exception ex) { Log.Error(Tag,ex.Message); Log.Error(Tag,ex.StackTrace); } finally { this.IsServiceRunning = false; } }
/// <summary> /// This is the main thread for the Downloader. /// This thread is responsible for queuing up downloads and other goodness. /// </summary> /// <param name="intent"> /// The intent that was recieved. /// </param> protected override void OnHandleIntent(Intent intent) { Log.Debug(Tag, "DownloaderService.OnHandleIntent"); this.IsServiceRunning = true; try { var pendingIntent = (PendingIntent)intent.GetParcelableExtra(DownloaderServiceExtras.PendingIntent); if (null != pendingIntent) { this.downloadNotification.PendingIntent = pendingIntent; this.pPendingIntent = pendingIntent; } else if (null != this.pPendingIntent) { this.downloadNotification.PendingIntent = this.pPendingIntent; } else { Log.Debug(Tag, "LVLDL Downloader started in bad state without notification intent."); return; } // when the LVL check completes, a successful response will update the service if (IsLvlCheckRequired(this.packageInfo)) { this.UpdateLvl(this); return; } // get each download List <DownloadInfo> infos = DownloadsDatabase.GetDownloads(); this.BytesSoFar = 0; this.TotalLength = 0; this.fileCount = infos.Count(); foreach (DownloadInfo info in infos) { // We do an (simple) integrity check on each file, just to // make sure and to verify that the file matches the state if (info.Status == ExpansionDownloadStatus.Success && !Helpers.DoesFileExist(this, info.FileName, info.TotalBytes, true)) { info.Status = ExpansionDownloadStatus.None; info.CurrentBytes = 0; } // get aggregate data this.TotalLength += info.TotalBytes; this.BytesSoFar += info.CurrentBytes; } this.PollNetworkState(); if (this.connectionReceiver == null) { // We use this to track network state, such as when WiFi, Cellular, etc. is enabled // when downloads are paused or in progress. this.connectionReceiver = new InnerBroadcastReceiver(this); var intentFilter = new IntentFilter(ConnectivityManager.ConnectivityAction); intentFilter.AddAction(WifiManager.WifiStateChangedAction); this.RegisterReceiver(this.connectionReceiver, intentFilter); } // loop through all downloads and fetch them int types = Enum.GetValues(typeof(ApkExpansionPolicy.ExpansionFileType)).Length; for (int index = 0; index < types; index++) { DownloadInfo info = infos[index]; Log.Debug(Tag, "Starting download of " + info.FileName); long startingCount = info.CurrentBytes; if (info.Status != ExpansionDownloadStatus.Success) { var dt = new DownloadThread(info, this, this.downloadNotification); this.CancelAlarms(); this.ScheduleAlarm(ActiveThreadWatchdog); dt.Run(); this.CancelAlarms(); } DownloadsDatabase.UpdateFromDatabase(ref info); bool setWakeWatchdog = false; DownloaderState notifyStatus; switch (info.Status) { case ExpansionDownloadStatus.Forbidden: // the URL is out of date this.UpdateLvl(this); return; case ExpansionDownloadStatus.Success: this.BytesSoFar += info.CurrentBytes - startingCount; if (index < infos.Count() - 1) { continue; } DownloadsDatabase.UpdateMetadata(this.packageInfo.VersionCode, ExpansionDownloadStatus.None); this.downloadNotification.OnDownloadStateChanged(DownloaderState.Completed); return; case ExpansionDownloadStatus.FileDeliveredIncorrectly: // we may be on a network that is returning us a web page on redirect notifyStatus = DownloaderState.PausedNetworkSetupFailure; info.CurrentBytes = 0; DownloadsDatabase.UpdateDownload(info); setWakeWatchdog = true; break; case ExpansionDownloadStatus.PausedByApp: notifyStatus = DownloaderState.PausedByRequest; break; case ExpansionDownloadStatus.WaitingForNetwork: case ExpansionDownloadStatus.WaitingToRetry: notifyStatus = DownloaderState.PausedNetworkUnavailable; setWakeWatchdog = true; break; case ExpansionDownloadStatus.QueuedForWifi: case ExpansionDownloadStatus.QueuedForWifiOrCellularPermission: // look for more detail here notifyStatus = this.wifiManager != null && !this.wifiManager.IsWifiEnabled ? DownloaderState.PausedWifiDisabledNeedCellularPermission : DownloaderState.PausedNeedCellularPermission; setWakeWatchdog = true; break; case ExpansionDownloadStatus.Canceled: notifyStatus = DownloaderState.FailedCanceled; setWakeWatchdog = true; break; case ExpansionDownloadStatus.InsufficientSpaceError: notifyStatus = DownloaderState.FailedSdCardFull; setWakeWatchdog = true; break; case ExpansionDownloadStatus.DeviceNotFoundError: notifyStatus = DownloaderState.PausedSdCardUnavailable; setWakeWatchdog = true; break; default: notifyStatus = DownloaderState.Failed; break; } if (setWakeWatchdog) { this.ScheduleAlarm(WatchdogWakeTimer); } else { this.CancelAlarms(); } // failure or pause state this.downloadNotification.OnDownloadStateChanged(notifyStatus); return; } this.downloadNotification.OnDownloadStateChanged(DownloaderState.Completed); } catch (Exception ex) { Log.Error(Tag, ex.Message); Log.Error(Tag, ex.StackTrace); } finally { this.IsServiceRunning = false; } }