![Android智能穿戴设备开发实战详解](https://wfqqreader-1252317822.image.myqcloud.com/cover/166/31729166/b_31729166.jpg)
4.3 远程数据下载解决方案
下载是指通过网络进行传输文件,把互联网或其他电子计算机上的信息保存到本地电脑中的一种网络活动。下载可以显式或隐式进行,只要是获得本地电脑上所没有的信息的活动,都可以认为是下载,如在线观看。在Android穿戴设备开发过程中,下载功能是十分常见的一个应用。在本节的内容中将详细讲解在Android穿戴设备中实现远程下载数据的基本知识,为读者步入本书后面知识的学习打下基础。
4.3.1 获取图片数据的方法总结
在Android系统应用中,获取网络中的图片工作是一件耗时的操作,如果直接获取有可能会出现应用程序无响应(ANR:Application Not Responding)对话框的情况。对于这种情况,一般的方法就是使用线程来实现操作。在Android网络应用中,有如下三种获取网络图片的方法。
(1)直接获取,例如下面的演示代码。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00089001.jpg?sign=1738881173-zVmyhZvyUfuzkTOb9QTLGM1MtwWaIcYV-0-c5cf1222fe54e8145fa06d73de53413b)
(2)对应的公用方法的实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00089002.jpg?sign=1738881173-xVgGyGG6HmYVl4nOcfB8aTkaKbVG7aE0-0-e9ee31ec8231618b8ea623a38a536388)
(3)后台线程获取url图片,例如下面的演示代码。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00089003.jpg?sign=1738881173-zZ22p3y1cWR9TCgGWwdZ9gjKV7eQ3oZI-0-e2a20874f2e5c1cad51294eb5894e6f0)
(4)AsyncTask获取url图片,例如下面的演示代码。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00089004.jpg?sign=1738881173-Mkna4yfrwujEIKfiEPot5H1ti9uNm7Zv-0-20a935e6388b5309a17b3f74efb27aee)
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00090001.jpg?sign=1738881173-rCKUG3wjQlR3tWu7OfZRKxqzRQNHA5gs-0-16f8fe928a560cb722e40856e90f44ce)
在接下来的内容中将通过一个具体实例的实现过程来讲解在Android穿戴设备中下载远程网络图片的方法。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00090002.jpg?sign=1738881173-e4gXEl9aeFPmXnzqqCcO572D0hXjsQDV-0-694714c808f8ab59e3b8802ea090504f)
本实例的具体实现流程如下所示。
(1)在布局文件main.xml中设置一个网址文本框。
(2)编写主程序文件GetAPictureFromInternetActivity.java,主要实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00090003.jpg?sign=1738881173-bAbjhzJIV8ZW0cmGWFtr2ZXs5KwuN57Q-0-cfbd96564e595855a64550531d4f92db)
执行后的效果如图4-4所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00090004.jpg?sign=1738881173-XP6dzD6ZrMA8Ooc36pAH6VYPqSTulQmJ-0-3ccd61d6b068b24d12d4cfbe1038a338)
图4-4 执行效果
4.3.2 JSON数据传输的常见用法
JSON是JavaScript Object Notation的缩写,是一种轻量级的数据交换格式。JSON基于JavaScript(Standard ECMA-262 3rd Edition - December 1999)的一个子集,采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。易于人们阅读和编写,同时也易于机器解析和生成。
简单来说,JSON就是JavaScript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构。
(1)对象
对象在js中表示为用“{}”括起来的内容,数据结构为{key:value,key:value,…}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为对象.key获取属性值,这个属性值的类型可以是数字、字符串、数组、对象几种。
(2)数组
数组在js中是中括号“[]”括起来的内容,数据结构为["java","javascript","vb",…],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是数字、字符串、数组、对象几种。
经过对象、数组这两种结构即可组合成复杂的数据结构。
和XML一样,JSON也是基于纯文本的数据格式。由于JSON天生是为JavaScript准备的,因此,JSON的数据格式非常简单,可以用JSON传输一个简单的String,Number,Boolean,也可以传输一个数组,或者一个复杂的Object对象。
用JSON表示String,Number和Boolean的方法非常简单,例如用JSON表示一个简单的String数据“abc”,则其表示格式为:
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00091001.jpg?sign=1738881173-9lK8j2FblRW92n40ekAOXrF3IWT0QC9w-0-196410ca4113061708a2ebe418ec95b7)
除了字符",\,/和一些控制符(\b,\f,\n,\r,\t)需要编码外,其他Unicode字符可以直接输出。图4-5所示是一个String的完整表示结构。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00091002.jpg?sign=1738881173-C0bJRFMXCFMccemTEMOVV98cB5ZirHuH-0-98d1437c6e8a1b52f0b31f902b42a0b6)
图4-5 String的完整表示结构
在接下来的内容中将通过一个具体实例的实现过程来详细讲解在Android系统中远程下载服务器中的JSON数据的方法。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00091003.jpg?sign=1738881173-zfHLq3lLf84izHnu4PtIeQXSyZHGcS9u-0-49c80947386830bfc477ab01bbf944a9)
本实例的具体实现流程如下所示。
(1)使用Eclipse新建一个JavaEE工程作为服务器端,设置工程名为“ServerForJSON”。自动生成工程文件后,打开文件web.xml进行配置。
(2)编写业务接口Bean的实现文件NewsService.java,具体代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00091004.jpg?sign=1738881173-1vYeWtkO3BAnMYLoURU46EH9wYyATViO-0-6fc1cf2d4a4c7072f35cea81cb15b2f6)
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00092001.jpg?sign=1738881173-ZyWcnU17SPnFqudPnVmh8LdZo5edilId-0-71b3bc32852531b3d73d2d65f4e06296)
(3)设置业务Bean的名称为NewsServiceBean,实现文件NewsServiceBean.java的具体代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00092002.jpg?sign=1738881173-P8NZGvRnJ7dxzEvXEIruhvjmfe3hOnCF-0-bf8fb93b9fd031e003d5af6870d71366)
(4)创建一个名为“News”的实现类,实现文件News.java的具体代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00092003.jpg?sign=1738881173-5VK1wXJLYFczeIwWFlu0oM8yn2IxMihQ-0-966a810a7a6bcb31b6e27f835cc01242)
(5)编写文件NewsListServlet,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00093001.jpg?sign=1738881173-ofPtCtd5uAQXP7s0TT3ylVXRckxCvRyz-0-55c5be0a3a5119bade4d659d4cc8ce6f)
(6)新建一个JSP文件jsonnewslist.jsp,在里面引入JSON功能,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00093002.jpg?sign=1738881173-eVUVq4EuiRvZDfuHQxA1eHepQdmYDUPd-0-7d84920538bd1e8253271724e5a264e1)
(7)使用Eclipse新建一个名为“GetNewsInJSONFromInternet”的Android工程文件,在文件AndroidManifest.xml申明对网络权限的应用。
(8)编写主界面布局文件mian.xml,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00093003.jpg?sign=1738881173-Xs9zZlqP239DsJTSAivYXQufO9ff5pzY-0-8011c9eeb970e66f01575366ef6581f1)
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00094001.jpg?sign=1738881173-6RTpkPLLhnbAqMv2npW6gZbvt9uzCNmy-0-e77ce0f7f58c79964e1f4f6be9317647)
(9)编写文件MainActivity.java,功能是获取JSON数据并显示数据,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00094002.jpg?sign=1738881173-zrF0yAAmfWpC28omf0BzFMsOKfjv8waM-0-84f5c7acb5b2e3cbc850c7a06c061c2c)
(10)编写文件NewsService.java,定义方法getJSONLastNews()请求前面搭建的JavaEE服务器,当获取JSON输入流后解析JSON的数据,并返回集合中的数据。文件News-Service.java的具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00095001.jpg?sign=1738881173-lHCOFo3WUMl6wEh1lMw82aJTdTagYnfb-0-9a36c5b5ddc9842fba13af3ab4d457f4)
到此为止,整个实例已介绍完毕,执行后将成功获取服务器端JSON的数据。
4.3.3 用多线程提升处理效率
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启多个下载通道。当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配。如果线程多,下载的速度就会越快。现在流行的下载软件都是支持多线程的。在本节的内容中将详细讲解在Android系统中实现多线程下载的过程。
1.多线程下载文件的过程
在Android系统中,实现多线程下载的基本过程如下所示。
(1)获得下载文件的长度,然后设置本地文件的长度。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00095002.jpg?sign=1738881173-JlgBglmrQBEQQDkhXefpPbwdxIXjCh7W-0-7875d31f157300904787aef4efa6c755)
(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。例如文件的长度为6M,线程数为3,那么每条线程下载的数据长度为2M,每条线程开始下载的位置如图4-6所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00096001.jpg?sign=1738881173-dosS2nRc1A6uoAZD4fHjlEc1rSo6SHZJ-0-29bb30efd575362b22e20d9c7e3c6736)
图4-6 每条线程开始下载的位置
例如10M大小,则使用三个线程来下载,具体说明如下所示。
● 线程下载的数据长度:(10%3== 0 ? 10/3:10/3+1),第1,2个线程下载长度是4M,第三个线程下载长度为2M。
● 下载开始位置:线程id*每条线程下载的数据长度=?。
● 下载结束位置:(线程id+1)*每条线程下载的数据长度-1=?。
(3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,例如指定从文件的2M位置开始下载,下载到位置(4M—1byte)为止,代码如下:
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00096002.jpg?sign=1738881173-pSnbuNS1GCJoUmuIcRACD0WwlrJ0aeYj-0-78a64eeca0810b5229aa468b14b70866)
(4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00096003.jpg?sign=1738881173-aaMjLfqkZ2w1AbK0DBqKm4fJNV3GoMjB-0-b1cb1251d33cd5400102964f91d288c9)
2.在穿戴设备中实现多线程下载
本实例介绍了在Android穿戴设备下通过HTTP协议实现断点续传下载的方法。本实例是一个HTTP协议多线程断点下载应用程序,直接使用单线程下载HTTP文件对初学者来说是一件非常简单的事。多线程断点需要具备如下所示的功能。
● 多线程下载。
● 支持断点。
在接下来的内容中将通过一个具体实例的实现过程来讲解在Android手机中下载在线铃声的方法。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00096004.jpg?sign=1738881173-Fd65vzBCfFHXslwm39BzYpPUKMfPd3H0-0-82f04515b1da5e17e9e3c4b4093374c5)
本实例的具体实现流程如下所示。
(1)打开Eclipse,新建一个名为“MultipleThreadDownload”的动态Web工程。然后准备一个MP3文件保存在WebContent目录下,最后发布服务器端的Web工程程序。
(2)打开Eclipse,新建一个名为“Multiple”的Android工程,然后编写主程序文件main.xml。
(3)创建数据库管理类DBOpenHelper,实现文件DBOpenHelper.java的具体代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00097001.jpg?sign=1738881173-D3cw9Su04P1NjU27Ppb85I7RpGXVUWpy-0-0b58398048888e065b26339c1d43b9b8)
(4)建立数据库业务操作类FileService,此类的实现文件是FileService.java,具体代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00097002.jpg?sign=1738881173-1OfBX2y4yA0WggtBvaW5ZKoja4AObReu-0-951376cef9fb863d582b014073ce0b27)
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00098001.jpg?sign=1738881173-2lEBGIqDCbyMxgC98e7DZYfytBzLmlpC-0-f4f445fef7fbbbc78fb32f334d5b246e)
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00099001.jpg?sign=1738881173-1aiq2B3Jj33vuhPUihPcH7kzOhnTOrKw-0-b03164a386a995ffc1b5ee3f0416c447)
(5)编写文件下载FileDownloader类,此类调用类DownloadThread实现具体的下载功能。
(6)FileDownloader类在文件FileDownloader.java中定义,DownloadThread类在文件DownloadThread.java中定义。
(7)在FileDownloader类中调用了DownloadProgressListener类来监听下载进度,DownloadProgressListener类在文件DownloadProgressListener.java中定义,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00099002.jpg?sign=1738881173-CEX5l1N0slavJTzb2vOpNOsju9SycwdY-0-706e4f6d2030bd9b1c9c5842eaf47e82)
(8)编写文件主Activity文件MultipleThreadDownloadAndroid.java,负责显示下载界面、与用户交互、响应用户等事件。
(9)在文件AndroidManifest.xml中申明使用网络的权限和操作SDCard的权限,具体实现代码如下所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00099003.jpg?sign=1738881173-Y0U3ErSY96W6tPQEceMUamZeeO43P1W2-0-f2a80ebeb886ddd51ab24ce736ba370f)
到此为止,整个实例已介绍完毕,执行后的效果如图4-7所示。
![](https://epubservercos.yuewen.com/850D74/17180246404476806/epubprivate/OEBPS/Images/img00099004.jpg?sign=1738881173-pwJLCoHPIKVurKAMOShN87FZAFXSKl79-0-48d5a71778859299c2f27ad70577e59d)
图4-7 执行效果