Пример #1
0
    /// <summary>
    /// 应用版本比对,包内版本和包外记录的版本之间对比
    /// </summary>
    void AppVersionComparison()
    {
        bool   needCreateAppVersion = true;
        string appVersionPath       = FileSystem.persistentDataPath + "/lastclean_app_version.";

        try
        {
            if (FileSystem.IsFileExists(appVersionPath))
            {
                string exappVersion = LoadVersionXml(FileSystem.byte2string(FileSystem.ReadFile(appVersionPath)));
                if (exappVersion == Application.version)
                {
                    needCreateAppVersion = false;
                }
            }
        }
        catch (Exception) { }

        if (needCreateAppVersion)//首次更新或应用程序已升级
        {
            //删除所有外部包和外部版本信息
            {
                DirectoryInfo dirInfo = new DirectoryInfo(FileSystem.persistentDataPath + "/pack_res");
                if (dirInfo.Exists)
                {
                    FileInfo[] files = dirInfo.GetFiles();
                    foreach (FileInfo curr in files)
                    {
                        if (curr.Extension == "" || curr.Extension == ".manifest" || curr.Extension == ".xml")
                        {
                            curr.Delete();
                        }
                    }
                }
                else
                {
                    dirInfo.Create();
                }
            }

            {
                DirectoryInfo dirInfo = new DirectoryInfo(FileSystem.persistentDataPath + "/pack_script");
                if (dirInfo.Exists)
                {
                    FileInfo[] files = dirInfo.GetFiles();
                    foreach (FileInfo curr in files)
                    {
                        if (curr.Extension == "" || curr.Extension == ".manifest" || curr.Extension == ".xml")
                        {
                            curr.Delete();
                        }
                    }
                }
                else
                {
                    dirInfo.Create();
                }
            }

            //删除主资源版本文件
            {
                string   mainVersionPath = FileSystem.persistentDataPath + "/pack_main_version.xml";
                FileInfo mainVersionInfo = new FileInfo(mainVersionPath);
                if (mainVersionInfo.Exists)
                {
                    mainVersionInfo.Delete();
                }
            }


            //创建版本文件
            VersionContent version = new VersionContent(Application.version);
            version.OutFile(appVersionPath);
        }


        {
            {
                DirectoryInfo dirInfo = new DirectoryInfo(FileSystem.persistentDataPath + "/pack_res");
                if (!dirInfo.Exists)
                {
                    dirInfo.Create();
                }
            }

            {
                DirectoryInfo dirInfo = new DirectoryInfo(FileSystem.persistentDataPath + "/pack_script");
                if (!dirInfo.Exists)
                {
                    dirInfo.Create();
                }
            }
        }
    }
Пример #2
0
    /// <summary>
    /// 热更协程
    /// </summary>
    IEnumerator coGo(context currContext)
    {
        using (
            SafeRecall_0 safeRecall = new SafeRecall_0(() => m_CurrContext = null)
            )
        {
            //装载内部版本文件包
            {
                List <string> packs = new List <string>();
                packs.Add("rom_version");

                PacketLoader loader = new PacketLoader();
                loader.Start(PackType.Res, packs, null);

                //等待资源装载完成
                while (loader.Result == PacketLoader.ResultEnum.Loading)
                {
                    yield return(null);
                }
            }



            //比对包外应用版本号
            {
                AppVersionComparison();
                NotifyProgress(currContext, 0.01f);
                yield return(null);
            }


            //获取远程资源包主版本
            MainVersionContent remote_main_pack_version = null;
            {
                IEnumerator coit = coPackMainVersionComparison(
                    currContext,
                    (vf) => remote_main_pack_version = vf
                    );
                while (coit.MoveNext())
                {
                    yield return(null);
                }
            }
            if (currContext.m_State == STATE.stopd)
            {
                yield break;                                    //已经终止
            }
            NotifyProgress(currContext, 0.02f);
            yield return(null);


            string runtimePlatform = RuntimePlatformStr();

            //主资源版本信息
            string exmain_pack_path = FileSystem.persistentDataPath + "/pack_main_version.xml";
            {
                MainVersionContent local_main_pack_version = MainVersionContent.FromFile(exmain_pack_path); //从外部文件夹获取资源主版本
                if (local_main_pack_version == null)                                                        //从外部文件读取失败,则从资源包读取
                {
                    //string path = string.Format("{0}/pack_main_version", runtimePlatform);
                    //TextAsset versionAsset = Resources.Load(path) as TextAsset;
                    //string xmlstr = FileSystem.byte2string(versionAsset.bytes);

                    string xmlstr = PacketManage.Single.GetPacket("rom_version").LoadString("pack_main_version");

                    local_main_pack_version = MainVersionContent.FromXmlDocument(xmlstr);

                    //将版本信息写入外部文件夹
                    local_main_pack_version.OutFile(exmain_pack_path);
                }


                //检查应用标识和平台标识是否一致
                bool IdentifierError;
                do
                {
                    IdentifierError = false;
                    if (
                        local_main_pack_version.Identifier != remote_main_pack_version.Identifier ||
                        local_main_pack_version.Platform != remote_main_pack_version.Platform
                        )
                    {
                        IdentifierError     = true;
                        currContext.m_State = STATE.netError;
                        if (currContext.m_OnNetError != null)
                        {
                            currContext.m_OnNetError(ErrorNo.RemoteMainVersionFmtError, "远程版本文件标识符错误");
                        }
                        while (true)
                        {
                            if (currContext.m_State == STATE.stopd)//用户选择停止工作
                            {
                                yield break;
                            }
                            else if (currContext.m_State == STATE.doing)//用户选择重试
                            {
                                break;
                            }
                            else
                            {
                                yield return(null);

                                if (currContext.m_State == STATE.stopd)
                                {
                                    yield break;
                                }
                            }
                        }
                    }
                } while (IdentifierError);

                //检查大版本更新
                if (local_main_pack_version.AppVersion != remote_main_pack_version.AppVersion)
                {
                    //应用软件升级
                    if (currContext.m_OnUpgradeApp != null)
                    {
                        currContext.m_OnUpgradeApp();
                    }

                    yield break;
                }

                //比对主版本号
                if (int.Parse(local_main_pack_version.PackVersion) >= int.Parse(remote_main_pack_version.PackVersion))
                {
                    NotifyProgress(currContext, 1f);
                    if (currContext.m_OnComplate != null)
                    {
                        currContext.m_OnComplate();
                    }

                    yield break; //本地资源主版本号>=远程资源主版本号 表示无需更新资源
                }
            }
            NotifyProgress(currContext, 0.03f);
            yield return(null);

            Dictionary <string, int> remote_res_version    = new Dictionary <string, int>(); //远程资源版本信息
            Dictionary <string, int> remote_script_version = new Dictionary <string, int>(); //远程脚本版本信息
            Dictionary <string, int> local_res_version     = new Dictionary <string, int>(); //本地资源版本信息
            Dictionary <string, int> local_script_version  = new Dictionary <string, int>(); //本地远程脚本版本信息

            //获取远程版本比对信息
            string remote_Identifier = "";
            string remote_Platform   = "";
            {
                XmlDocument remote_version_doc = null;
                do
                {
                    string version_url = url + "/pack_version.zip";//版本文件url

                    WWW www = new WWW(version_url);
                    yield return(www);

                    if (www.error == null)
                    {
                        //解压缩版本比对文件
                        byte[] xmlbytes = MonoEX.LZMA.Decompress(www.bytes, 0);
                        string xmlstr   = FileSystem.byte2string(xmlbytes);
                        try
                        {
                            remote_version_doc = new XmlDocument();
                            remote_version_doc.LoadXml(xmlstr);
                            XmlElement xmlNode = remote_version_doc.SelectSingleNode("xml") as XmlElement;
                            remote_Identifier = xmlNode.GetAttribute("Identifier");
                            remote_Platform   = xmlNode.GetAttribute("Platform");
                            {
                                XmlElement resNode = remote_version_doc.SelectSingleNode("xml/pack_res") as XmlElement;
                                foreach (XmlNode aNode in resNode.SelectNodes("a"))
                                {
                                    XmlElement aElement = aNode as XmlElement;
                                    string     n        = aElement.GetAttribute("n");
                                    int        v        = int.Parse(aElement.GetAttribute("v"));
                                    remote_res_version.Add(n, v);
                                }
                            }

                            {
                                XmlElement resNode = remote_version_doc.SelectSingleNode("xml/pack_script") as XmlElement;
                                foreach (XmlNode aNode in resNode.SelectNodes("a"))
                                {
                                    XmlElement aElement = aNode as XmlElement;
                                    string     n        = aElement.GetAttribute("n");
                                    int        v        = int.Parse(aElement.GetAttribute("v"));
                                    remote_script_version.Add(n, v);
                                }
                            }
                        }
                        catch (Exception)
                        {
                            remote_version_doc = null;
                        }

                        if (remote_version_doc == null)
                        {
                            currContext.m_State = STATE.netError;
                            if (currContext.m_OnNetError != null)
                            {
                                currContext.m_OnNetError(ErrorNo.RemoteVersionFmtError, "远程版本信息文件格式有误");
                            }
                            while (true)
                            {
                                if (currContext.m_State == STATE.stopd)//用户选择停止工作
                                {
                                    yield break;
                                }
                                else if (currContext.m_State == STATE.doing)//用户选择重试
                                {
                                    break;
                                }
                                else
                                {
                                    yield return(null);

                                    if (currContext.m_State == STATE.stopd)
                                    {
                                        yield break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        currContext.m_State = STATE.netError;
                        if (currContext.m_OnNetError != null)
                        {
                            currContext.m_OnNetError(ErrorNo.GetRemoteVersionFailed, "获取" + version_url + "失败");
                        }
                        while (true)
                        {
                            if (currContext.m_State == STATE.stopd)//用户选择停止工作
                            {
                                yield break;
                            }
                            else if (currContext.m_State == STATE.doing)//用户选择重试
                            {
                                break;
                            }
                            else
                            {
                                yield return(null);

                                if (currContext.m_State == STATE.stopd)
                                {
                                    yield break;
                                }
                            }
                        }
                    }
                } while (remote_version_doc == null);
            }

            NotifyProgress(currContext, 0.04f);
            yield return(null);

            //获取本地包内版本信息文件
            {
                //string path = string.Format("{0}/pack_version", runtimePlatform);
                //TextAsset versionAsset = Resources.Load(path) as TextAsset;
                //string xmlstr = FileSystem.byte2string(versionAsset.bytes);

                var xmlstr = PacketManage.Single.GetPacket("rom_version").LoadString("pack_version");

                XmlDocument local_version_doc = new XmlDocument();
                local_version_doc.LoadXml(xmlstr);

                //检查应用标识和平台标识是否一致
                bool IdentifierError;
                do
                {
                    IdentifierError = false;
                    XmlElement xmlNode = local_version_doc.SelectSingleNode("xml") as XmlElement;
                    if (
                        remote_Identifier != xmlNode.GetAttribute("Identifier") ||
                        remote_Platform != xmlNode.GetAttribute("Platform")
                        )
                    {
                        IdentifierError     = true;
                        currContext.m_State = STATE.netError;
                        if (currContext.m_OnNetError != null)
                        {
                            currContext.m_OnNetError(ErrorNo.RemoteVersionFmtError, "远程版本文件标识符错误");
                        }
                        while (true)
                        {
                            if (currContext.m_State == STATE.stopd)//用户选择停止工作
                            {
                                yield break;
                            }
                            else if (currContext.m_State == STATE.doing)//用户选择重试
                            {
                                break;
                            }
                            else
                            {
                                yield return(null);

                                if (currContext.m_State == STATE.stopd)
                                {
                                    yield break;
                                }
                            }
                        }
                    }
                } while (IdentifierError);

                {
                    XmlElement resNode = local_version_doc.SelectSingleNode("xml/pack_res") as XmlElement;
                    foreach (XmlNode aNode in resNode.SelectNodes("a"))
                    {
                        XmlElement aElement = aNode as XmlElement;
                        string     n        = aElement.GetAttribute("n");
                        int        v        = int.Parse(aElement.GetAttribute("v"));
                        local_res_version.Add(n, v);
                    }
                }

                {
                    XmlElement resNode = local_version_doc.SelectSingleNode("xml/pack_script") as XmlElement;
                    foreach (XmlNode aNode in resNode.SelectNodes("a"))
                    {
                        XmlElement aElement = aNode as XmlElement;
                        string     n        = aElement.GetAttribute("n");
                        int        v        = int.Parse(aElement.GetAttribute("v"));
                        local_script_version.Add(n, v);
                    }
                }
            }


            NotifyProgress(currContext, 0.05f);
            yield return(null);

            List <string> NeedDownloadRes    = BuildNeedDownload(remote_res_version, local_res_version, "pack_res");
            List <string> NeedDownloadScript = BuildNeedDownload(remote_script_version, local_script_version, "pack_script");


            NotifyProgress(currContext, 0.06f);
            yield return(null);

            float start_p    = 0.06f;
            int   pack_count = NeedDownloadRes.Count + NeedDownloadScript.Count;
            int   currindex  = 0;

            //更新资源
            foreach (string name in NeedDownloadRes)
            {
                bool isok     = false;
                int  reUpdate = 0;
                do
                {
                    string pack_url = string.Format("{0}/pack_res/{1}.zip", url, name);
                    //UnityEngine.Debug.Log("热更资源" + pack_url + "路径" + name);
                    WWW www = new WWW(pack_url);
                    yield return(www);

                    if (www.error == null)
                    {
                        //byte[] filebytes = MonoEX.LZMA.Decompress(www.bytes, 0);
                        byte[] filebytes = www.bytes;

                        string pack_file         = FileSystem.MakeExternalPackPath("pack_res", name);
                        string pack_file_version = FileSystem.MakeExternalPackPath("pack_res", name + ".xml");

                        //判定是否可以读取信息 读取信息失败则重新下载一次
                        if (reUpdate <= 1)
                        {
                            int    fileleng = filebytes.Length - 20;
                            byte[] tail     = new byte[20];
                            Buffer.BlockCopy(filebytes, fileleng, tail, 0, 20);

                            string   tailstr  = Encoding.Default.GetString(tail);
                            string[] tailInfo = tailstr.Split('#');

                            //判断文件完整性
                            int    filel      = Int32.Parse(tailInfo[2]);
                            string farversion = remote_res_version[name].ToString();
                            //判断当前版本信息与自身携带的信息
                            if (tailInfo.Length != 3 || tailInfo[0] != farversion || fileleng < filel)
                            {
                                if (reUpdate < 1)
                                {
                                    //失败 重新下载一次
                                    reUpdate++;
                                    //UnityEngine.Debug.Log("失败一次 重新下载 版本号对比:" + tailInfo[0] + "-----" + farversion);
                                    continue;
                                }
                                else
                                {
                                    //失败过一次则直接解压
                                    //UnityEngine.Debug.Log("失败第二次 直接解压 文件长度对比:" + fileleng + "-----" + filel);
                                    FileStream fren = File.OpenWrite(pack_file);
                                    fren.Write(filebytes, 0, filebytes.Length);
                                    fren.Close();
                                }
                            }
                            else
                            {
                                using (FileStream fren = new FileStream(pack_file, FileMode.Create))
                                {
                                    fren.Write(filebytes, 0, fileleng);
                                    fren.Close();
                                }
                                //保存版本信息
                                //UnityEngine.Debug.Log("更新成功");
                                VersionContent version = new VersionContent(farversion);
                                version.OutFile(pack_file_version);
                            }
                        }
                        else
                        {
                            //UnityEngine.Debug.Log("更新成功 版本失败");
                            using (FileStream fren = File.OpenWrite(pack_file))
                            {
                                fren.Write(filebytes, 0, filebytes.Length);
                                fren.Close();
                            }
                        }

                        reUpdate = 0;

                        isok = true;
                        currindex++;
                        NotifyProgress(currContext, start_p + (1f - start_p) * ((float)currindex / (float)pack_count));
                    }
                    else
                    {
                        currContext.m_State = STATE.netError;
                        if (currContext.m_OnNetError != null)
                        {
                            currContext.m_OnNetError(ErrorNo.GetRemotePackFailed, "获取" + pack_url + "失败");
                        }
                        while (true)
                        {
                            if (currContext.m_State == STATE.stopd)//用户选择停止工作
                            {
                                yield break;
                            }
                            else if (currContext.m_State == STATE.doing)//用户选择重试
                            {
                                break;
                            }
                            else
                            {
                                yield return(null);

                                if (currContext.m_State == STATE.stopd)
                                {
                                    yield break;
                                }
                            }
                        }
                    }
                } while (!isok);
            }

            //更新脚本
            foreach (string name in NeedDownloadScript)
            {
                bool isok = false;
                do
                {
                    string pack_url = string.Format("{0}/pack_script/{1}.zip", url, name);
                    WWW    www      = new WWW(pack_url);
                    yield return(www);

                    if (www.error == null)
                    {
                        byte[] filebytes = MonoEX.LZMA.Decompress(www.bytes, 0);
                        string pack_file = FileSystem.MakeExternalPackPath("pack_script", name);
                        using (FileStream fs = File.OpenWrite(pack_file))
                        {
                            fs.Write(filebytes, 0, filebytes.Length);
                            fs.Close();
                        }

                        //保存版本信息
                        string         pack_file_version = FileSystem.MakeExternalPackPath("pack_script", name + ".xml");
                        VersionContent version           = new VersionContent(remote_script_version[name].ToString());
                        version.OutFile(pack_file_version);

                        isok = true;
                        currindex++;
                        NotifyProgress(currContext, start_p + (1f - start_p) * ((float)currindex / (float)pack_count));
                    }
                    else
                    {
                        currContext.m_State = STATE.netError;
                        if (currContext.m_OnNetError != null)
                        {
                            currContext.m_OnNetError(ErrorNo.GetRemotePackFailed, "获取" + pack_url + "失败");
                        }
                        while (true)
                        {
                            if (currContext.m_State == STATE.stopd)//用户选择停止工作
                            {
                                yield break;
                            }
                            else if (currContext.m_State == STATE.doing)//用户选择重试
                            {
                                break;
                            }
                            else
                            {
                                yield return(null);

                                if (currContext.m_State == STATE.stopd)
                                {
                                    yield break;
                                }
                            }
                        }
                    }
                } while (!isok);
            }

            remote_main_pack_version.OutFile(exmain_pack_path);//更新完成后改写主资源版本信息

            DoComplate(currContext);
        }
    }