记一次最新的c#ill2cpp热更方案

Posted avi9111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次最新的c#ill2cpp热更方案相关的知识,希望对你有一定的参考价值。

热更的Demo项目(非源hook dll热更项目)

https://github.com/noodle1983/UnityAndroidIl2cppPatchDemo/

其他的热更方法,如TOLUA,xLua的热更就不多说了

XLua最近开源了(可能也开源很久了,一直没留意),可以很值得看看

虽然,LUA和C#是风马牛不相近的东西(其实是相近的,说这话的人基本不懂Lua),两者的热更流程可以互相借鉴,

但我们今天也不是说热更流程的,而是更直接的想说说热更原理,以及如何完全实现。。。。

这里,基于某大神的方案,的一个Demo案例展开说说

热更Demo

 Demo界面如上,我们先从这两个按钮做突破,层层深入以至于完全了解最根本的热更(替代)原理

    public void OnClickSetVersion()
    {
        if (messageBox.gameObject.activeInHierarchy) { return; }

        if (updateVersion <= 0)
        {
            string error = Bootstrap.use_data_dir("", "");
            if (!string.IsNullOrEmpty(error))
            {
                messageBox.Show("use failed. empty path error:" + error, "ok", ()=> { messageBox.Close(); });
            }
            else
            {
                StartCoroutine(Restart());
            }
            return;
        }
        StartCoroutine(PreparePatchAndRestart());
    }

从代码可以看出,点击更新version按钮后的流程

(暂时无需网络下载更新包)

 所以我们要做的是,先打包母包,然后打包增量升级包,最后还必须往SteamingAssets目录放

重启的源码

    public static void reboot_app()
    {
        using (androidJavaClass unity_player = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            AndroidJavaObject current_activity = unity_player.GetStatic<AndroidJavaObject>("currentActivity");

            AndroidJavaObject pm = current_activity.Call<AndroidJavaObject>("getPackageManager");
            AndroidJavaObject intent = pm.Call<AndroidJavaObject>("getLaunchIntentForPackage", Application.identifier);
            //intent.Call<AndroidJavaObject>("setFlags", 0x20000000);//Intent.FLAG_ACTIVITY_SINGLE_TOP
            intent.Call<AndroidJavaObject>("setFlags", 0x04000000 | 0x00008000 | 0x10000000);//Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK

            AndroidJavaClass pending_intent = new AndroidJavaClass("android.app.PendingIntent");
            AndroidJavaObject content_intent = pending_intent.CallStatic<AndroidJavaObject>("getActivity", current_activity, 0, intent, 0x8000000); //PendingIntent.FLAG_UPDATE_CURRENT = 134217728 [0x8000000]
            AndroidJavaObject alarm_manager = current_activity.Call<AndroidJavaObject>("getSystemService", "alarm");
            AndroidJavaClass system = new AndroidJavaClass("java.lang.System");
            long current_time = system.CallStatic<long>("currentTimeMillis");
            alarm_manager.Call("set", 1, current_time + 1000, content_intent); // android.app.AlarmManager.RTC = 1 [0x1]

            Debug.LogError("alarm_manager set time " + current_time + 1000);
            current_activity.Call("finish");

            AndroidJavaClass process = new AndroidJavaClass("android.os.Process");
            int pid = process.CallStatic<int>("myPid");
            process.CallStatic("killProcess", pid);
        }
    }

重启逻辑写的有点复杂,博主知识有限,没看出来想干啥。。。。。

虽然是很硬核的 Android ,杀进程

但这里线索又断了,只能重新看  AndroidBuilder 这个类,是如何打更新包的?

 直接看代码有些懵,所以作弊了一下,偷看了大神怎么说的

  • 具体的做法是,libboostrap.so的dlopen,判断/data/目录下是否有热更后的libil2cpp.so文件,如果有则优先读取热更后的libil2cpp.so,没有则读取apk中的libil2cpp.so

从上点击更新version按钮后的流程,知道点击后,必须通过重启,再执行一遍libboostrap.so,才可实现热更(替换),所以必须要重启;执行Libboostrap.so的方法是优先从local的/data/目录找,没有则次选从.apk内的目录读取。

但切记,不要相信权威,我们需要的其实是 AllAndroidPatchFiles_ 这个文件

不要相信权威

最终,对于初级使用者的我们,就不需要了解Libboostrap.so

只需要知道2个包,母包+热更包

而“大神”说的,data目录下,其实又双叒是 persistent 目录

    public static string RUNTIME_PATCH_PATH_FORMAT { get { return Application.persistentDataPath + "/Version_{0}"; } }

方法二:更新version1 to English

解压

重启

确认.apk已经热更

方法一:验证是否优先取安卓手机本地 /app/目录

无热更包

有热更包

最后完善

到这里,热更基础完成了,一些功能如打包脚本,这个Demo项目就很好用了,留了不少尾巴

1.可能会补充http断线重连实现

2.搭建测试服务器(或CDN的搭建吧)

3.还有就是实现自己的热更流程

4.如何只打包脚本

5.极限优化-最小包

6.下载文件前检查存储空间是否足够

7.下载后检查md5是否匹配,不匹配重装

以上是关于记一次最新的c#ill2cpp热更方案的主要内容,如果未能解决你的问题,请参考以下文章

unity 代码热更+资源管理框架总结

xLua热更方案

记一次Unity最新多人联网同步框架Mirror

记一次抽象类中定义的静态变量,多个子类继承后,在方法中被重写引起的问题

记一次安装mysqlclient采坑:安装2.0.2最新版出错

记一次 C# 代码审查