服务项目
新闻详情
NEWS DETAILS
通过上面几节的介绍,对Java和Android中的线程应该有了一个简单的了解,下面通过上面讲解的一些知识实现一个简单的多线程下载。在这个下载功能的实现中,需要用到以下知识点:多线程、Android中的服务、访问网络资源、通知、文件的存储等。首先了解一下这个实例的界面,如图13.11至图13.14所示。
这个实例界面很少,只要一个按钮就行了,下面来看看实现过程。
(1)单击下载的事件处理。单击下载按钮会跳转到一个服务,把要下载的文件地址传过去。
Eutton button = (Button) findViewByld(R.id.do讨nload); :.
button.setOnClickListener(new OnClickLis七巳门8工(){
^Override 1 飞
public void onClick (View v) {
String path = "http://www.etwap.cn/cms/aFetion/
etfeti cmV2.4.apk";
Intent intent = new Intent () ; ■■-
intent.putExtra("p$th”, path);
intent.setclass(TestDownload_lActivity.this,
DownloadService.class);
startservice(intent);
}
});
(2)下载的服务类,主要的下载都在这个类中实现。
继承Service类,覆盖方法,在onStartCommand方法中获取界面传过来的值,判断SD卡的情况,获取NotificationManager的实例,设置通知栏的一些属性,代码如下:
@Override
public int onStartCommand(Intent intent, int flags, int startld) {
path = intent.getStringExtra("path");
//创建文件
if(android.os.Environment.MEDIA^MOUNTED.equals(android.os.
Environment.getExternaLStorageState())){
storageDir = new File(Environment.getExternalStorageDirec
"download/");
name - path.substring(path.lastTndexOf(”/”) + 1);
file = new File(storageDir.getPath() , name);
}
//获取 Not if icationManager
this.manager = (NotificationManager)getSystemService
(NOTIFICATION_SERVICE);
this.notification = new Not;
//设置下载的过程中单击通知栏,返回到主界面
intent = new Intent(this, TestDownload_lActivity.class);
pendingintent = Pendingintent.getActivity(this/ 0, intent,
Pendingintent ・ FLAG_CANCEL_CURRENT);
〃设置通知栏显示的内容
notification.icon = R.drawable.ic_launcher;
notification. tickerText ="开始下栽";
notification.setLatestEventlnfo(this, name, n0%n, pendingintent);
//发出通知
manager・notify^。, notification);
new Thread (new DownloadRunnable ()) . star ; //开启下载的銭程
return super.onStartCommand(intent, flags, startld);
}
通过Handler处理下载的信息,下载完成或失败时,更新通知栏:
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case DOWNLOAD—COMPLETE://下载成功
//铃声提醒
notification.defaults = Notification.DEFAULTJSOUND;
notification.setLatestEventlnfo(DownloadService.this, name,"下
裁完成,单击安装。",pendingintent);
manager.notify(0, notification);
break;
case DOWNLOAD_FAIL: / /下载失败
notification.setLatestEventlnfo(DownloadService.this, name,
"下载失败”$ pendinglntent);
_ Android_史务线程介纟目 |i77
manager.notify(0, notification);
break;
default:
break;
}
};
};
实现Runnable接口,当文件大小不为0时,通过Handler的方法sendMessage发送消息:
//下载文件的线程
private class DownloadRunnable implements Runnable{
^Override
public void run() {
Message message = handler.obtainMessage();
message.what = DOWNLOAD_COMPLETE;
try{//文件存储的路径是否存在
if(!storageDir.exists ()){
storageDir.mkdirs();
}
if (! file. exists () ) { //文件是否存在
file.createNewFile();
}
long downloadsize = downloadFile(path, file);
if(downloadSize>0){
//下載成功
handler.sendMessage(message);
}
}catch (Exception e) {
message.what = DOWNLOAD„FAIL;
handler.sendMessage(message);
}
//从网络上下载文件
public long downloadFile(String downloadUrl,File saveFile) throws
IOExcep七ion{
int downloadCount = 0;
int currentsize = 0;
long totalSize = 0;
int updateTotalSize - 0;
HttpURLConnection httpConnection = null;
Inpu七Stream is = null;
FileOutputStream fos = null;
try {
URL url = new URL(downloadUrl);
httpConnection - (HttpURLConnection)url.openConnection();
httpConnection・ setRequestProperty (''User-Agent'S 11 PacificHttpClient");
if(currentsize > 0) {
httpConnection. setRequestProperty ("RANGE", ,,bytes=1' + currentsize + ;
}
httpConnection.setConnectTimeout(10000);
httpConnection.setReadTimeout(20000);
updateTotalSize = httpConnection.getContentLength();
if (httpConnection,getResponseCode() == 404) {
throw new Exception (*'f ail! M);
}
is = httpConnection,get工nputStream();
fos - new FileOutputStream(saveFile, false);
byte buffer[] = new byte[4096];
int readsize = 0;
while((readsize = is.read(buffer)) > 0){
fos•讨rite(buffer, 0, readsize);
totalsize +二 readsize;
_ . if((downloadCount = 0)||(int) (totalSize*100/updateTotalSize)
-10>downloadCount){
dovmloadCount += 10;
, notification. setLatestEventlnfo (DownloadSexrvice. this,"正在
下載“,(int)totalSxze*100/updateTotalSize+"%", pendingintent);
I manager・not;i£y(0, notification);
}
} catch (IOException e) {
e.printStackTrace ();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (httipConnectiion != null) {
httpConnection.disconnect();
}
if (is != null) {
is.close();
}
if(fos !- null) {
fos ・ close();
}
}
return totalsize;
}
(3)Service类和用户权限在AndroidManifest.xml中的声明。
<?xml version="l. 0" encoding=',utf-8,,?>
<manifest xmlns:android^^http://schemas ・android.com/apk/工es/android"
package:="coin. zhy.download"
android:versionCode="1”
android: versionName=11l. 0n >
<uses-sdk android:minSdkVersion=" 8'* />
<uses-permission
android: name= "android. permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name=,1 android.permission.INTERNET"/>
<application
android: icon="@drawab丄e/ic_1aunc:he:r”
android:label=H@string/app_namen >
<activity
android:name=".TestDownload_lActivity"
android:label=H@string/app_name" >
<intent-filter〉
<action android:name="android.intent.action.MAIN" />
<category android:name=,,android.intent.category.LAUNCHER” />
</intent-filter>
</activity>
<service android: name="DownloadService"X/service>
</application>
</manifest>
至此,下载功能就实现了。如果有多文件一起下载,还需要做相应的处理,在这里就不多做说明了,有兴趣的读者可以自己去实现。