代码改变世界

智能手机程序在线更新

2007-08-28 10:22  老羽  阅读(662)  评论(1编辑  收藏  举报
      最近刚完成一个在线更新的东西。因为智能手机应用没有Clickonce之类的更新程序,所以自己动手写一个。(其实clickonce也并不好用,自己动手写一个更方便).更新程序后台用webservicehttphandler都行,这里不多讲,主要讲讲前台设计。

更新程序分为4个步骤:

1.下载服务器版本及更新列表,对比本地的版本,是否需要更新;

2.下载服务器的更新版本;

3.覆盖本地版本;

4.重新启动主应用程序; 

如果用传统的设计,4个步骤很简单,定义一个枚举分别对应每个步骤;

/// <summary>

    /// 系统自动升级步骤

    /// </summary>

    public enum AutoUpdateStep

    {

        /// <summary>

        /// 正在获取服务器版本

        /// </summary>

        SeeingServerEdition = 1,

        /// <summary>

        /// 正在下载服务器端文件

        /// </summary>

        DownLoadingServerFiles = 2,

        /// <summary>

        /// 服务器文件保存完毕

        /// </summary>

        ServerFilesDownloaded = 3,

        /// <summary>

        /// 更新完毕

        /// </summary>

        Finished = 4,

        /// <summary>

        /// 未知状态

        /// </summary>

        Unknow = 0

}

然后if…else…判断步骤,执行相应的步骤。但是这样如果想在中间插入一个步骤,都会很麻烦。考虑过后,如果引入命令模式,则很方便的实现各个步骤。

定义各个步骤的基类:

public abstract class UpdateCommand

    {

        protected Context _context;

 

        public UpdateCommand(Context context)

        {

            this._context = context;

        }

 

        #region abstract Method

        public abstract void Execute();

        #endregion

}

 

获取服务端版本及更新列表:

public class GetServerVersionCommand : UpdateCommand

    {

        public GetServerVersionCommand(Context context)

            : base(context)

        {

 

        }

 

        public override void Execute()

        {

             //实现略……

        }

}

 

 


下载服务端新版本:

public class DownloadDataCommand : UpdateCommand

    {

        public DownloadDataCommand(Context context)

            : base(context)

        {

 

        }

 

        public override void Execute()

        {

            //实现略……

        }

}

其它2个步骤,更新本地版本,完成更新重启主程序类似,SaveDownloadDataCommandFinishDownloadCommand

Context 是用来和主界面交互的中间层,有点中介者的味道,主要定义了一系列事件,用于实现和主界面的交互。这样可以实现主界面与各个命令的解藕。

public sealed class SmartUpdateManager 

    {

        #region Properties

        private List<UpdateCommand> Commands = null;

        private int Index = 0;

 

        private Context _context = null;

        public Context UpdateContext

        {

            get

            {

                if (this._context == null)

                {

                    _context = new Context();

                }

                return this._context;

            }

        }

 

        #endregion

 

        public SmartUpdateManager()

        {

            InitHandleUpdate();

        }

 

        private void InitHandleUpdate()

        {

            Commands = new List<UpdateCommand>();

            GetServerVersionCommand cmd1 = new GetServerVersionCommand(UpdateContext);

            DownloadDataCommand cmd2 = new DownloadDataCommand(UpdateContext);

            SaveDownloadDataCommand cmd3 = new SaveDownloadDataCommand(UpdateContext);

            FinishDownloadCommand cmd4 = new FinishDownloadCommand(UpdateContext);

 

            Commands.Add(cmd1);

            Commands.Add(cmd2);

            Commands.Add(cmd3);

            Commands.Add(cmd4);

        }

 

        #region Public Method

        public void Execute()

        {

              InnerHandExecute();

        }

 

        private void InnerHandExecute()

        {

            try

            {

                 if (this.Index < this.Commands.Count)

                {

                    this.Commands[this.Index].Execute();

                    this.Index++;

                }

            }

            catch (Exception)

            {

            }

        }

        #endregion

 

}

客户界面调用,很方便,主界面订阅SmartUpdateManagerContext的事件用于更新进度条,提示信息等交互信息。

private SmartUpdateManager manager = null;

private void InitUpdateManager()

        {

            manager = new SmartUpdateManager();

            manager.UpdateContext.ApplicationExit += new ApplicationExitHandler(manager_onApplicationExit);

            manager.UpdateContext.EnabledChanged += new EnabledChangedHandler(manager_onEnabledChanged);

            manager.UpdateContext.ProcessBarValueChanged += new ProgressarValueChangedHandler(manager_onProcessBarValueChanged);

            manager.UpdateContext.PromptMsgChanged += new PromptMsgChangedHandler(manager_onPromptMsgChanged);

            manager.UpdateContext.TextChanged += new TextChangedHandler(manager_onTextChanged);

            manager.UpdateContext.VisiableChanged += new VisiableChangedHandler(manager_onVisiableChanged);

            manager.UpdateContext.WorkingTipMessageChanged += new WorkingTipMessageChangedHandler(manager_onWorkingTipMessageChanged);

            manager.UpdateContext.CancelEnableChanged += new CancelEnableChangedHandler(manager_onCancelEnabled);

           

        }

 

void btnNext_Click(object sender, EventArgs e)

        {

            try

            {

                this.psbDownload.Value = 0;

                this.btnNext.Enabled = false;

                this.manager.Execute();

                //Application.DoEvents();

            }

            catch (Exception)

            {

                //………           

}

        }

 

    这样的设计很容易实现向导,实际上我实现的就是向导式的更新。一步一步提示用户。如果想在中间增加一个环节,比如增加一个欢迎环节,一个校对文件的环节。那么我们只需要更改SmartUpdateManager中的代码。我们新增2WelComeCommand, ValidateCommand.

private void InitHandleUpdate()

        {

            Commands = new List<UpdateCommand>();

            //_context = new Context();

 

            GetServerVersionCommand cmd1 = new GetServerVersionCommand(UpdateContext);

            DownloadDataCommand cmd2 = new DownloadDataCommand(UpdateContext);

            SaveDownloadDataCommand cmd3 = new SaveDownloadDataCommand(UpdateContext);

            FinishDownloadCommand cmd4 = new FinishDownloadCommand(UpdateContext);

 

            //注意这是新增的环节,欢迎环节。

            WelComeCommand cmdNew1 = new WelComeCommand(UpdateContext);

            //插入另一个新环节,校对下载的文件。。。。

            ValidateCommand cmdNew2 = new ValidateCommand(UpdateContext);

 

            Commands.Add(cmdNew1);  //插到第一个环节;

            Commands.Add(cmd1);

            Commands.Add(cmd2);

            Commands.Add(cmdNew2);  //插入另一个环节,校对文件环节。

            Commands.Add(cmd3);

            Commands.Add(cmd4);

        }
这样的需求变更,客户端的调用不需要任何改动。