Android通过后台service下载

首先介绍一下这个dome:通过service下载Word文档;当然你也可以使用我这个dome下载其他文件类型;代码中有注释修改文件类型即可。

为了方便大家快速引入项目,下面介绍下目录:

那么我们导入文件只需将Downloader、DownloadListener、DownloadService、MainActivity以及对应的布局文件导入,当然你还需要清单文件配置,具体详细看代码。

首先下载文件要先解决下载功能代码,Downloader代码如下:

package com.example.servicetest;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.content.Context;
import android.os.Environment;
import android.util.Log;

public class Downloader {
	String urlStr;// 下载链接
	String filePath;// 下载路径
	String fileName;// 下载文件名

	DownloadListener downloadListener;

	public void setDownloadListener(DownloadListener listener) {
		this.downloadListener = listener;
	}

	public Downloader(Context context, String url, String filePath, String fileName) {
		this.urlStr = url;
		this.filePath = filePath;
		this.fileName = fileName;
	}

	public Downloader(Context context, String url, String fileName) {
		this(context, url, "/download/", fileName);
	}

	/**
	 * 开始下载
	 */
	public void start() {
		URL url = null;
		try {
			url = new URL(urlStr);
			HttpURLConnection urlCon = (HttpURLConnection) url.openConnection();
			urlCon.setDoInput(true);
			urlCon.setRequestMethod("GET");
			urlCon.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");

			// 建立连接
			urlCon.connect();
			int length = urlCon.getContentLength();
			downloadListener.onStart(length);

			if (urlCon.getResponseCode() == 200) {

				File path = Environment.getExternalStoragePublicDirectory(filePath);
				File file = new File(path, fileName);
				BufferedInputStream is = new BufferedInputStream(urlCon.getInputStream());
				BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
				byte[] buffer = new byte[10240];
				int len = 0;
				int receivedBytes = 0;
				label: while (true) {
					// 这里如果暂停下载,并没有真正的销毁线程,而是处于等待状态
					// 但如果这时候用户退出了,要做处理,比如取消任务;或做其他处理

					if (isPause)
						downloadListener.onPause();
					if (isCancel) {
						downloadListener.onCancel();
						break label;
					}
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}

					while (!isPause && (len = is.read(buffer)) > 0) {
						out.write(buffer, 0, len);
						receivedBytes += len;
						downloadListener.onProgress(receivedBytes);
						if (receivedBytes == length) {
							downloadListener.onSuccess(file);
							break label;
						}
						if (isCancel) {
							downloadListener.onCancel();
							file.delete();
							break label;
						}
					}
				}

				is.close();
				out.close();
			} else {
				Log.e("jlf", "ResponseCode:" + urlCon.getResponseCode() + ", msg:" + urlCon.getResponseMessage());
			}

		} catch (MalformedURLException e) {
			e.printStackTrace();
			downloadListener.onFail();
		} catch (IOException e) {
			e.printStackTrace();
			downloadListener.onFail();
		}
	}

	private boolean isPause;

	public void pause() {
		isPause = true;
	}

	public void resume() {
		isPause = false;
		isCancel = false;
		downloadListener.onResume();
	}

	private boolean isCancel;

	public void cancel() {
		isCancel = true;
	}
}

我们可以看到下载主要代码部分在start()方法中。他是通过接口DownloadListener进行回调处理,下面贴出DownloadListener代码:

package com.example.servicetest;

import java.io.File;

public interface DownloadListener {

	void onStart(int fileByteSize);
	
	void onPause();

	void onResume();

	void onProgress(int receivedBytes);

	void onFail();

	void onSuccess(File file);
	
	void onCancel();
}

接下来我们需要service与activity交互进行下载,DownloadService代码如下:

package com.example.servicetest;

import java.io.File;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class DownloadService extends Service {
	static final int Flag_Init = 0; // 初始状态
	static final int Flag_Down = 1; // 下载状态
	static final int Flag_Pause = 2; // 暂停状态
	static final int Flag_Done = 3; // 完成状态
	String url;//下载地址
	String filetype;//文件类型
	private int progress = 0;// 下载进度
	public int getProgress() {
		return progress;
	}
	private int flag;// 下载状态标志
	public int getFlag() {
		return flag;
	}
	DownThread mThread;
	Downloader downloader;
	private static DownloadService instance;
	public static DownloadService getInstance() {
		return instance;
	}
	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onCreate() {
		Log.i("xuxu", "service.........onCreate");
		instance = this;
		flag = Flag_Init;
		super.onCreate();
	}

	@Override
	public void onStart(Intent intent, int startId) {
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		String msg = intent.getExtras().getString("flag");//通过标识判断下载状态
		url = intent.getExtras().getString("url");
		filetype=intent.getExtras().getString("filetype");
		if (mThread == null){
			mThread = new DownThread();
		}
		if(downloader == null)
		{
			downloader = new Downloader(this, url, filetype);
		}
		downloader.setDownloadListener(downListener);
		
		if (msg.equals("start"))
		{
			startDownload();
		} 
		else if (msg.equals("pause")) 
		{
			downloader.pause();
		}
		else if (msg.equals("resume")) 
		{
			downloader.resume();
		} 
		else if (msg.equals("stop"))
		{
			downloader.cancel();
			stopSelf();
		}

		return super.onStartCommand(intent, flags, startId);
	}

	private void startDownload() {
		if (flag == Flag_Init || flag == Flag_Pause) {
			if (mThread != null && !mThread.isAlive()) {
				mThread = new DownThread();
			}
			mThread.start();
		}
	}

	@Override
	public void onDestroy() {
		Log.e("xuxu", "service...........onDestroy");
		try {
			flag = 0;
			mThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		mThread = null;
		super.onDestroy();
	}

	class DownThread extends Thread {
		
		@Override
		public void run() {
			
			if (flag == Flag_Init || flag == Flag_Done) {
				flag = Flag_Down;
			}
			
			downloader.start();
		}
	}
	
	/**
	 * 下载监听
	 */
	private DownloadListener downListener = new DownloadListener() {
		
		int fileSize;
		Intent intent = new Intent();
		
		@Override
		public void onSuccess(File file) {
			intent.setAction(MainActivity.ACTION_DOWNLOAD_SUCCESS);
			intent.putExtra("progress", 100);
			intent.putExtra("file", file);
			sendBroadcast(intent);
		}
		
		@Override
		public void onStart(int fileByteSize) {
			fileSize = fileByteSize;
			flag = Flag_Down;
		}
		
		@Override
		public void onResume() {
			flag = Flag_Down;
		}
		
		@Override
		public void onProgress(int receivedBytes) {
			if(flag == Flag_Down)
			{
				progress = (int)((receivedBytes / (float)fileSize) * 100);
				intent.setAction(MainActivity.ACTION_DOWNLOAD_PROGRESS);
				intent.putExtra("progress", progress);
				sendBroadcast(intent);
				
				if (progress == 100) {
					flag = Flag_Done;
				}
			}
		}
		
		@Override
		public void onPause() {
			flag = Flag_Pause;
		}
		
		@Override
		public void onFail() {
			intent.setAction(MainActivity.ACTION_DOWNLOAD_FAIL);
			sendBroadcast(intent);
			flag = Flag_Init;
		}
		
		@Override
		public void onCancel(){
			progress = 0;
			flag = Flag_Init;
		}
	};
}
做完上述准备后需要做可视化界面进行操作,先贴出布局文件来:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="10dip"
    android:orientation="vertical" >
    

    <TextView 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="18sp"
        style="?android:textAppearanceMedium"
        android:padding="5dp"
        android:text="通过Service来模拟下载,如果把下载任务放在Activity中执行,则按返回键退出后,下载任务也会结束;但如果放在Service中,退出Activity后下载仍可继续"
        />
    
    <Button 
        android:id="@+id/btn_down"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="通过Service下载"
        android:textSize="18sp"
        android:onClick="onClick"
        />

    <ProgressBar
        android:id="@+id/progressBar1"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="fill_parent"
        android:padding="10dp"
        android:max="100"
        android:layout_height="wrap_content" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/button_pause"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="暂停/继续" />

        <Button
            android:id="@+id/button_cancel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="取消" />

    </LinearLayout>
    
    
    <TextView 
        android:id="@+id/text_desc"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:padding="6dp"
        style="?android:textAppearanceSmall"
        />
    
    <Button 
        android:id="@+id/btn_open"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打开文件"
        android:layout_gravity="center_horizontal"
        android:padding="6dp"
        android:visibility="gone"
        />
    
</LinearLayout>
那么现在我们可以做可视化界面操作,MainActivity代码如下:

package com.example.servicetest;

import java.io.File;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

/**
 * @author Administrator
 * 通过Service后台下载
 */

public class MainActivity extends Activity {
	public static final String ACTION_DOWNLOAD_PROGRESS = "my_download_progress";// 下载中
	public static final String ACTION_DOWNLOAD_SUCCESS = "my_download_success";// 成功
	public static final String ACTION_DOWNLOAD_FAIL = "my_download_fail";// 失败
	String url = "http://app.voofeng.com/UploadFiles/attached/word/1.docx";// 下载链接
	ProgressBar progBar;// 下载进度条
	MyReceiver receiver;// 广播
	TextView textView;// 显示下载路径
	Button btnOpen;// 打开文件

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
		progBar = (ProgressBar) findViewById(R.id.progressBar1);
		textView = (TextView) findViewById(R.id.text_desc);
		btnOpen = (Button) findViewById(R.id.btn_open);
		if (DownloadService.getInstance() != null) {
			progBar.setProgress(DownloadService.getInstance().getProgress());// 获取DownloadService下载进度
		}
		receiver = new MyReceiver();
	}

	@Override
	protected void onStart() {
		super.onStart();
		IntentFilter filter = new IntentFilter();
		filter.addAction(ACTION_DOWNLOAD_PROGRESS);
		filter.addAction(ACTION_DOWNLOAD_SUCCESS);
		filter.addAction(ACTION_DOWNLOAD_FAIL);
		registerReceiver(receiver, filter);// 注册广播
	}

	@Override
	protected void onStop() {
		super.onStop();
		unregisterReceiver(receiver);// 注销广播
	}

	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btn_down:// 开始下载
			startDownloadService();
			break;
		case R.id.button_pause:// 暂停下载
			pauseDownloadService();
			break;
		case R.id.button_cancel:// 取消下载
			stopDownloadService();
			break;

		default:
			break;
		}
	}

	/**
	 * 开始下载
	 */
	void startDownloadService() {
		if (DownloadService.getInstance() != null
				&& DownloadService.getInstance().getFlag() != DownloadService.Flag_Init) {
			Toast.makeText(this, "已经在下载", 0).show();
			return;
		}
		Intent it = new Intent(this, DownloadService.class);
		it.putExtra("flag", "start");
		it.putExtra("url", url);
		it.putExtra("filetype", ".doc");// 文件后缀名(注意要确认你下载的文件类型)
		startService(it);
	}

	/**
	 * 暂停下载
	 */
	void pauseDownloadService() {
		String flag = null;
		int f = DownloadService.getInstance().getFlag();
		if (DownloadService.getInstance() != null) {
			// 如果当前已经暂停,则恢复
			if (f == DownloadService.Flag_Pause) {
				flag = "resume";
			} else if (f == DownloadService.Flag_Down) {
				flag = "pause";
			} else {
				return;
			}
		}
		Intent it = new Intent(this, DownloadService.class);
		it.putExtra("flag", flag);
		startService(it);
	}

	/**
	 * 取消下载
	 */
	void stopDownloadService() {
		Intent it = new Intent(this, DownloadService.class);
		it.putExtra("flag", "stop");
		startService(it);
		progBar.setProgress(0);
	}

	class MyReceiver extends BroadcastReceiver {

		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (action.equals(ACTION_DOWNLOAD_PROGRESS)) {// 下载中显示进度
				int pro = intent.getExtras().getInt("progress");
				progBar.setProgress(pro);
			} else if (action.equals(ACTION_DOWNLOAD_SUCCESS)) {// 下载成功
				Toast.makeText(MainActivity.this, "下载成功", Toast.LENGTH_SHORT).show();
				final File f = (File) intent.getExtras().getSerializable("file");
				btnOpen.setVisibility(View.VISIBLE);
				textView.setText("文件已保存在:" + f.getAbsolutePath());
				btnOpen.setOnClickListener(new View.OnClickListener() {

					@Override
					public void onClick(View v) {
						openFile(f);
					}
				});
			} else if (action.equals(ACTION_DOWNLOAD_FAIL)) {// 下载失败
				Toast.makeText(MainActivity.this, "下载失败", Toast.LENGTH_SHORT).show();
			}
		}

	}

	/**
	 * 打开文件
	 * 
	 * @param f
	 */
	private void openFile(File f) {
		Intent intent = new Intent();
		intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		intent.setAction(android.content.Intent.ACTION_VIEW);
		// String type = "audio";
		String type = "application/msword";// 文件类型(word文档)
		intent.setDataAndType(Uri.fromFile(f), type);
		startActivity(intent);
	}

	/**
	 * 监听返回操作
	 */
	@Override
	public void onBackPressed() {
		if (DownloadService.getInstance() != null) {
			final int f = DownloadService.getInstance().getFlag();
			// XXX:暂停状态下退出???
			if (f == DownloadService.Flag_Down || f == DownloadService.Flag_Pause) {
				new AlertDialog.Builder(this).setTitle("确定退出程序?").setMessage("你有未完成的下载任务")
						.setNegativeButton("取消下载", new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {
								stopDownloadService();
								MainActivity.super.onBackPressed();
							}
						}).setPositiveButton("后台下载", new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {

								if (f == DownloadService.Flag_Pause) {
									Intent it = new Intent(MainActivity.this, DownloadService.class);
									it.putExtra("flag", "resume");
									startService(it);
								}

								MainActivity.super.onBackPressed();
							}
						}).create().show();
				return;
			}
			DownloadService.getInstance().stopSelf();//退出停止下载(也可不用则后台下载)
		}
		super.onBackPressed();
	}
}

可以看到打开文件可以设置打开类型,那么系统会调用相应的app供我们选择;当然我们需要设置监听返回键,根据自己的需要判断退出APP是否需要停止service;
废话补多少直接给dome地址,有什么问题、建议可以提出来!

下载地址:http://download.csdn.net/download/yanxuxu123/9721647


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值