/// <summary> /// Report download progress through the database if necessary. /// </summary> /// <param name="innerState"> /// The inner State. /// </param> private void ReportProgress(InnerState innerState) { long now = PolicyExtensions.GetCurrentMilliseconds(); if (innerState.BytesSoFar - innerState.BytesNotified > DownloaderService.MinimumProgressStep && now - innerState.TimeLastNotification > DownloaderService.MinimumProgressTime) { // we store progress updates to the database here this.downloadInfo.CurrentBytes = innerState.BytesSoFar; DownloadsDatabase.UpdateDownloadCurrentBytes(this.downloadInfo); innerState.BytesNotified = innerState.BytesSoFar; innerState.TimeLastNotification = now; long totalBytesSoFar = innerState.BytesThisSession + this.downloaderService.BytesSoFar; Debug.WriteLine( "DownloadThread : downloaded {0} out of {1}", this.downloadInfo.CurrentBytes, this.downloadInfo.TotalBytes); Debug.WriteLine( "DownloadThread : total {0} out of {1}", totalBytesSoFar, this.downloaderService.TotalLength); this.downloaderService.NotifyUpdateBytes(totalBytesSoFar); } }
/// <summary> /// The do validate zip files. /// </summary> /// <param name="state"> /// The state. /// </param> private void DoValidateZipFiles(object state) { var downloads = DownloadsDatabase.GetDownloads().Select(x => Helpers.GenerateSaveFileName(this, x.FileName)).ToArray(); var result = downloads.Any() && downloads.All(this.IsValidZipFile); this.RunOnUiThread( delegate { this.pauseButton.Click += delegate { Finish(); StartActivity(typeof(ZipTestActivity)); }; this.dashboardView.Visibility = ViewStates.Visible; this.useCellDataView.Visibility = ViewStates.Gone; if (result) { this.statusTextView.SetText(Resource.String.text_validation_complete); this.pauseButton.SetText(Android.Resource.String.Ok); } else { this.statusTextView.SetText(Resource.String.text_validation_failed); this.pauseButton.SetText(Android.Resource.String.Cancel); } }); }
private void DoValidateZipFiles(object state) { var downloads = DownloadsDatabase.GetDownloads().Select(x => Helpers.GenerateSaveFileName(this, x.FileName)).ToArray(); var result = downloads.Any() && downloads.All(IsValidZipFile); RunOnUiThread(delegate { pauseButton.Click += delegate { HideAllControls(); StorehouseInitializationParadigm(); }; dashboardView.Visibility = ViewStates.Visible; useCellDataView.Visibility = ViewStates.Gone; if (result) { statusTextView.SetText(Resource.String.text_validation_complete); pauseButton.SetText(Android.Resource.String.Ok); } else { statusTextView.SetText(Resource.String.text_validation_failed); pauseButton.SetText(Android.Resource.String.Cancel); } // I ADDED THESE METHODS HideAllControls(); StorehouseInitializationParadigm(); }); }
/// <summary> /// Called when we've reached the end of the HTTP response stream, to update the database and /// check for consistency. /// </summary> /// <param name="state"> /// The state. /// </param> /// <param name="innerState"> /// The inner State. /// </param> private void HandleEndOfStream(State state, InnerState innerState) { Debug.WriteLine("HandleEndOfStream"); this.downloadInfo.CurrentBytes = innerState.BytesSoFar; //// this should always be set from the market // if (innerState.HeaderContentLength == null) // { // downloadInfo.TotalBytes = innerState.BytesSoFar; // } DownloadsDatabase.UpdateDownload(this.downloadInfo); bool lengthMismatched = innerState.HeaderContentLength != null && innerState.BytesSoFar != int.Parse(innerState.HeaderContentLength); if (lengthMismatched) { string message; ExpansionDownloadStatus finalStatus; if (CannotResume(innerState)) { finalStatus = ExpansionDownloadStatus.CannotResume; message = "mismatched content length"; } else { finalStatus = this.GetFinalStatusForHttpError(state); message = "closed socket before end of file"; } throw new StopRequestException(finalStatus, message); } }
/// <summary> /// Read some data from the HTTP response stream, handling I/O errors. /// </summary> /// <param name="state"> /// </param> /// <param name="innerState"> /// </param> /// <param name="data"> /// data buffer to use to read data /// </param> /// <param name="entityStream"> /// entityStream stream for reading the HTTP response entity /// </param> /// <returns> /// the number of bytes actually read or -1 if the end of the stream has been reached /// </returns> private int ReadFromResponse(State state, InnerState innerState, byte[] data, Stream entityStream) { try { return(entityStream.Read(data, 0, data.Length)); } catch (IOException ex) { this.LogNetworkState(); this.downloadInfo.CurrentBytes = innerState.BytesSoFar; DownloadsDatabase.UpdateDownload(this.downloadInfo); string message; ExpansionDownloadStatus finalStatus; if (CannotResume(innerState)) { finalStatus = ExpansionDownloadStatus.CannotResume; message = string.Format("while reading response: {0}, can't resume interrupted download with no ETag", ex); } else { finalStatus = this.GetFinalStatusForHttpError(state); message = string.Format("while reading response: {0}", ex); } throw new StopRequestException(finalStatus, message, ex); } }
public static void DownloadAssetDatabase() { var sw = new Stopwatch(); sw.Start(); string json = new WebClient().DownloadString("https://raw.githubusercontent.com/headassbtw/LootSaber/master/AssetDatabase.json"); sw.Stop(); Plugin.Log.Info("Database downloaded in " + sw.ElapsedMilliseconds + "ms"); DownloadsDatabase items = JsonConvert.DeserializeObject <DownloadsDatabase>(json); FileManager.assetDB = items; }
/// <summary> /// Starts the download if necessary. /// </summary> /// <remarks> /// This function starts a flow that /// does many things: /// 1) Checks to see if the APK version has been checked and the /// metadata database updated /// 2) If the APK version does not match, checks the new LVL status /// to see if a new download is required /// 3) If the APK version does match, then checks to see if the /// download(s) have been completed /// 4) If the downloads have been completed, returns /// <see cref="DownloadServiceRequirement.NoDownloadRequired"/> /// The idea is that this can be called during the startup of an /// application to quickly ascertain if the application needs to wait /// to hear about any updated APK expansion files. /// This does mean that the application MUST be run with a network /// connection for the first time, even if Market delivers all of the /// files. /// </remarks> /// <param name="context"> /// Your application Context. /// </param> /// <param name="pendingIntent"> /// A PendingIntent to start the Activity in your application that /// shows the download progress and which will also start the /// application when downloadcompletes. /// </param> /// <param name="serviceType"> /// The class of your <see cref="DownloaderService"/> implementation. /// </param> /// <returns> /// Whether the service was started and the reason for starting the /// service. /// Either <see cref="DownloadServiceRequirement.NoDownloadRequired"/>, /// <see cref="DownloadServiceRequirement.LvlCheckRequired"/>, or /// <see cref="DownloadServiceRequirement.DownloadRequired"/> /// </returns> public static DownloadServiceRequirement StartDownloadServiceIfRequired( Context context, PendingIntent pendingIntent, Type serviceType) { // first: do we need to do an LVL update? // we begin by getting our APK version from the package manager PackageInfo pi = context.PackageManager.GetPackageInfo(context.PackageName, 0); var status = DownloadServiceRequirement.NoDownloadRequired; // we need to update the LVL check and get a successful status to proceed if (IsLvlCheckRequired(pi)) { status = DownloadServiceRequirement.LvlCheckRequired; } // we don't have to update LVL. Do we still have a download to start? if (DownloadsDatabase.DownloadStatus == ExpansionDownloadStatus.None) { List <DownloadInfo> infos = DownloadsDatabase.GetDownloads(); IEnumerable <DownloadInfo> nonExisting = infos.Where(i => !Helpers.DoesFileExist(context, i.FileName, i.TotalBytes, true)); if (nonExisting.Any()) { status = DownloadServiceRequirement.DownloadRequired; DownloadsDatabase.DownloadStatus = ExpansionDownloadStatus.Unknown; } } else { status = DownloadServiceRequirement.DownloadRequired; } switch (status) { case DownloadServiceRequirement.DownloadRequired: case DownloadServiceRequirement.LvlCheckRequired: var fileIntent = new Intent(context.ApplicationContext, serviceType); fileIntent.PutExtra(DownloaderServiceExtras.PendingIntent, pendingIntent); context.StartService(fileIntent); break; } return(status); }
public static void SaveJson2(string path) { var bruh = new List <string> { "", "" }; var bruh2 = new Rarity(bruh, bruh, bruh, bruh); var bruh3 = new DownloadsDatabase(bruh2, bruh2, bruh2, bruh2, bruh2); using (StreamWriter w = new StreamWriter(path)) { JsonSerializer serializer = new JsonSerializer(); string contents = JsonConvert.SerializeObject(bruh3); var jtw = new JsonTextWriter(w); jtw.Formatting = Formatting.Indented; serializer.Serialize(jtw, bruh3); w.Close(); } }
/// <summary> /// The APK has been updated and a filename has been sent down from the /// Market call. If the file has the same name as the previous file, we do /// nothing as the file is guaranteed to be the same. If the file does not /// have the same name, we download it if it hasn't already been delivered by /// Market. /// </summary> /// <param name="filename"> /// the name of the new file /// </param> /// <param name="fileSize"> /// the size of the new file /// </param> /// <returns> /// The handle file updated. /// </returns> private bool HandleFileUpdated(string filename, long fileSize) { DownloadInfo di = DownloadsDatabase.GetDownloadInfo(filename); if (di != null && di.FileName != null) { if (filename == di.FileName) { return(false); } // remove partially downloaded file if it is there string deleteFile = Helpers.GenerateSaveFileName(this, di.FileName); if (File.Exists(deleteFile)) { File.Delete(deleteFile); } } return(!Helpers.DoesFileExist(this, filename, fileSize, true)); }
private void CheckDownloadedFile() { var downloads = DownloadsDatabase.GetDownloads().OrderByDescending(d => d.LastModified); if (downloads.Count() == 0) { return; } var down = downloads.First(); if (down.ExpansionFileType != LicenseVerificationLibrary.Policy.ApkExpansionPolicy.ExpansionFileType.MainFile) { return; } string fileName = down.FileName; //int versionCode = PackageManager.GetPackageInfo(this.PackageName, 0).VersionCode; //string fileName = Helpers.GetExpansionApkFileName(this, true, versionCode); string path = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Android/obb/" + this.PackageName + "/" + fileName; if (System.IO.File.Exists(path)) { if (fileName != DataManager.Get <IPreferencesManager>().Preferences.ApkDownloaded) { CopyDownloadedFile(path); //Toast.MakeText(this, "Copia", ToastLength.Long).Show(); } else { //Toast.MakeText(this, "C'è Già", ToastLength.Long).Show(); StartApp(); } } }
/// <summary> /// The update download database. /// </summary> /// <param name="status"> /// The status. /// </param> /// <param name="countRetry"> /// The count retry. /// </param> /// <param name="retryAfter"> /// The retry after. /// </param> /// <param name="redirectCount"> /// The redirect count. /// </param> /// <param name="gotData"> /// The got data. /// </param> private void UpdateDownloadDatabase( ExpansionDownloadStatus status, bool countRetry, int retryAfter, int redirectCount, bool gotData) { this.downloadInfo.Status = status; this.downloadInfo.RetryAfter = retryAfter; this.downloadInfo.RedirectCount = redirectCount; this.downloadInfo.LastModified = PolicyExtensions.GetCurrentMilliseconds(); if (!countRetry) { this.downloadInfo.FailedCount = 0; } else if (gotData) { this.downloadInfo.FailedCount = 1; } else { this.downloadInfo.FailedCount++; } DownloadsDatabase.UpdateDownload(this.downloadInfo); }
/// <summary> /// Go through each of the Expansion APK files defined in the project /// and determine if the files are present and match the required size. /// </summary> /// <remarks> /// Free applications should definitely consider doing this, as this /// allows the application to be launched for the first time without /// having a network connection present. /// Paid applications that use LVL should probably do at least one LVL /// check that requires the network to be present, so this is not as /// necessary. /// </remarks> /// <returns> /// True if they are present, otherwise False; /// </returns> private bool AreExpansionFilesDelivered() { var downloads = DownloadsDatabase.GetDownloads(); return(downloads.Any() && downloads.All(x => Helpers.DoesFileExist(this, x.FileName, x.TotalBytes, false))); }
internal static DownloadRequestResponse DownloadAsset(DownloadsDatabase db) { DownloadRequestResponse resp = new DownloadRequestResponse(); var rng = new Random(); Rarity rolledRarity = new Rarity(); List <String> rolledType = new List <string>(); int amountOfRolledType = 0; switch (Random.Range(0, 5)) { case 0: rolledRarity = db.Tier1; Plugin.Log.Info("Rolled Tier 1"); resp.tier = 1; break; case 1: rolledRarity = db.Tier2; Plugin.Log.Info("Rolled Tier 2"); resp.tier = 2; break; case 2: rolledRarity = db.Tier3; Plugin.Log.Info("Rolled Tier 3"); resp.tier = 3; break; case 3: rolledRarity = db.Tier4; Plugin.Log.Info("Rolled Tier 4"); resp.tier = 4; break; case 4: rolledRarity = db.Tier5; Plugin.Log.Info("Rolled Tier 5"); resp.tier = 5; break; } string folder = ""; int maxtype = 4; if (!AssetModDetection.MenuFonts) { maxtype = 3; } var a = Random.Range(0, maxtype); if (a.Equals(rollcat1)) { a = Random.Range(0, maxtype); } rollcat1 = a; switch (a) { case 0: rolledType = rolledRarity.Sabers; amountOfRolledType = rolledType.Count; folder = "UserData\\LootSaber\\Asset Cache\\CustomSabers"; Plugin.Log.Info("Rolled Saber"); resp.assetType = "Saber"; break; case 1: rolledType = rolledRarity.Notes; amountOfRolledType = rolledType.Count; folder = "UserData\\LootSaber\\Asset Cache\\CustomNotes"; Plugin.Log.Info("Rolled Note"); resp.assetType = "Note"; break; case 2: rolledType = rolledRarity.Platforms; amountOfRolledType = rolledType.Count; folder = "UserData\\LootSaber\\Asset Cache\\CustomPlatforms"; Plugin.Log.Info("Rolled Platform"); resp.assetType = "Platform"; break; case 3: rolledType = rolledRarity.MenuFonts; amountOfRolledType = rolledType.Count; folder = "UserData\\LootSaber\\Asset Cache\\UserData\\CustomMenuText\\Fonts"; Plugin.Log.Info("Rolled Menu Font"); resp.assetType = "Menu Text Font"; break; } var URL = rolledType.ElementAt(Random.Range(0, amountOfRolledType)); var client = new WebClient(); string _realname = URL.Substring(URL.LastIndexOf("/") + 1).Replace("%20", " "); if (_realname.Contains("?")) { _realname = _realname.Substring(0, _realname.IndexOf("?")); } string fileSavePath = UnityGame.InstallPath + "\\" + folder + "\\" + _realname; try { Plugin.Log.Notice("Downloading " + _realname + " From " + URL); client.DownloadFileAsync( new Uri(URL), fileSavePath ); resp.client = client; } catch (Exception) { //if the folder doesn't exist, create it and try again Directory.CreateDirectory(UnityGame.InstallPath + "\\" + folder); client.DownloadFileAsync( new Uri(URL), fileSavePath ); resp.client = client; } resp.filePath = fileSavePath; return(resp); }
//rolls a few dice to give you an asset internal static string DiceRoll(DownloadsDatabase db, Random rng) { Rarity rolledRarity = new Rarity(); List <String> rolledType = new List <string>(); int amountOfRolledType = 0; switch (Random.Range(0, 5)) { case 0: rolledRarity = db.Tier1; Plugin.Log.Info("Rolled Tier 1"); break; case 1: rolledRarity = db.Tier2; Plugin.Log.Info("Rolled Tier 2"); break; case 2: rolledRarity = db.Tier3; Plugin.Log.Info("Rolled Tier 3"); break; case 3: rolledRarity = db.Tier4; Plugin.Log.Info("Rolled Tier 4"); break; case 4: rolledRarity = db.Tier5; Plugin.Log.Info("Rolled Tier 5"); break; } var a = Random.Range(0, 4); if (a.Equals(rollcat1)) { a = Random.Range(0, 4); } rollcat1 = a; switch (a) { case 0: rolledType = rolledRarity.Sabers; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Saber"); break; case 1: rolledType = rolledRarity.Notes; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Note"); break; case 2: rolledType = rolledRarity.Platforms; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Platform"); break; case 3: rolledType = rolledRarity.MenuFonts; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Menu Font"); break; } return(rolledType.ElementAt(Random.Range(0, amountOfRolledType))); }
internal async void DownloadAsset(DownloadsDatabase db, Random rng, int slot) { Rarity rolledRarity = new Rarity(); List <String> rolledType = new List <string>(); int amountOfRolledType = 0; switch (rng.Next(0, 5)) { case 0: rolledRarity = db.Tier1; Plugin.Log.Info("Rolled Tier 1"); break; case 1: rolledRarity = db.Tier2; Plugin.Log.Info("Rolled Tier 2"); break; case 2: rolledRarity = db.Tier3; Plugin.Log.Info("Rolled Tier 3"); break; case 3: rolledRarity = db.Tier4; Plugin.Log.Info("Rolled Tier 4"); break; case 4: rolledRarity = db.Tier5; Plugin.Log.Info("Rolled Tier 5"); break; } var a = rng.Next(0, 4); if (a.Equals(rollcat1)) { rng = new Random(3294704); a = rng.Next(0, 4); } rollcat1 = a; switch (a) { case 0: rolledType = rolledRarity.Sabers; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Saber"); break; case 1: rolledType = rolledRarity.Notes; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Note"); break; case 2: rolledType = rolledRarity.Platforms; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Platform"); break; case 3: rolledType = rolledRarity.MenuFonts; amountOfRolledType = rolledType.Count; Plugin.Log.Info("Rolled Menu Font"); break; } var URL = rolledType.ElementAt(rng.Next(0, amountOfRolledType)); var client = new WebClient(); string _realname = URL.Substring(URL.LastIndexOf("/")).Replace("%20", " "); if (_realname.Contains("?")) { _realname = _realname.Substring(0, _realname.IndexOf("?")); } switch (slot) { case 1: client.DownloadProgressChanged += wc_progChange1; break; case 2: client.DownloadProgressChanged += wc_progChange2; break; case 3: client.DownloadProgressChanged += wc_progChange3; break; } string folder = ""; switch (a) { case 0: folder = "CustomSabers"; break; case 1: folder = "CustomNotes"; break; case 2: folder = "CustomPlatforms"; break; case 3: folder = "UserData\\CustomMenuText\\Fonts"; break; } client.DownloadFileAsync( new Uri(URL), UnityGame.InstallPath + "\\" + folder + "\\" + _realname ); }
/// <summary> /// The allow. /// </summary> /// <param name="reason"> /// The reason. /// </param> /// <exception cref="Java.Lang.RuntimeException"> /// Error with LVL checking and database integrity /// </exception> /// <exception cref="Java.Lang.RuntimeException"> /// Error with getting information from package name /// </exception> public void Allow(PolicyServerResponse reason) { try { int count = this.policy.GetExpansionFilesCount(); if (count == 0) { Debug.WriteLine("No expansion packs."); } ExpansionDownloadStatus status = 0; for (int index = 0; index < count; index++) { var type = (ApkExpansionPolicy.ExpansionFileType)index; ApkExpansionPolicy.ExpansionFile expansionFile = this.policy.GetExpansionFile(type); string currentFileName = expansionFile.FileName; if (currentFileName != null) { var di = new DownloadInfo { ExpansionFileType = type, FileName = currentFileName, }; if (this.Context.HandleFileUpdated(currentFileName, expansionFile.FileSize)) { status = ExpansionDownloadStatus.Unknown; di.ResetDownload(); di.Uri = expansionFile.Url; di.TotalBytes = expansionFile.FileSize; di.Status = status; DownloadsDatabase.UpdateDownload(di); } else { // we need to read the download information from the database DownloadInfo dbdi = DownloadsDatabase.GetDownloadInfo(di.FileName); if (dbdi == null) { // the file exists already and is the correct size // was delivered by Market or through another mechanism Debug.WriteLine(string.Format("file {0} found. Not downloading.", di.FileName)); di.Status = ExpansionDownloadStatus.Success; di.TotalBytes = expansionFile.FileSize; di.CurrentBytes = expansionFile.FileSize; di.Uri = expansionFile.Url; DownloadsDatabase.UpdateDownload(di); } else if (dbdi.Status != ExpansionDownloadStatus.Success) { // we just update the URL dbdi.Uri = expansionFile.Url; DownloadsDatabase.UpdateDownload(dbdi); status = ExpansionDownloadStatus.Unknown; } } } } // first: do we need to do an LVL update? // we begin by getting our APK version from the package manager try { PackageInfo pi = this.Context.PackageManager.GetPackageInfo(this.Context.PackageName, 0); DownloadsDatabase.UpdateMetadata(pi.VersionCode, status); DownloadServiceRequirement required = StartDownloadServiceIfRequired( this.Context, this.Context.pPendingIntent, this.Context.GetType()); switch (required) { case DownloadServiceRequirement.NoDownloadRequired: this.Context.downloadNotification.OnDownloadStateChanged(DownloaderState.Completed); break; case DownloadServiceRequirement.LvlCheckRequired: // DANGER WILL ROBINSON! Debug.WriteLine("In LVL checking loop!"); this.Context.downloadNotification.OnDownloadStateChanged( DownloaderState.FailedUnlicensed); throw new RuntimeException("Error with LVL checking and database integrity"); case DownloadServiceRequirement.DownloadRequired: // do nothing: the download will notify the application when things are done break; } } catch (PackageManager.NameNotFoundException e1) { e1.PrintStackTrace(); throw new RuntimeException("Error with getting information from package name"); } catch (Exception ex) { Debug.WriteLine("LVL Update Exception: " + ex.Message); throw; } } catch (Exception ex) { Debug.WriteLine("Allow Exception: " + ex.Message); throw; } finally { this.Context.IsServiceRunning = false; } }
/// <summary> /// Update necessary database fields based on values of HTTP response headers that have been read. /// </summary> /// <param name="innerState"> /// The inner State. /// </param> private void UpdateDatabaseFromHeaders(InnerState innerState) { this.downloadInfo.ETag = innerState.HeaderETag; DownloadsDatabase.UpdateDownload(this.downloadInfo); }
/// <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; } }