这个demo是对前一篇断点后台下载的完善。
demo的总体效果是可以同时进行两个下载任务,任务的进行状态分为:开始,连接中,暂停,完成,继续;通知栏进度条显示的是开始任务的平均进度。
先看一下效果图:
先说一下实现思路,数据显示通过Recycleview显示,在Adapter中添加点击事件,将点击item的position和状态值传递给调用的Activity;后台Service在下载线程的个个状态通过广播发送给主线程并更新UI。
下面直接上代码。
数据库操作类
DownloadContract:
public class DownloadContract {
// 为了防止有人意外地实例化合同类,使构造函数私有。
private DownloadContract() {
}
/* 内部类定义表的内容 */
public static class DownloadEntry implements BaseColumns {
public static final String TABLE_NAME = "downloadentry";
public static final String COLUMN_NAME_TID = "tid";
public static final String COLUMN_NAME_JINDU = "jindu";
public static final String COLUMN_NAME_YIXIAZAI = "yixiazai";
public static final String COLUMN_NAME_PATH = "path";
public static final String COLUMN_NAME_ZHUANGTAI = "zhuangtai";
public static final String COLUMN_NAME_URL = "url";
}
}
SQLTool:
public class SQLTool {
private static final String TEXT_TYPE = " TEXT";
private static final String INTEGER_TYPE = " INTEGER";
private static final String COMMA_SEP = ",";
public static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + DownloadContract.DownloadEntry.TABLE_NAME + " (" +
DownloadContract.DownloadEntry._ID + " INTEGER PRIMARY KEY," +
DownloadContract.DownloadEntry.COLUMN_NAME_TID + INTEGER_TYPE + COMMA_SEP +
DownloadContract.DownloadEntry.COLUMN_NAME_JINDU + INTEGER_TYPE + COMMA_SEP +
DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI + INTEGER_TYPE + COMMA_SEP +
DownloadContract.DownloadEntry.COLUMN_NAME_PATH + TEXT_TYPE + COMMA_SEP +
DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI + INTEGER_TYPE + COMMA_SEP +
DownloadContract.DownloadEntry.COLUMN_NAME_URL + TEXT_TYPE + " )";
public static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + DownloadContract.DownloadEntry.TABLE_NAME;
}
DownloadDbHelper:
public class DownloadDbHelper extends SQLiteOpenHelper {
// 如果更改数据库模式,则必须增加数据库版本。
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "dl.db";
public DownloadDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(SQL_CREATE_ENTRIES);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// 这个数据库只是一个用于在线数据的缓存,因此其升级策略是简单地丢弃数据并重新开始
sqLiteDatabase.execSQL(SQL_DELETE_ENTRIES);
onCreate(sqLiteDatabase);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db, oldVersion, newVersion);
}
}
DAOHelper:
public class DAOHelper {
private DownloadDbHelper downloadDbHelper;
public DAOHelper(Context context) {
downloadDbHelper = new DownloadDbHelper(context);
}
public long add(Download download) {
// 以写入模式获取数据存储库
SQLiteDatabase db = downloadDbHelper.getWritableDatabase();
//创建一个新的值映射,其中列名称是键
ContentValues values = new ContentValues();
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_TID, download.gettId());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_JINDU, download.getJindu());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI, download.getYixiazai());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_PATH, download.getPath());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI, download.getZhuangtai());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_URL, download.getUrl());
// 插入新行,返回新行的主键值,-1表示插入失败
long newRowId = db.insert(DownloadContract.DownloadEntry.TABLE_NAME, null, values);
return newRowId;
}
public void delete(int tID) {
SQLiteDatabase db = downloadDbHelper.getWritableDatabase();
// 定义查询的“where”部分。
String selection = DownloadContract.DownloadEntry.COLUMN_NAME_TID + " LIKE ?";
// 在占位符顺序中指定参数。
String[] selectionArgs = {tID + ""};
// 发出SQL语句。
db.delete(DownloadContract.DownloadEntry.TABLE_NAME, selection, selectionArgs);
}
public int update(Download download) {
SQLiteDatabase db = downloadDbHelper.getReadableDatabase();
ContentValues values = new ContentValues();
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_JINDU, download.getJindu());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI, download.getYixiazai());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_PATH, download.getPath());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI, download.getZhuangtai());
values.put(DownloadContract.DownloadEntry.COLUMN_NAME_URL, download.getUrl());
// 要更新的行
String selection = DownloadContract.DownloadEntry.COLUMN_NAME_TID + " LIKE ?";
String[] selectionArgs = {download.gettId() + ""};
// 得到受影响的行数
int count = db.update(
DownloadContract.DownloadEntry.TABLE_NAME,
values,
selection,
selectionArgs);
return count;
}
public boolean include(int tID) {
SQLiteDatabase db = downloadDbHelper.getReadableDatabase();
String[] projection = {
DownloadContract.DownloadEntry.COLUMN_NAME_TID,
DownloadContract.DownloadEntry.COLUMN_NAME_JINDU,
DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI,
DownloadContract.DownloadEntry.COLUMN_NAME_PATH,
DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI,
DownloadContract.DownloadEntry.COLUMN_NAME_URL
};
String selection = DownloadContract.DownloadEntry.COLUMN_NAME_TID + " = ?";
String[] selectionArgs = {tID + ""};
String sortOrder =
DownloadContract.DownloadEntry.COLUMN_NAME_TID + " DESC";
Cursor c = db.query(
DownloadContract.DownloadEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
if (c.moveToFirst()) {
return true;
} else {
return false;
}
}
public Download select(int tID) {
Download download = new Download();
SQLiteDatabase db = downloadDbHelper.getReadableDatabase();
String[] projection = {
DownloadContract.DownloadEntry.COLUMN_NAME_TID,
DownloadContract.DownloadEntry.COLUMN_NAME_JINDU,
DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI,
DownloadContract.DownloadEntry.COLUMN_NAME_PATH,
DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI,
DownloadContract.DownloadEntry.COLUMN_NAME_URL
};
String selection = DownloadContract.DownloadEntry.COLUMN_NAME_TID + " = ?";
String[] selectionArgs = {tID + ""};
String sortOrder =
DownloadContract.DownloadEntry.COLUMN_NAME_TID + " DESC";
Cursor c = db.query(
DownloadContract.DownloadEntry.TABLE_NAME,
projection,
selection,
selectionArgs,
null,
null,
sortOrder
);
if (c.moveToFirst()) {
download.settId(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_TID)));
download.setJindu(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_JINDU)));
download.setYixiazai(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI)));
download.setPath(c.getString(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_PATH)));
download.setZhuangtai(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI)));
download.setUrl(c.getString(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_URL)));
return download;
} else {
return null;
}
}
public List<Download> selectAll() {
List<Download> dataList = new ArrayList<Download>();
SQLiteDatabase db = downloadDbHelper.getReadableDatabase();
Cursor c = db.query(
DownloadContract.DownloadEntry.TABLE_NAME,
null,
null,
null,
null,
null,
null
);
while (c.moveToNext()) {
Download download = new Download();
download.settId(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_TID)));
download.setJindu(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_JINDU)));
download.setYixiazai(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_YIXIAZAI)));
download.setPath(c.getString(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_PATH)));
download.setZhuangtai(c.getInt(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_ZHUANGTAI)));
download.setUrl(c.getString(c.getColumnIndexOrThrow(DownloadContract.DownloadEntry.COLUMN_NAME_URL)));
dataList.add(download);
}
return dataList;
}
}
布局
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.jqk.backgrounddownload.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView>
</LinearLayout>
item_dl.xml:
<?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="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:max="100" />
<TextView
android:id="@+id/jindu"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.1" />
<Button
android:id="@+id/start"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:text="" />
</LinearLayout>
remoteview.xml:
<?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="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.9" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.1" />
</LinearLayout>
实体类
Download:
public class Download {
private int tId;
private int jindu;
private int yixiazai;
private String path;
private int zhuangtai;
private String url;
public int gettId() {
return tId;
}
public void settId(int tId) {
this.tId = tId;
}
public int getJindu() {
return jindu;
}
public void setJindu(int jindu) {
this.jindu = jindu;
}
public int getYixiazai() {
return yixiazai;
}
public void setYixiazai(int yixiazai) {
this.yixiazai = yixiazai;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public int getZhuangtai() {
return zhuangtai;
}
public void setZhuangtai(int zhuangtai) {
this.zhuangtai = zhuangtai;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
@Override
public String toString() {
return "Download{" +
"tId=" + tId +
", jindu=" + jindu +
", yixiazai=" + yixiazai +
", path='" + path + '\'' +
", zhuangtai=" + zhuangtai +
", url='" + url + '\'' +
'}';
}
}
Jindu:
public class Jindu {
// 进度状态:0为未开始,1为开始
private int type;
private int jindu;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getJindu() {
return jindu;
}
public void setJindu(int jindu) {
this.jindu = jindu;
}
@Override
public String toString() {
return "Jindu{" +
"type=" + type +
", jindu=" + jindu +
'}';
}
}
工具类
AppConstant:
public class AppConstant {
public static final int START = 1;
public static final int PAUSE = 2;
public static final int WAIT = 3;
public static final int CONNECTING = 4;
public static final int FINISH = 5;
public static final int GOON = 6;
}
FileUtil:
public class FileUtil {
public static File getStorageDir(Context context, String albumName) {
File file = new File(context.getExternalFilesDir(
Environment.DIRECTORY_DOWNLOADS), albumName);
if (file.mkdirs() || file.isDirectory()) {
Log.d("dl", "文件夹已存在");
} else {
Log.d("dl", "文件夹创建失败");
}
return file;
}
}
Activity
MainActivity:
public class MainActivity extends AppCompatActivity implements MyAdapter.OnClickTypeListener {
private RecyclerView recyclerView;
private File file;
private List<Download> downloads;
private DAOHelper daoHelper;
private DownloadService mService;
private boolean mBound = false;
private LinearLayoutManager linearLayoutManager;
private MyAdapter myAdapter;
// 定时任务,更新下载进度
private Timer timer;
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
DownloadService.DLBinder binder = (DownloadService.DLBinder) service;
mService = binder.getService();
timer = new Timer();
// 开启刷新UI的任务
timer.schedule(new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1000;
handler.sendMessage(message);
}
}, 0, 700);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1000:
shuaxin(downloads, mService.getJindu());
break;
}
}
};
private BroadcastReceiver typeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case "type":
int position = intent.getIntExtra("position", 0);
int type = intent.getIntExtra("type", 0);
downloads.get(position).setZhuangtai(type);
myAdapter.notifyDataSetChanged();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
daoHelper = new DAOHelper(this);
initData();
adaptationData();
// 启动服务
Intent intent = new Intent(this, DownloadService.class);
startService(intent);
// 绑定服务
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("type");
registerReceiver(typeReceiver, intentFilter);
}
public void initView() {
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
}
/**
* 初始化数据
*/
public void initData() {
file = FileUtil.getStorageDir(getApplicationContext(), "apk");
Log.d("dl", "path = " + file.getAbsolutePath());
if (!daoHelper.include(1)) {
Download download = new Download();
download.settId(1);
download.setJindu(0);
download.setYixiazai(0);
download.setPath(file.getAbsolutePath() + "/111.apk");
download.setZhuangtai(1);
download.setUrl("http://msoftdl.360.cn/mobilesafe/shouji360/360safe/500192/360MobileSafe.apk");
long i = daoHelper.add(download);
if (i != -1) {
Log.d("dl", "插入成功1");
} else {
Log.d("dl", "插入失败1");
}
} else {
Log.d("dl", "数据已存在1");
}
if (!daoHelper.include(2)) {
Download download = new Download();
download.settId(2);
download.setJindu(0);
download.setYixiazai(0);
download.setPath(file.getAbsolutePath() + "/222.apk");
download.setZhuangtai(1);
download.setUrl("http://msoftdl.360.cn/mobilesafe/shouji360/360safe/500192/360MobileSafe.apk");
long i = daoHelper.add(download);
if (i != -1) {
Log.d("dl", "插入成功2");
} else {
Log.d("dl", "插入失败2");
}
} else {
Log.d("dl", "数据已存在2");
}
if (!daoHelper.include(3)) {
Download download = new Download();
download.settId(3);
download.setJindu(0);
download.setYixiazai(0);
download.setPath(file.getAbsolutePath() + "/333.apk");
download.setZhuangtai(1);
download.setUrl("http://msoftdl.360.cn/mobilesafe/shouji360/360safe/500192/360MobileSafe.apk");
long i = daoHelper.add(download);
if (i != -1) {
Log.d("dl", "插入成功3");
} else {
Log.d("dl", "插入失败3");
}
} else {
Log.d("dl", "数据已存在3");
}
if (!daoHelper.include(4)) {
Download download = new Download();
download.settId(4);
download.setJindu(0);
download.setYixiazai(0);
download.setPath(file.getAbsolutePath() + "/444.apk");
download.setZhuangtai(1);
download.setUrl("http://msoftdl.360.cn/mobilesafe/shouji360/360safe/500192/360MobileSafe.apk");
long i = daoHelper.add(download);
if (i != -1) {
Log.d("dl", "插入成功4");
} else {
Log.d("dl", "插入失败4");
}
} else {
Log.d("dl", "数据已存在4");
}
}
/**
* 适配数据
*/
public void adaptationData() {
downloads = daoHelper.selectAll();
for (Download download : downloads) {
Log.d("dl", "适配的数据:" + "线程ID = " + download.gettId() + ",type = " + download.getZhuangtai() + ",进度 = " + download.getJindu());
}
linearLayoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(linearLayoutManager);
myAdapter = new MyAdapter(this, downloads, this);
recyclerView.setAdapter(myAdapter);
}
/**
* 刷新进度条
*
* @param downloads
* @param jindus
*/
public void shuaxin(List<Download> downloads, List<Jindu> jindus) {
for (int i = 0; i < downloads.size(); i++) {
downloads.get(i).setJindu(jindus.get(i).getJindu());
}
myAdapter.notifyDataSetChanged();
}
@Override
public void onClickType(int position, int type) {
Log.d("dl", "点击position" + position + ", type = " + type);
switch (type) {
case AppConstant.START: // 开始
mService.startDL(position);
break;
case AppConstant.PAUSE: // 暂停
mService.pauseDL(position);
break;
case AppConstant.WAIT: // 等待
break;
case AppConstant.CONNECTING: // 连接中
break;
case AppConstant.FINISH: // 完成
break;
case AppConstant.GOON:
mService.startDL(position);
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mConnection);
// Intent intent = new Intent(this, DownloadService.class);
// stopService(intent);
unregisterReceiver(typeReceiver);
timer.cancel();
}
}
Service
DownloadService:
public class DownloadService extends Service {
private File dlFile, file;
private Timer timer;
// 数据库帮助类
private DAOHelper daoHelper;
// 线程池,大小为2
private ExecutorService fixedThreadPool;
// 线程集合 大小为2
private List<DownloadThread> threads;
// 进度集合
private List<Jindu> jindus;
// 下载实例集合
private List<Download> downloads;
// 等待集合
private List<Integer> waits;
private Intent typeIntent;
// IBinder对象
private final IBinder mBinder = new DLBinder();
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1000:
int jindu = getPingJunJindu(jindus);
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("自定义布局");
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.remoteview);
remoteViews.setProgressBar(R.id.progressBar, 100, jindu, false);
remoteViews.setTextViewText(R.id.textView, jindu + "%");
builder.setContent(remoteViews);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
startForeground(1, builder.build());
break;
}
}
};
public class DLBinder extends Binder {
public DownloadService getService() {
return DownloadService.this;
}
}
@Override
public void onCreate() {
daoHelper = new DAOHelper(this);
file = FileUtil.getStorageDir(getApplicationContext(), "apk");
Log.d("dl", "path = " + file.getAbsolutePath());
fixedThreadPool = Executors.newFixedThreadPool(2);
jindus = new ArrayList<Jindu>();
threads = new ArrayList<DownloadThread>();
downloads = daoHelper.selectAll();
for (int i = 0; i < downloads.size(); i++) {
Jindu jindu = new Jindu();
if (downloads.get(i).getZhuangtai() != 1) { // 根据存储的状态值设置进度的状态
// 已经开始
jindu.setType(1);
} else {
// 还未开始
jindu.setType(0);
}
jindu.setJindu(downloads.get(i).getJindu());
jindus.add(jindu);
}
for (int i = 0; i < 2; i++) {
DownloadThread downloadThread = new DownloadThread();
threads.add(downloadThread);
}
waits = new ArrayList<Integer>();
typeIntent = new Intent();
typeIntent.setAction("type");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext());
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentTitle("自定义点击事件");
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.remoteview);
remoteViews.setProgressBar(R.id.progressBar, 100, 0, false);
remoteViews.setTextViewText(R.id.textView, 0 + "%");
builder.setContent(remoteViews);
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
startForeground(1, builder.build());
start();
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
}
/**
* 开始下载
*/
public void startDL(int position) {
for (int i = 0; i < 2; i++) { // 遍历线程集合,判断线程ID,如果线程ID为-1则通过线程池运行线程
if (threads.get(i).gettID() == -1) {
DownloadThread downloadThread = threads.get(i);
downloadThread.settID(position + 1);
Log.d("dl", "线程" + i + "启动");
downloadThread.setDlUrl(downloads.get(position).getUrl());
fixedThreadPool.execute(downloadThread);
return;
}
}
// 如果两个线程都被使用,则加入等待集合
if (threads.get(0).gettID() != -1 && threads.get(1).gettID() != -1) {
Log.d("dl", "等待增加" + position);
waits.add(position);
saveType(position, AppConstant.WAIT);
}
}
/**
* 暂停下载
* @param position
*/
public void pauseDL(int position) {
for (int i = 0; i < 2; i++) {
if (threads.get(i).gettID() != -1 && threads.get(i).gettID() == position + 1) {
Log.d("dl", "线程" + i + "暂停");
threads.get(i).pause();
break;
}
}
}
/**
* 开始显示通知栏的定时任务
*/
public void start() {
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
Message msg = new Message();
msg.what = 1000;
handler.sendMessage(msg);
}
}, 0, 700);
}
/**
* 停止显示通知栏的定时任务
*/
public void stop() {
timer.cancel();
}
public void saveType(int position, int type) {
typeIntent.putExtra("position", position);
typeIntent.putExtra("type", type);
sendBroadcast(typeIntent);
Download download = downloads.get(position);
download.setZhuangtai(type);
download.setJindu(jindus.get(position).getJindu());
// daoHelper.update(download);
if (daoHelper.update(download) == 1) {
Log.d("dl", "数据保存成功:" + "线程ID = " + download.gettId() + ",type = " + download.getZhuangtai() + ",进度 = " + download.getJindu());
}
}
/**
* 获取平均进度,显示在通知栏中
*
* @param jindus
* @return
*/
public int getPingJunJindu(List<Jindu> jindus) {
int jindu = 0;
int i = 0;
for (Jindu jd : jindus) {
if (jd.getType() == 1) {
jindu += jd.getJindu();
i++;
}
}
if (i == 0) {
return jindu;
} else {
return jindu / i;
}
}
/**
* 返回进度
* @return
*/
public List<Jindu> getJindu() {
return jindus;
}
public class DownloadThread implements Runnable {
private boolean pause = false;
private int tID = -1;
private String dlUrl = "";
public int gettID() {
return tID;
}
public void settID(int tID) {
this.tID = tID;
}
public String getDlUrl() {
return dlUrl;
}
public void setDlUrl(String dlUrl) {
this.dlUrl = dlUrl;
}
@Override
public void run() {
try {
//创建URL对象
Log.d("dl", "线程ID = " + tID);
URL url = new URL(dlUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
//已经下载的字节数
long alreadySize = 0;
//将文件写到指定目录中
Download download = daoHelper.select(tID);
File file = new File(download.getPath());
if (file.exists()) {
//如果文件存在,就获取当前文件的大小
alreadySize = file.length();
}
conn.addRequestProperty("range", "bytes=" + alreadySize + "-");
saveType(tID - 1, AppConstant.CONNECTING); // 正在连接
conn.connect();
// 获得返回结果
int code = conn.getResponseCode();
// 响应成功返回206
if (code == 206) {
jindus.get(tID - 1).setType(1);
saveType(tID - 1, AppConstant.PAUSE); // 暂停
// 获取未下载的文件的大小
long unfinishedSize = conn.getContentLength();
// 文件的大小
long size = alreadySize + unfinishedSize;
Log.d("dl", "size = " + size);
// 获取输入流
InputStream in = conn.getInputStream();
// 获取输出对象,在原文件后追加
OutputStream out = new BufferedOutputStream(new FileOutputStream(file, true));
// 开始下载
byte[] buff = new byte[2048];
int len;
StringBuilder sb = new StringBuilder();
while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len);
// 累加已下载的大小
alreadySize += len;
// 更新进度
jindus.get(tID - 1).setJindu((int) (alreadySize * 1.0 / size * 100));
synchronized (this) {
if (pause) {
saveType(tID - 1, AppConstant.GOON); // 继续
Log.d("dl", "线程ID" + tID + "停止");
break; // 暂停后跳出while循环继续执行后面的代码
}
}
}
out.close();
conn.disconnect();
if (alreadySize == size) {
saveType(tID - 1, AppConstant.FINISH); // 完成
}
pause = false; // 重置pause常量
tID = -1; // 重置线程编号
if (waits.size() != 0) {
pause = false; // 重置pause常量
tID = -1; // 重置线程编号
Log.d("dl", "等待执行" + waits.get(0));
startDL(waits.get(0)); // 执行等待的任务
waits.remove(0);
}
} else {
Toast.makeText(DownloadService.this, "下载失败", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void pause() {
pause = true;
}
}
}
最后别忘了添加权限,声明Service:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<service android:name=".DownloadSerivce"></service>