示例#1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadThread"/> class.
 /// </summary>
 /// <param name="info">
 /// The info.
 /// </param>
 /// <param name="service">
 /// The service.
 /// </param>
 /// <param name="notification">
 /// The notification.
 /// </param>
 internal DownloadThread(DownloadInfo info, DownloaderService service, DownloadNotification notification)
 {
     this.context              = service;
     this.downloadInfo         = info;
     this.downloaderService    = service;
     this.downloadNotification = notification;
     this.UserAgent            = string.Format("APKXDL (Linux; U; Android {0};{1}; {2}/{3}){4}",
                                               Build.VERSION.Release,
                                               System.Threading.Thread.CurrentThread.CurrentCulture.Name,
                                               Build.Device,
                                               Build.Id,
                                               this.downloaderService.PackageName);
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="DownloadThread"/> class.
 /// </summary>
 /// <param name="info">
 /// The info.
 /// </param>
 /// <param name="service">
 /// The service.
 /// </param>
 /// <param name="notification">
 /// The notification.
 /// </param>
 internal DownloadThread(DownloadInfo info, DownloaderService service, DownloadNotification notification)
 {
     this.context = service;
     this.downloadInfo = info;
     this.downloaderService = service;
     this.downloadNotification = notification;
     this.UserAgent = string.Format("APKXDL (Linux; U; Android {0};{1}; {2}/{3}){4}",
                                    Build.VERSION.Release,
                                    System.Threading.Thread.CurrentThread.CurrentCulture.Name,
                                    Build.Device,
                                    Build.Id,
                                    this.downloaderService.PackageName);
 }
        /// <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));
        }
                /// <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.");
                        }

                        DownloadStatus 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 = DownloadStatus.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("file {0} found. Not downloading.", di.FileName);
                                        di.Status = DownloadStatus.Success;
                                        di.TotalBytes = expansionFile.FileSize;
                                        di.CurrentBytes = expansionFile.FileSize;
                                        di.Uri = expansionFile.Url;
                                        DownloadsDatabase.UpdateDownload(di);
                                    }
                                    else if (dbdi.Status != DownloadStatus.Success)
                                    {
                                        // we just update the URL
                                        dbdi.Uri = expansionFile.Url;
                                        DownloadsDatabase.UpdateDownload(dbdi);
                                        status = DownloadStatus.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>
                /// 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;
                    }
                }
示例#6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="State"/> class.
 /// </summary>
 /// <param name="info">
 /// The info.
 /// </param>
 /// <param name="service">
 /// The service.
 /// </param>
 public State(DownloadInfo info, DownloaderService service)
 {
     this.RedirectCount = info.RedirectCount;
     this.RequestUri    = info.Uri;
     this.Filename      = service.GenerateTempSaveFileName(info.FileName);
 }
        /// <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;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="State"/> class.
 /// </summary>
 /// <param name="info">
 /// The info.
 /// </param>
 /// <param name="service">
 /// The service.
 /// </param>
 public State(DownloadInfo info, DownloaderService service)
 {
     this.RedirectCount = info.RedirectCount;
     this.RequestUri = info.Uri;
     this.Filename = service.GenerateTempSaveFileName(info.FileName);
 }