图形引擎实战:手游Android端后台下载技术分享

一.功能特点

手游android端后台下载SDK是畅游自主研发的一款移动平台android端后台文件下载工具包,它主要提供网络文件的后台下载功能,功能完善,性能高,可以满足游戏制作有关后台下载文件的需求。使用该系统,玩家可以不用等待漫长的前台下载过程,只需切换到后台就可以下载文件,极大提升用户体验,具有以下特点:

  1. 支持后台下载,用户开启下载后,将游戏切换到后台,下载继续进行,不中断、不闪退
  2. 支持大规模文件的后台下载,支持了上万个文件的后台下载
  3. 适配度高,最低支持到android5.0, 同时也支持模拟器
  4. 支持大文件的下载,通过采用切割技术,开多个线程同时下载各个片段,最后实现整个文件的下载
  5. 下载速度最快达到每秒10M以上
  6. 采用多线程技术,可以同时下载多个文件
  7. 支持限速功能,在宽带受限的情况下,用户可以限制下载速度,不影响其它app的使用
  8. 断点续传技术,用户可以随时暂停下载,或者在下载失败后,后续可以继续下载
  9. 支持断线重连
  10. 通知栏显示下载进度条,下载完成后,只要不点击通知栏,app一直驻留不闪退

二.主要技术原理

后台下载

首先,我们说一下普通的下载,就是根据客户端提供的某个文件在服务端的地址,使用http连接技术,将这个文件下载到本地,支持http和https两种url地址。

那什么是后台下载呢?后台下载和普通下载有什么不同?

所谓的后台下载,就是将手机切换到后台以后,我们的下载仍然可以正常运行,用户启动后台下载后,可以打开其它app,一边看着新闻,聊着天,一边后台跑着下载程序,两不耽误。

前台下载是无法实现这个功能的,只要你切换到后台,下载就停止了。

我们的后台下载技术,基于android自带的下载模块实现,启动下载后,将游戏切换到后台,下载继续进行,不中断、不闪退。

第一步,实现一个普通的下载DownTask

Class DownloadTask extends Thread

{

@Override

public void run()

{

根据url获得远程链接

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

int timeout = 10;

conn.setConnectTimeout(timeout * 1000);

conn.setReadTimeout(timeout * 1000);

conn.setRequestMethod("GET");

然后,获得数据流,并读取数据到文件里

InputStream inputStream = conn.getInputStream();

int bytesRead = -1;

byte[] readBuf = new byte[1024];

bytesRead = inputStream.read(readBuf);

while(bytesRead != -1)

{

raf.write(readBuf, 0, bytesRead);

。。。。。。

}

}

}

第二步,将下载嵌入到嵌入到android系统service框架内,通过将下载模块嵌入到service内,完成后台下载逻辑,可以实现下载程序的后台运行。

public class DownloadService extends Service

{

@Override

public int onStartCommand(Intent intent, int flags, int startId)

{

if(intent != null)

{

int downloadId = intent.getIntExtra("downloadId",0);

String url = intent.getStringExtra("url");

String downloadPath = intent.getStringExtra("downloadPath");

DownloadFileInfo fileInfo = new DownloadFileInfo(url, downloadPath);

DownloadTask task = new DownloadTask( fileInfo,maxBandwidth);

task.download();

}

}

}

第三步,启动service

Intent intent = new Intent(context, DownloadService.class);

intent.putExtra("downloadId",needInfo._downloadId);

intent.putExtra("url",needInfo._url)

intent.putExtra("downloadPath",needInfo._downloadPath);

context.startService(intent);

通过以上几步,一个后台下载,就跑起来了。

断点续传

对于一个几个G,几十G的大文件来说, 断点续传是必须要有的功能。当我们下载了一半的时候,手机没电了,或者网络断了,或者游戏闪退了,如果没有断点续传,那就悲剧了,重新启动下载,就会重新开始下载,不仅浪费了时间,浪费了电量,还浪费了流量,这对用户是不可接受的。而有了断点续传就好多了,我们再也不用担心下载过程中发生各种意外了。

断点续传是怎么实现的呢?android系统的http模块支持片段下载,我们可以把每次下载的起始点、偏移量等数据保存到本地,然后,每次启动下载,首先查询之前有没有下载过,下载记录里如果以前下载过,那我们就从上次下载的位置接着下载;没有下载过则从头下载。下载开始后,用户可以随时暂停下载、关闭下载,或者在下载失败后,后续可以继续下载。

多线程的应用

线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。进程中如果包含多个线程在同时运行,就是多线程了,在多线程运行环境下,所有线程轮流使用 CPU 的使用权,根据优先级,给每个线程分配占用 CPU 的时间。

游戏里的资源,不压缩的散文件有上万个,压缩到几个大文件,每个文件,也是好几个G大。不管是散文件,还是大文件,如果把下载任务放到主线程里,那游戏体验非常不好,不仅卡顿,下载的时候,还干不了别的。基于这些,多线程技术的使用,是必选的了。

采用多线程技术,一方面,上万个文件需要下载,速度不够高。没啥好办法,多开几个下载队列,同时下载,实现了多个文件的同时下载。另一方面,几个G的单一大文件,速度不够高。在单文件下载性能优化无法提高的情况下,可以将几个G的大文件切割成若干不同片端,每个片段开一个线程来分别下载各个片段,然后几个线程同时下载,最后实现整个文件的下载,极大提高了大文件的下载速度,通过实测,下载速度最快达到每秒十几M。

推送通知

通知栏显示采用操作系统原生API接口实现,创建通知的基本步骤如下:

使用getSystemService 拿到 NotificationManager 的管理类,使用Notification 设置标题、内容、图片等,最后调用 NotificationManager 的 notify() 调出通知栏

由于android手机不同品牌,版本不一致,而且有的大厂(华为,oppo,三星、小米等)的操作系统没有跟随google版本走,自己再维护一套,导致通知栏的显示,在不同品牌手机,不同版本上的表现不一致,最后通过适配来解决差异性。

三.代码结构

代码分为3层结构

底层:

采用java语言,调用android原生API实现,提供aar文件

1.TakeDownload对外开放接口,对内向DownloadEngine传递参数

2.DownloadEngine是下载管理器,负责下载队列的创建、管理,下载文件的收集、管理,回调消息的发布。通过创建若干下载队列,采用多线程,几个队列同时下载文件。

3.downloadService负责下载任务的创建,管理,

4.DownloadTask,负责单个文件的下载

5.LocalData,负责本地数据存储,将每个文件的下载状态信息保存下来

6.NotificationBar,负责通知栏显示

中间层:

采用C#语言,封装底层接口实现各个功能,然后,向上层提供调用接口,提供dll文件

逻辑层:采用C#语言,调用中间层提供的接口,实现相关功能

四.开发中遇到的难点及解决办法

从设计开发初期,到项目实际使用中,断断续续,遇到了很多的问题,其中有几个典型问题,这里记录了下来。

1.在某些低端机上,存在内存不足的问题。这个,不管在什么档次的设备上,内存消耗,永远是个问题。需要尽量减少内存泄漏,释放短期内不用的内存,还有,可以使用内存池来减少碎片。

2.弱网环境下,网络时好时坏,导致下载经常失败。网络断开,经常会遇到。后来,加了一个重复下载机制。每个文件,都可以尝试下载三次,超过三次以上,还没有下载成功,就认为是失败,直接返回给上层,由上层来弹出提示框,等待用户决定,是否重新下载。

3.上万个文件需要下载,速度不够高。没啥好办法,多开几个下载队列,同时下载。项目使用过程,建议把这些小文件压缩到若干个大文件,可以提高速度。

4.几个G的单一大文件,速度不够高。在单文件下载性能优化无法提高的情况下,可以把文件切割成若干片段,每个片段开一个线程,然后几个线程同时下载。

5.通知栏在很多设备上出现异常,表现不一。不同设备,操作系统版本号不同,而且,有的机型,即使版本号一样,但由于自己对系统做了修改而有差异,需要做适配。

6.文件下载到本地后,需要进行md5、crc等文件校验。项目在验证的过程中,出现了一个所有人没有想到的小插曲,就是在所有文件下载完毕后,他们直接进入手机目录下,手动将下载的文件拷贝到了电脑里,然后用文件比较工具,比较下载文件和源文件的二进制内容,发现很多文件都不同。这个问题,当时我和另一个同事,都被搞懵了,因为demo里有md5校验都是对的,但是把文件手动拷出来比较就不对,我们投入了两个工作日时间去查找问题,怎么也查不到。最后,发现是手机操作系统做了文件保护机制,如果手动拷贝文件,拷出来的文件已经发生了变化。后来,我们是通过手机助手软件来导出了文件,经过和源文件比较,才验证了文件的正确性。

7.还遇到个问题,项目在测试的时候,他们先下载一半的时候中途退出程序,然后手动进入手机目录下,把下载目录给删除掉,接着,重新启动下载,出现了文件下载完后md5校验不对的问题,而且是必现的。之前,一直没有这么测试过,也就从来没有发现这个问题。这个问题主要是因为下载的文件和数据库文件不在同一个目录下,中途删除下载目录的时候,没有把另一个目录下的记录文件下载进度的数据库文件给删掉,导致启动下载的时候,会首先查找文件下载进度,查找到有个文件下载了一半,然后就从一半的位置接着下载,然后就出现了文件校验不对的问题。知道了问题所在,就好修复了。在每次下载某个文件的时候,如果数据库里有这个文件的下载进度记录的时候,再查找一下本地是否有这个文件,如果没有就把数据库里的这条记录给清空了。

欢迎加入我们!

感兴趣的同学可以投递简历至:CYouEngine@cyou-inc.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搜狐畅游引擎部

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值