作为一个游戏开发者, 更新这个技能是必不可少的! 更新分为游戏内的更新, 也就是所谓的资源热更包括 AssetBundle 更新和代码更新, 代码其实也是所谓的二进制文件, 在安卓上和普通资源文件毫无差异, 然而在 iOS 上差别大来个去了, 由于苹果爸爸所谓出于安全性的考虑, 不支持 JIT, 我们也很无奈啊! 如今能绕过去的, 只能靠解释器去执行这部分被视为另类的代码文件了, 能解决的也就是今天各种版本的 Lua 和 ILRuntime 了! 好了, 夜已深, 废话不多说了, 开始今天正题!!!
1, 如何通过 Unity 进行应用内更新?
应用内的更新也就所谓的资源热更了, 从 CDN 上直接下载就完事了, 下载的方式有很多, WWW,webRequest,HttpWebRequest 等, 最不推荐的就是 WWW, 原因一: www.bytes 这家伙很占内存, 句柄有限, 在 iOS 上文件过多, 开的 WWW 超过句柄限制会有意想不到的惊喜 (Bug),Unity 官方已逐渐适应 WebRequest 取而代之了, 推荐使用 HttpWebRequest, 支持断点续传, 很是方便!
2, 何时进行大版本更新, 该如何更新呢?
这个大版本更新要看如何设计了, 我们游戏是采用高中低三位来决定该更新哪些东西, 例如: 当前版本号 1.0.1, 下次客户端提高版本号到 1.0.2 或者 1.1.0 都是资源更新, 如果大版本好改为 2.x.x 则进行大版本更新, 如何更新呢? 两种方法, 一通过 "market://details?id=com.xxx.xxx" 标记使用 Android 代码打开应用市场内的应用, 那么有经验同学就看到了问题, 如果我装的不是本应用商店的应用呢, 那不就凉了!!! 是的, 装的不是手机应用商店的肯定凉不了啊, 我们还有方法二呢, 前往你下载的对应版本的 cdn 上直接下载就可以了啊! 至于怎么下载请转到 1.
3, 下载完了, 我该怎么安装呢?
不要着急, 安装及其的简单, Android 原生提供了很好 API, 如果你的 Android OS 低于 7.0 那么只需要这几行代码就 OK 了!
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- File apkFile = new File(apkFullPath);
- Uri uri = null; uri = Uri.fromFile(apkFile);
- intent.setDataAndType(uri, "application/vnd.android.package-archive");
- MainActivity.instance.startActivity(intent);
为什么我强调了下是 7.0 的呢, 因为 Android 7.0 行为变更了所以这么写会报错的, 尝试传递 file://URI 可能会触发 FileUriExposedException. 不要慌, 那么如何解决呢? 我们首先需要在 AndroidManifest 里添加 provider 标签, 通过这个标签将 apk 所在路径的 share 出去, 这样本次就能访问该路径下的 apk 了, 那么这个错误也就引刃而解了! 如何使用这个 provider 呢, 别着急, 手把手教你如何使用 provider.
第一步: 先在 AndroidManfiest.xml 添加 provider 标签, 位置在 application 内即可!
- <provider
- Android:name="android.support.v4.content.FileProvider"
- Android:authorities="com.wuzhang.testandroid.fileProvider"
- Android:grantUriPermissions="true"
- Android:exported="false">
- <meta-data
- Android:name="android.support.FILE_PROVIDER_PATHS"
- Android:resource="@xml/provider_paths" />
- </provider>
别忘记还要加个安装的权限: <uses-permission Android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
第二步: 指定共享目录, 在 res 下创建 / xml/provider_paths.xml, 路径见下图
provider_paths.xml 文件
- <?xml version="1.0" encoding="utf-8"?>
- <paths>
- <external-path
- name="publicDir" path=""/>
- </paths>
解释下, 此处 name="publicDir" 无实际意义, 就是一个解释而已, path=""; 表示的是这个目录是当前根目录下的不再添加子目录等价于 Unity 中的 Application.persistentDataPath 也就是安卓设备上的 storage/0/Android/data/com.wuzhang.testandroid/files/
第三步: 再次调用 apk 安装代码
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- File apkFile = new File(apkFullPath);
- Uri uri = null;
- String path = MainActivity.instance.getApplicationContext().getPackageName() + ".fileProvider";
- uri = FileProvider.getUriForFile(MainActivity.instance, path,apkFile);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setDataAndType(uri, "application/vnd.android.package-archive");
- MainActivity.instance.startActivity(intent);
PS: 这里有个地方需要注意, 为何非要是这个顺序???
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- ...
- ...
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
为什么 setFlag 放到上面就可以, addFlag 放上面就不行呢??? 原因很简单, 当 setFlag 时会先清空 intent 下之前所有的 flag, 所以 addFlag 的 FLAG_GRANT_READ_URI_PERMISSION 就无效了, 本人亲自踩的坑, 多么痛的礼物!
这一切到搞定了, 打包真机测试, Android 7.0 的果然好了, 年轻人, 别高兴的太早, 说完又遇到一个坑, 8.0 以上的系统死活不会弹出安装界面, 一首凉凉送给自己,,, 但是马上就要看到胜利的曙光了, 一定要淡定, 车到山前必有路, 办法总比困难多!!!
最终安装代码, 完美兼容, Android 7.0,8.0
- public static void installApk(String apkFullPath)
- {
- try
- {
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- Log.v("android", apkFullPath);
- onCoderReturn(apkFullPath);
- File apkFile = new File(apkFullPath);
- Uri uri = null;
- if (Build.VERSION.SDK_INT>= 24)
- {
- String path = MainActivity.instance.getApplicationContext().getPackageName() + ".fileProvider";
- Log.v("android", path);
- uri = FileProvider.getUriForFile(MainActivity.instance, path, apkFile);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- else
- {
- uri = Uri.fromFile(apkFile);
- Log.v("android", apkFile.getAbsolutePath());
- }
- onCoderReturn("install" + uri.getPath());
- intent.setDataAndType(uri, "application/vnd.android.package-archive");
- // 解决安卓 8.0 安装界面不弹出
- // 查询所有符合 intent 跳转目标应用类型的应用, 注意此方法必须放置在 setDataAndType 方法之后
- List<ResolveInfo> resolveLists = MainActivity.instance.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
- // 然后全部授权
- for (ResolveInfo resolveInfo : resolveLists)
- {
- String packageName = resolveInfo.activityInfo.packageName;
- MainActivity.instance.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- }
- MainActivity.instance.startActivity(intent);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
好了, 到此基本上真的结束了, 还有一个可优化的是安装完成可以做个自动启动 App 就完美了, 这个有时间继续完善! 时间过得好快 1 点开始写的, 现在都快 3 点半了, 困的不行了, 得睡觉了, 祝大家小长假玩的愉快, 有问题可以联系我一起探讨!
来源: https://www.cnblogs.com/wuzhang/p/wuzhang20190405.html