首先介绍一下这个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.youkuaiyun.com/download/yanxuxu123/9721647