《项目实战:下载器迷你版》


源代码
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'
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值