Unity 大版本更新之APK的下载与覆盖安装
作为一个游戏开发者,更新这个技能是必不可少的!更新分为游戏内的更新,也就是所谓的资源热更包括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点半了,困的不行了,得睡觉了,祝大家小长假玩的愉快,有问题可以联系我一起探讨!
Unity 大版本更新之APK的下载与覆盖安装的更多相关文章
- nginx开启gzip压缩后导致apk包下载不能正常安装
最后更新时间:2019/4/27 nginx一般都会开启gzip压缩,以提升传输性能. 配置如下: gzip on; gzip_comp_level 2; gzip_min_length 1k; gz ...
- Nginx集群之WCF大文件上传及下载(支持6G传输)
目录 1 大概思路... 1 2 Nginx集群之WCF大文件上传及下载... 1 3 BasicHttpBinding相关配置解析... 2 4 编写 ...
- Unity编程标准导引-1.1下载和安装Unity
本文为博主原创文章,欢迎转载,请保留出处:http://blog.csdn.net/andrewfan 1.1.下载和安装Unity 1.1.1 选取版本 首先找到Unity官方网站https://s ...
- 全网最简单的大文件上传与下载代码实现(React+Go)
前言 前段时间我需要实现大文件上传的需求,在网上查找了很多资料,并且也发现已经有很多优秀的博客讲了大文件上传下载这个功能. 我的项目是个比较简单的项目,并没有采用特别复杂的实现方式,所以我这篇文章的目 ...
- Expo大作战(一)--什么是expo,如何安装expo clinet和xde,xde如何使用
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- CentOS6安装各种大数据软件 第七章:Flume安装与配置
相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...
- flash builder 4.6 下载完成后安装不成功
从网上下载了一下flash builder 4.6 下载完成后安装不成功,说是有一个安装被挂起,不成安装成功结果从注册表中删除了pendingobject,还是不行,没有办法,从网上搜了一下,发现了大 ...
- Eclipse 官方简体中文语言包下载地址及安装方法
Eclipse 官方简体中文语言包下载地址及安装方法 打开Eclipse Babel Project 主页: http://www.eclipse.org/babel/downloads.php 根据 ...
- oracle 11g 服务端下载地址及安装说明
oracle 11g 服务端下载地址及安装说明 分类: Oracle 2013-11-17 19:40 988人阅读 ...
随机推荐
- lattice diamond 3.7安装破解
第一步安装:执行.EXE文件,一直下一步,最后license选择没有USB什么的那个(具体记不清了). 第二步破解:安装完成后在环境变量中将license路径指定到license文件即可(LM_LIC ...
- 【Android】5.6 弹出菜单(PopUp Menus)
分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 功能描述:用户单击按钮弹出菜单.当用户选择一个菜单项,会触发MenuItemClick事件并让弹出的菜单消失:如果 ...
- STL_算法_查找算法(lower_bound、upper_bound、equal_range)
C++ Primer 学习中. .. 简单记录下我的学习过程 (代码为主) //全部容器适用(O(log(n))) 已序区间查找算法 lower_bound() //找第一个符合的 ...
- jquery ajax中success与complete的执行顺序 (转)
http://blog.sina.com.cn/s/blog_4adc4b090101dhnh.html https://q.cnblogs.com/q/21810/ **************** ...
- java jsp失效问题--待解决
打印jps错误信息jps -J-Djps.debug=true -J-Djps.printStackTrace=true 未完待续...
- Query图像滑块插件 (支持触摸/滑动手势)
1.http://bxslider.com/ 2.http://www.slidesjs.com/ (http://www.html5cn.org/article-6437-1.html很多歌)
- ehcache OR Memcache
ehcache是纯java编写的,通信是通过RMI方式,适用于基于java技术的项目.memcached服务器端是c编写的,客户端有多个语言的实现,如c,php(淘宝,sina等各大门户网站),pyt ...
- JavaScript高级 面向对象(1)--添加一个div标签
说明(2017.3.28): 1. JavaScript是一种基于对象的多范式编程语言,不是面向对象,但离开对象不能活. 范式编程是指编程习惯.方式,分为过程式.对象式和函数式编程. 2. 面向对象是 ...
- cglib 动态代理基础篇
cglib 动态代理基础篇 CGlib是什么? CGlib是一个强大的,高性能,高质量的Code生成类库.它可以在运行期扩展Java类与实现Java接口. 下面我们将通过一个具体的事例来看一下CGli ...
- iOS边练边学--Segue数据逆传(用block代替delegate)
一.block与方法的异同点: 相同点是都是保存代码段,什么时候执行,什么时候调用 不同点是block不受类或者对象的约束:方法收到了类或者对象的约束 二.思路:(通讯录练习) 在联系人控制器中,添加 ...