作为一个游戏开发者,更新这个技能是必不可少的!更新分为游戏内的更新,也就是所谓的资源热更包括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点半了,困的不行了,得睡觉了,祝大家小长假玩的愉快,有问题可以联系我一起探讨!


最新文章

  1. asp.net mvc跨域filter
  2. css中important的用处
  3. CodeForces Gym 100500A A. Poetry Challenge DFS
  4. 学习练习 java 线程
  5. sql server 自定义函数
  6. 保存android程序崩溃日志到SD卡
  7. 《STL源代码分析》---stl_heap.h读书笔记
  8. 基于 Koa平台Node.js开发的KoaHub.js的输出json到页面代码
  9. python基础笔记(一)
  10. 【转】FIO使用指南
  11. SQL Server 2016 快照代理过程分析
  12. JS Replace 全部替换字符的用法小结
  13. IDEA上传码云报错Push rejected: Push to origin/master was rejected
  14. JavaScript-isFinite()判断是否数字有效
  15. 2018.10.30 NOIP训练 【模板】树链剖分(换根树剖)
  16. tensorflow 优化图
  17. InstallShield卸载状态
  18. MicroRNA in Control of Gene Expression: An Overview of Nuclear Functions 微RNA控制基因表达:核功能概述
  19. 突破MIME限制上传
  20. 设置CentOS7虚拟机使用静态IP上网

热门文章

  1. onethink迁移
  2. flink watermark介绍
  3. application , application pool., W3wp ,httpapplication, domain
  4. nyoj 504 课程设计
  5. SparkStreaming操作Kafka
  6. Along with all the above benefits, you cannot overlook the space efficiency and performance gains in using DataFrames and Dataset APIs for two reasons.
  7. 汉诺塔X
  8. 算法初探——大O表示法
  9. python下RSA加密解密以及跨平台问题
  10. redis未授权