MainActivity |
package com.example.downloador;
import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
public static DownloadServiceBinder binder;
private static final int REQUEST_NEW_CREATE=0;
public static DownloadTaskAdapter downloadTaskAdapter;
private static RecyclerView downloadTaskRecyclerView;
private static LinearLayoutManager linearLayoutManager;
public static ArrayList<DownloadTask> downloadTaskArrayList;
private static int downloadTaskRecyclerViewLayout=R.layout.download_task_recycler_view_layout;
public static DownloadCallbackInterface serviceListener;
//下载任务回调接口匿名类
public DownloadCallbackInterface callback=new DownloadCallbackInterface() {
//任务成功回调
@Override
public void onSuccess(final int itemId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
DownloadTaskViewHolder viewHolder=((DownloadTaskViewHolder)downloadTaskRecyclerView.findViewHolderForAdapterPosition(itemId));
if(viewHolder!=null) {
viewHolder.downloadTaskProgressBar.setProgress(100);
viewHolder.startOrPauseDownloadTaskButton.setText("OK");
viewHolder.startOrPauseDownloadTaskButton.setOnClickListener(null);
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT).show();
}
}
});
}
//任务失败回调
@Override
public void onFailed(final int itemId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
DownloadTaskViewHolder viewHolder=((DownloadTaskViewHolder)downloadTaskRecyclerView.findViewHolderForAdapterPosition(itemId));
if(viewHolder!=null) {
viewHolder.startOrPauseDownloadTaskButton.setText(">>");
viewHolder.downloadTaskProgressBar.setProgress(0);
Toast.makeText(MainActivity.this, "任务失败", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(MainActivity.this, "任务失败", Toast.LENGTH_SHORT).show();
}
}
});
}
//任务暂停回调
@Override
public void onPaused(int itemId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"暂停下载",Toast.LENGTH_SHORT).show();
}
});
}
//任务取消回调
@Override
public void onCanceled(final int itemId) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this,"取消下载",Toast.LENGTH_SHORT).show();
}
});
}
//进度更新回调
@Override
public void onProgressChanged(final int itemId, final Integer progressValue) {
if(progressValue>0){
runOnUiThread(new Runnable() {
@Override
public void run() {
DownloadTaskViewHolder viewHolder=((DownloadTaskViewHolder) downloadTaskRecyclerView.findViewHolderForAdapterPosition(itemId));
if(viewHolder!=null){
viewHolder.downloadTaskProgressBar.setProgress(progressValue);
}
}
});
}
}
};
//建立下载服务连接器
private ServiceConnection serviceConnection=new ServiceConnection() {
//服务连接
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder=(DownloadServiceBinder) service;
}
//服务断开
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
//创建新任务活动回调
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (requestCode){
case REQUEST_NEW_CREATE:
if(resultCode==RESULT_OK){
final String downloadUrl=data.getStringExtra("downloadUrl");
if(downloadUrl!=null){
if(!binder.checkIsExist(downloadUrl)) {
binder.startDownload(downloadUrl);
}else{
Toast.makeText(this,"任务已存在",Toast.LENGTH_SHORT).show();
}
}
}
break;
}
}
//请求相关权限
protected void requestPermissions(){
if(ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!=PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
}
//创建主活动折叠菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_activity_menu_resource,menu);
return true;
}
//创建主活动折叠菜单项点击事件处理
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.exitMenuItem:
Toast.makeText(this,"退出",Toast.LENGTH_LONG).show();
this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
break;
}
return true;
}
//创建主活动
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity_layout);
serviceListener=callback;
requestPermissions();
Button openCreateNewTaskDialogButton=findViewById(R.id.openCreateNewTaskDialogButton);
Button startAllDownloadTaskButton=findViewById(R.id.startAllDownloadTaskButton);
Button pauseAllDownloadTaskButton=findViewById(R.id.pauseAllDownloadTaskButton);
Button deleteAllDownloadTaskButton=findViewById(R.id.deleteAllDownloadTaskButton);
startAllDownloadTaskButton.setOnClickListener(this);
pauseAllDownloadTaskButton.setOnClickListener(this);
deleteAllDownloadTaskButton.setOnClickListener(this);
openCreateNewTaskDialogButton.setOnClickListener(this);
Intent startServiceIntent=new Intent(this,DownloadService.class);
bindService(startServiceIntent,serviceConnection,BIND_AUTO_CREATE);
downloadTaskArrayList=new ArrayList<>();
downloadTaskRecyclerView=findViewById(R.id.downloadTaskRecyclerView);
linearLayoutManager=new LinearLayoutManager(this);
downloadTaskAdapter=new DownloadTaskAdapter(downloadTaskArrayList,downloadTaskRecyclerViewLayout);
downloadTaskRecyclerView.setLayoutManager(linearLayoutManager);
downloadTaskRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
downloadTaskRecyclerView.setAdapter(downloadTaskAdapter);
}
//主活动摧毁
@Override
protected void onDestroy() {
unbindService(serviceConnection);
super.onDestroy();
}
//主活动置顶按钮点击事件处理
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.openCreateNewTaskDialogButton:
Intent openCreateNewTaskDialogIntent=new Intent(this,CreateNewDownloadTaskActivity.class);
startActivityForResult(openCreateNewTaskDialogIntent,REQUEST_NEW_CREATE);
break;
case R.id.startAllDownloadTaskButton:
for(int index=0;index<MainActivity.downloadTaskAdapter.getItemCount();index++){
Button startOrPauseDownloadTaskButton=((DownloadTaskViewHolder) MainActivity.downloadTaskRecyclerView.findViewHolderForAdapterPosition(index)).startOrPauseDownloadTaskButton;
if(">>".equals(startOrPauseDownloadTaskButton.getText().toString())){
MainActivity.downloadTaskAdapter.onClick(startOrPauseDownloadTaskButton);
}
}
break;
case R.id.pauseAllDownloadTaskButton:
for(int index=0;index<MainActivity.downloadTaskAdapter.getItemCount();index++){
Button startOrPauseDownloadTaskButton=((DownloadTaskViewHolder) MainActivity.downloadTaskRecyclerView.findViewHolderForAdapterPosition(index)).startOrPauseDownloadTaskButton;
if("||".equals(startOrPauseDownloadTaskButton.getText().toString())){
MainActivity.downloadTaskAdapter.onClick(startOrPauseDownloadTaskButton);
}
}
break;
case R.id.deleteAllDownloadTaskButton:
for(int index=MainActivity.downloadTaskAdapter.getItemCount()-1;index>=0;index--){
Button cancelDownloadTaskButton=((DownloadTaskViewHolder) MainActivity.downloadTaskRecyclerView.findViewHolderForAdapterPosition(index)).cancelDownloadTaskButton;
MainActivity.downloadTaskAdapter.onClick(cancelDownloadTaskButton);
}
break;
}
}
}
|
DownloadTaskAdapter.java |
package com.example.downloador;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.util.ArrayList;
//下载任务适配器类
public class DownloadTaskAdapter extends RecyclerView.Adapter<DownloadTaskViewHolder> implements View.OnClickListener{
private static ArrayList<DownloadTask> tasksList;
private int layoutResourceID;
//下载任务适配器构造初始化
public DownloadTaskAdapter(ArrayList<DownloadTask> tasksList, int layoutResourceID) {
DownloadTaskAdapter.tasksList=tasksList;
this.layoutResourceID=layoutResourceID;
}
//适配器内按钮点击事件处理
@Override
public void onClick(View button) {
String textOfButton=((Button)button).getText().toString();
DownloadTask tagTask=((DownloadTask)button.getTag());
switch (button.getId()){
case R.id.startOrPauseDownloadTaskButton:
if("||".equals(textOfButton)){
MainActivity.binder.pauseDownload(tagTask);
((Button) button).setText(">>");
}else if(">>".equals(textOfButton)){
MainActivity.binder.resumeDownload(tagTask);
((Button) button).setText("||");
}
break;
case R.id.cancelDownloadTaskButton:
MainActivity.binder.pauseDownload(tagTask);
MainActivity.binder.cancelDownload(tagTask);
break;
}
}
//适配器子项被回收时回调
@Override
public void onViewRecycled(@NonNull DownloadTaskViewHolder holder) {
((TextView)((AppCompatActivity)holder.itemView.getContext()).findViewById(R.id.downloadTaskCount))
.setText("下载任务总数:"+String.valueOf(this.getItemCount()));
}
//适配器子项滚至窗口内显示时回调
@Override
public void onViewAttachedToWindow(@NonNull DownloadTaskViewHolder holder) {
DownloadTask attachedTask=(DownloadTask)holder.startOrPauseDownloadTaskButton.getTag();
attachedTask.setDetached(false);
holder.downloadTaskProgressBar.setProgress(attachedTask.getDownloadProgress());
if(attachedTask.getDownloadProgress()==100){
holder.startOrPauseDownloadTaskButton.setText("OK");
holder.startOrPauseDownloadTaskButton.setOnClickListener(null);
}
}
//适配器子项滚至窗口外隐藏时回调
@Override
public void onViewDetachedFromWindow(@NonNull DownloadTaskViewHolder holder) {
DownloadTask detachedTask=(DownloadTask)holder.startOrPauseDownloadTaskButton.getTag();
detachedTask.setDetached(true);
}
//适配器子项被绑定到适配器时回调
@Override
public void onBindViewHolder(@NonNull DownloadTaskViewHolder viewHolder, int position) {
((TextView)((AppCompatActivity)viewHolder.itemView.getContext()).findViewById(R.id.downloadTaskCount))
.setText("下载任务总数:"+String.valueOf(this.getItemCount()));
final DownloadTask onBindTask = MainActivity.downloadTaskArrayList.get(position);
if (!onBindTask.getIsStarted()) {
viewHolder.downloadTaskUrl.setText(onBindTask.getDownloadUrl());
if (onBindTask.getPaused()) {
viewHolder.startOrPauseDownloadTaskButton.setText(">>");
} else {
viewHolder.startOrPauseDownloadTaskButton.setText("||");
viewHolder.startOrPauseDownloadTaskButton.setTag(onBindTask);
viewHolder.cancelDownloadTaskButton.setTag(onBindTask);
new Thread(new Runnable() {
@Override
public void run() {
onBindTask.startExecute();
}
}).start();
}
}
}
//适配器子项被填充创建时回调
@NonNull
@Override
public DownloadTaskViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
View view=LayoutInflater.from(viewGroup.getContext()).inflate(this.layoutResourceID,viewGroup,false);
DownloadTaskViewHolder viewHolder=new DownloadTaskViewHolder(view);
viewHolder.startOrPauseDownloadTaskButton.setOnClickListener(this);
viewHolder.cancelDownloadTaskButton.setOnClickListener(this);
return viewHolder;
}
//获取适配器子项总数量
@Override
public int getItemCount() {
return tasksList.size();
}
}
//ViewHolder持有类
class DownloadTaskViewHolder extends RecyclerView.ViewHolder{
protected Button startOrPauseDownloadTaskButton;
protected TextView downloadTaskUrl;
protected ProgressBar downloadTaskProgressBar;
protected Button cancelDownloadTaskButton;
//ViewHolder构造初始化
public DownloadTaskViewHolder(@NonNull View itemView) {
super(itemView);
this.startOrPauseDownloadTaskButton=itemView.findViewById(R.id.startOrPauseDownloadTaskButton);
this.downloadTaskUrl=itemView.findViewById(R.id.downloadTaskUrl);
this.downloadTaskProgressBar=itemView.findViewById(R.id.downloadTaskProgressBar);
this.cancelDownloadTaskButton=itemView.findViewById(R.id.cancelDownloadTaskButton);
}
}
|
DownloadTask |
package com.example.downloador;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
//下载任务类
public class DownloadTask{
private static final int TYPE_SUCCESS=0;
private static final int TYPE_FAILED=1;
private static final int TYPE_PAUSED=2;
private static final int TYPE_CANCELED=3;
private String downloadUrl;
private int downloadProgress=0;
private int downloadItemID;
private boolean isPaused=false;
private boolean isCanceled=false;
private boolean isStarted=false;
private boolean isDetached=false;
private File storageFile;
private DownloadCallbackInterface callback;
private int lastProgress=0;
//下载任务构造初始化
public DownloadTask(DownloadCallbackInterface callback) {
this.callback=callback;
}
//设置是否剥离窗口
public void setDetached(boolean isDetached){
this.isDetached=isDetached;
}
//设置是否启动了任务
public void setIsStarted(boolean isStarted){
this.isStarted=isStarted;
}
//获取是否启动了任务
public boolean getIsStarted(){
return this.isStarted;
}
//设置下载进度
public void setDownloadProgress(int downloadProgress){
this.downloadProgress=downloadProgress;
}
//获取下载进度
public int getDownloadProgress(){
return this.downloadProgress;
}
//设置下载任务在适配器中的坐标
public void setDownloadItemID(int downloadItemID){
this.downloadItemID=downloadItemID;
}
//获取下载任务在适配器中的坐标
public int getDownloadItemID(){
return this.downloadItemID;
}
//获取下载任务的URL
public String getDownloadUrl(){
return this.downloadUrl;
}
//设置下载任务的URL
public void setDownloadUrl(String url){
this.downloadUrl=url;
}
//设置暂停下载任务
public void setPaused(){
this.isPaused=true;
}
//获取下载任务是否暂停
public boolean getPaused(){
return this.isPaused;
}
//设置取消下载任务
public void setCanceled(){
this.isCanceled=true;
if(this.storageFile!=null&&this.storageFile.exists()){
this.storageFile.delete();
}
}
//获取已下载的文件长度
private long getDownloadedLength(File storageFile){
return storageFile.length();
}
//获取下载任务的本地存储文件
private File getStorageFile(String downloadUrl){
String fileName=downloadUrl.substring(downloadUrl.lastIndexOf("/"));
String storagePath=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
String storageFilePath=storagePath+fileName;
File returnFile=new File(storageFilePath);
if(returnFile!=null){
return returnFile;
}else{
try {
returnFile.createNewFile();
}catch (IOException e){
Log.e("Error", "ItemID:"+String.valueOf(downloadItemID)+" getStorageFile:无法建立存储文件:"+storageFilePath);
}
return returnFile;
}
}
//获取下载任务目标文件完整大小
private long getDownloadFileContentLength(String downloadUrl){
long returnLength=0;
try {
OkHttpClient httpClient = new OkHttpClient();
Request request = new Request.Builder().url(downloadUrl).build();
Response response = httpClient.newCall(request).execute();
if(response.isSuccessful()){
returnLength=response.body().contentLength();
}
}catch (IOException e){
Log.e("Error","ItemID:"+String.valueOf(downloadItemID)+" getDownloadFileContentLength:无法获取回应数据");
}catch (NullPointerException e) {
Log.e("Error", "ItemID:"+String.valueOf(downloadItemID)+" getDownloadFileContentLength:获取数据长度为空");
}
return returnLength;
}
//执行下载任务的入口
public void startExecute(){
setIsStarted(true);
onReturnToCallback(download());
}
//执行下载处理
private int download(){
RandomAccessFile fileWrite=null;
this.storageFile=getStorageFile(this.downloadUrl);
long downloadedLength=getDownloadedLength(this.storageFile);
long downloadFileContentLength=getDownloadFileContentLength(this.downloadUrl);
byte[] readBytes=new byte[1024];
long readTotal=0;
int readBytesCount;
Response response;
InputStream downloadInputStream=null;
OkHttpClient httpClient=new OkHttpClient();
if(downloadFileContentLength==0){
return TYPE_FAILED;
}
if(downloadFileContentLength==downloadedLength){
return TYPE_SUCCESS;
}
Request request=new Request.Builder().url(this.downloadUrl)
.addHeader("RANGE","bytes="+downloadedLength+"-")
.build();
try {
response = httpClient.newCall(request).execute();
}catch (IOException e){
Log.e("Error","ItemID:"+String.valueOf(downloadItemID)+" doInBackground:无法获取回应数据");
return TYPE_FAILED;
}
if(response!=null&&response.isSuccessful()){
try {
downloadInputStream=response.body().byteStream();
try {
if(this.storageFile!=null) {
fileWrite = new RandomAccessFile(this.storageFile, "rw");
fileWrite.seek(downloadedLength);
}else{
return TYPE_FAILED;
}
}catch (FileNotFoundException e){
Log.e("Error","ItemID:"+String.valueOf(downloadItemID)+" doInBackground:未能创建随机读写文件");
}catch (IOException e){
Log.e("Error","ItemID:"+String.valueOf(downloadItemID)+" doInBackground:未能移动文件读写索引");
}
while ((readBytesCount = (downloadInputStream.read(readBytes))) != -1) {
if(isPaused){
return TYPE_PAUSED;
}else if(isCanceled){
return TYPE_CANCELED;
}
fileWrite.write(readBytes,0,readBytesCount);
readTotal+=readBytesCount;
this.downloadProgress=(int)((readTotal+downloadedLength)*100/downloadFileContentLength);
if(this.lastProgress<this.downloadProgress&&!this.isDetached){
this.lastProgress=this.downloadProgress;
callback.onProgressChanged(this.getDownloadItemID(), this.lastProgress);
}else if(this.lastProgress<this.downloadProgress&&this.isDetached){
this.lastProgress=this.downloadProgress;
}
}
}catch (NullPointerException e){
Log.e("Error", "ItemID:"+String.valueOf(downloadItemID)+" doInBackground:无法获取二进制输入流" );
}catch (IOException e){
Log.e("Error", "ItemID:"+String.valueOf(downloadItemID)+" doInBackground:数据流读取失败" );
}finally {
try{
downloadInputStream.close();
response.close();
fileWrite.close();
}catch (IOException e){
Log.e("Error","ItemID:"+String.valueOf(downloadItemID)+" doInBackground:资源关闭异常");
}
}
return TYPE_SUCCESS;
}
return TYPE_FAILED;
}
//下载处理完毕时回调
protected void onReturnToCallback(int resultType) {
switch (resultType){
case TYPE_SUCCESS:
callback.onSuccess(this.downloadItemID);
break;
case TYPE_FAILED:
callback.onFailed(this.downloadItemID);
break;
case TYPE_PAUSED:
callback.onPaused(this.downloadItemID);
break;
case TYPE_CANCELED:
callback.onCanceled(this.downloadItemID);
break;
}
}
}
|
DownloadService.java |
package com.example.downloador;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
//后台下载服务
public class DownloadService extends Service {
private DownloadServiceBinder downloadServiceBinder=new DownloadServiceBinder();
//返回服务的Bind
@Override
public IBinder onBind(Intent intent) {
return this.downloadServiceBinder;
}
}
//后台服务的Bind类
class DownloadServiceBinder extends Binder{
//从RecyclerView中删除指定下载任务
public void removeDownloadItemFromRecyclerView(DownloadTask removeTask){
int position=removeTask.getDownloadItemID();
if(MainActivity.downloadTaskArrayList.size()>1&&position<MainActivity.downloadTaskArrayList.size()-1){
for(int index=position+1;index<MainActivity.downloadTaskArrayList.size();index++){
DownloadTask modifyTask=MainActivity.downloadTaskArrayList.get(index);
modifyTask.setDownloadItemID(modifyTask.getDownloadItemID()-1);
}
}
MainActivity.downloadTaskArrayList.remove(removeTask);
MainActivity.downloadTaskAdapter.notifyItemRemoved(position);
}
//在RecyclerView中增加下载任务
public void addDownloadItemToRecyclerView(DownloadTask addTask){
if(!checkIsExist(addTask.getDownloadUrl())) {
MainActivity.downloadTaskArrayList.add(addTask);
addTask.setDownloadItemID(MainActivity.downloadTaskArrayList.size()-1);
MainActivity.downloadTaskAdapter.notifyItemInserted(MainActivity.downloadTaskArrayList.size()-1);
}
}
//在RecyclerView中替换指定的下载任务
public void setDownloadItemOnRecyclerView(DownloadTask oldTask){
int setPosition=oldTask.getDownloadItemID();
String resumeDownloadUrl=oldTask.getDownloadUrl();
int resumeProgress=oldTask.getDownloadProgress();
DownloadTask resumeTask=new DownloadTask(MainActivity.serviceListener);
resumeTask.setDownloadUrl(resumeDownloadUrl);
resumeTask.setDownloadProgress(resumeProgress);
resumeTask.setDownloadItemID(setPosition);
MainActivity.downloadTaskArrayList.set(setPosition,resumeTask);
MainActivity.downloadTaskAdapter.notifyItemChanged(setPosition);
}
//判断RecyclerView中是否已经包含指定的下载任务
public boolean checkIsExist(String downloadUrl){
boolean returnResult=false;
for(DownloadTask temp:MainActivity.downloadTaskArrayList){
if(temp.getDownloadUrl().equals(downloadUrl)){
returnResult=true;
}
}
return returnResult;
}
//开始下载服务入口
public void startDownload(String downloadUrl){
DownloadTask newTask=new DownloadTask(MainActivity.serviceListener);
newTask.setDownloadUrl(downloadUrl);
addDownloadItemToRecyclerView(newTask);
}
//暂停下载服务入口
public void pauseDownload(DownloadTask pauseTask){
if(pauseTask!=null){
pauseTask.setPaused();
}
}
//取消下载服务入口
public void cancelDownload(DownloadTask cancelTask){
if(cancelTask!=null){
removeDownloadItemFromRecyclerView(cancelTask);
cancelTask.setCanceled();
}else{
removeDownloadItemFromRecyclerView(cancelTask);
}
}
//恢复下载服务入口
public void resumeDownload(DownloadTask resumeDownload){
setDownloadItemOnRecyclerView(resumeDownload);
}
}
|
DownloadCallbackInterface |
package com.example.downloador;
//下载任务完成时回调接口
public interface DownloadCallbackInterface {
void onSuccess(int itemId);
void onFailed(int itemId);
void onPaused(int itemId);
void onCanceled(int itemId);
void onProgressChanged(int itemId,Integer progressValue);
}
|
CreateNewDownloadTaskActivity |
package com.example.downloador;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
//创建新任务对话框活动
public class CreateNewDownloadTaskActivity extends AppCompatActivity {
//创建对话框活动
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.create_new_download_task_layout);
setTitle("新建任务");
Button createDownloadTaskButton=findViewById(R.id.createDownloadTaskButton);
createDownloadTaskButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TextView downloadUrlEditText=findViewById(R.id.downloadUrlEditText);
if(downloadUrlEditText.getText().toString()!=null){
String downloadUrl=downloadUrlEditText.getText().toString();
if(checkUrl(downloadUrl)) {
Intent resultIntent = new Intent();
resultIntent.putExtra("downloadUrl", downloadUrl);
setResult(RESULT_OK, resultIntent);
onBackPressed();
}else{
Toast.makeText(CreateNewDownloadTaskActivity.this,"下载地址不符合格式要求",Toast.LENGTH_LONG).show();
}
}
}
});
Button cancelCreateDownloadTaskButton=findViewById(R.id.cancelCreateDownloadTaskButton);
cancelCreateDownloadTaskButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_CANCELED);
onBackPressed();
}
});
}
//判断下载地址格式是否符合格式要求
private boolean checkUrl(String url){
Uri uri=Uri.parse(url);
String scheme=uri.getScheme();
String filename=uri.getLastPathSegment();
if(("http".equalsIgnoreCase(scheme)||"https".equalsIgnoreCase(scheme))&&filename.contains(".")){
return true;
}else{
return false;
}
}
}
|
AndroidManifest.xml |
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.downloador">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".CreateNewDownloadTaskActivity"
android:theme="@style/Theme.AppCompat.Dialog"
android:launchMode="singleTask"></activity>
<service android:name=".DownloadService"
android:enabled="true"
android:exported="false"/>
</application>
</manifest> |
res/menu/main_activity_menu_resource.xml |
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="退出"
android:id="@+id/exitMenuItem"/>
</menu> |
res/layout/create_new_download_task_layout.xml |
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="400dp"
android:layout_height="200dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginHorizontal="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="下载URL:"
android:layout_marginTop="20dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/downloadUrlEditText"
android:textSize="60px"
android:text="http://8dx.pc6.com/xzx6/ccprojinst_v11.59.zip"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center">
<Button
android:id="@+id/createDownloadTaskButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下载" />
<Button
android:id="@+id/cancelCreateDownloadTaskButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />
</LinearLayout>
</LinearLayout> |
res/layout/download_task_recycler_view_layout.xml |
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="50dp"
android:layout_height="50dp"
android:id="@+id/startOrPauseDownloadTaskButton"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="50dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginTop="5dp"
android:singleLine="true"
android:ellipsize="middle"
android:id="@+id/downloadTaskUrl"/>
<ProgressBar
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:max="100"
android:layout_marginBottom="10dp"
android:id="@+id/downloadTaskProgressBar"
style="@style/Base.Widget.AppCompat.ProgressBar.Horizontal"/>
</LinearLayout>
<Button
android:layout_width="50dp"
android:layout_height="50dp"
android:text="X"
android:id="@+id/cancelDownloadTaskButton"/>
</LinearLayout> |
res/layout/main_activity_layout.xml |
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="新建任务"
android:textSize="60px"
android:textStyle="bold"
android:layout_weight="1"
android:id="@+id/openCreateNewTaskDialogButton"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="开始下载"
android:textSize="60px"
android:textStyle="bold"
android:id="@+id/startAllDownloadTaskButton"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暂停下载"
android:textSize="60px"
android:textStyle="bold"
android:id="@+id/pauseAllDownloadTaskButton"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="删除任务"
android:textSize="60px"
android:textStyle="bold"
android:id="@+id/deleteAllDownloadTaskButton"/>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000"/>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:id="@+id/downloadTaskRecyclerView" >
</android.support.v7.widget.RecyclerView>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#000000" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/downloadTaskCount"
android:layout_gravity="bottom"
android:text="下载任务数量:0"
android:textSize="60px"/>
</LinearLayout> |
build.gradle |
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.downloador"
minSdkVersion 17
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support:recyclerview-v7:28.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
|