使用service实现通知栏下载支持断点续传

来源:互联网 发布:电脑壁纸软件哪个好 编辑:程序博客网 时间:2024/05/18 00:03

先看一下效果
效果图

首先写一个监听器用来处理返回结果

public interface DownloadListener {     void onProgress(int progreess);     void onPuase();     void onCancel();     void onFailed();     void onSuccess();}

然后写一个异步任务来下载,在异步任务中传入DownloadListener 来处理下载的情况。使用异步任务的目的是为了能根据返回值方便的处理监听。

package down;import android.os.AsyncTask;import android.os.Environment;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;/** * Created by yuanteng on 2017/6/30. */public class DownLoadTask extends AsyncTask<String,Integer,Integer> {    public static final int TYPE_SUCESS = 0;    public static final int TYPE_FAILED = 1;    public static final int TYPE_PAUSE = 2;    public static final int TYPE_CANCEL = 3;    private boolean isCancel = false;    private boolean isPause = false;    private DownloadListener listener;    private int lastProgress;    public DownLoadTask(DownloadListener listener){        this.listener = listener;    }    @Override    protected Integer doInBackground(String... strings) {        InputStream inputStream = null;        //随机读取文件类可以指定文件从哪个地方开始写入,所以不用OutputStream        RandomAccessFile saveFile = null;        long downLoadLength = 0;//记录已经下载下的长度        File file = null;        try {            String downUrl = strings[0];            String fileName = downUrl.substring(downUrl.lastIndexOf("/"));            String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();            file = new File(dir + fileName);            if (file.exists()){                downLoadLength = file.length();            }            long contentLength = getContentLength(downUrl);            if (contentLength == 0){                return TYPE_FAILED;            }            if (contentLength == downLoadLength){                return TYPE_SUCESS;            }            OkHttpClient client = new OkHttpClient();            Request request = new Request.Builder()                    //断点下载                    .addHeader("RANGE","bytes="+downLoadLength+"-")                    .url(downUrl)                    .build();            Response response = client.newCall(request).execute();            if (response != null && response.isSuccessful()){                inputStream = response.body().byteStream();                saveFile = new RandomAccessFile(file,"rw");                //断点续传                saveFile.seek(downLoadLength);                byte[] b = new byte[4096];                int total = 0;                int len ;                while ((len = inputStream.read(b)) != -1){                    if (isCancel){                        return TYPE_CANCEL;                    }                    else if (isPause){                        return TYPE_PAUSE;                    }                    else {                        total += len;                        saveFile.write(b,0,len);                        int progress = (int)((total + downLoadLength)*100/contentLength);                        publishProgress(progress);                    }                }                response.body().close();                return TYPE_SUCESS;            }        }        catch (Exception e){            e.printStackTrace();        }        finally {            try {                if (inputStream != null){                    inputStream.close();                }                if (saveFile != null){                    saveFile.close();                }                if (isCancel && file != null){                    file.delete();                }            }            catch (IOException e){                e.printStackTrace();            }        }        return TYPE_FAILED;    }    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);        int progress = values[0];        if (progress > lastProgress){            listener.onProgress(progress);            lastProgress = progress;        }    }    /*根据不同的返回值进行处理*/    @Override    protected void onPostExecute(Integer integer) {        super.onPostExecute(integer);        switch (integer){            case TYPE_SUCESS:                listener.onSuccess();                break;            case TYPE_CANCEL:                listener.onCancel();                break;            case TYPE_PAUSE:                listener.onPuase();                break;            case TYPE_FAILED:                listener.onFailed();                break;            default:                break;        }    }    /*改变暂停或者取消的状态*/    public void pauseDownLoad(){        isPause = true;    }    public void cancelDownLoad(){        isCancel = true;    }    /*    * 获取文件的长度*/    private long getContentLength(String downUrl){        OkHttpClient okHttpClient = new OkHttpClient();        Request request = new Request.Builder().url(downUrl).build();        try {            Response response = okHttpClient.newCall(request).execute();            if (response != null && response.isSuccessful()){                long length = response.body().contentLength();                response.close();                return length;            }        } catch (IOException e) {            e.printStackTrace();        }        return  0;    }}

现在是关键部分写一个service

package down;import android.app.Notification;import android.app.NotificationManager;import android.app.PendingIntent;import android.app.Service;import android.content.Intent;import android.graphics.BitmapFactory;import android.os.Binder;import android.os.Environment;import android.os.IBinder;import android.support.v7.app.NotificationCompat;import com.petecc.potevio.testvitmionew.MainActivity;import com.petecc.potevio.testvitmionew.R;import com.petecc.potevio.testvitmionew.TestDownLoadActivity;import java.io.File;public class DownLoadService extends Service {    private DownLoadTask downLoadTask;    private String downloadUrl;    private DownloadListener listener = new DownloadListener() {        @Override        public void onProgress(int progreess) {            getNotificationManager().notify(1,getNotification("下载中...",progreess));        }        @Override        public void onPuase() {             downLoadTask = null;        }        @Override        public void onCancel() {            downLoadTask = null;            //将前台服务通知关闭            stopForeground(true);        }        @Override        public void onFailed() {            downLoadTask = null;            //将前台服务通知关闭,并创建一个下载失败通知            stopForeground(true);            getNotificationManager().notify(1,getNotification("下载失败!",-1));        }        @Override        public void onSuccess() {            downLoadTask = null;            //将前台服务通知关闭,并创建一个下载成功通知            stopForeground(true);            getNotificationManager().notify(1,getNotification("下载成功!",-1));        }    };    public DownLoadService() {    }    private DownLoadBinder downLoadBinder = new DownLoadBinder();    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.        return downLoadBinder;    }   public class DownLoadBinder extends Binder{        public void startDownLoad(String url){            if (downLoadTask == null){                downloadUrl = url;                downLoadTask = new DownLoadTask(listener);                downLoadTask.execute(url);                //开启前台服务,保证在内存低的情况下服务不会被杀死。同时系统会创建一个notification                startForeground(1,getNotification("下载中...",0));            }        }        public void pauseDownload(){            if (downLoadTask != null){                downLoadTask.pauseDownLoad();            }        }        public void cancelDownload(){            if (downLoadTask != null){                downLoadTask.cancelDownLoad();            }            else{                //如果downloadUrl不等于null删除已经下载的文件,并关闭通知                if (downloadUrl != null){                    String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));                    String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();                    File file = new File(dir+fileName);                    if (file.exists()){                        file.delete();                    }                    getNotificationManager().cancel(1);                    //取消前台服务                    stopForeground(true);                }            }        }    }    /*获取Notification*/    private Notification getNotification(String title,int progress){        //intent  需要根据自己的需要来制定        Intent intent = new Intent(DownLoadService.this, TestDownLoadActivity.class);        PendingIntent penIntent = PendingIntent.getActivity(DownLoadService.this,0,intent,PendingIntent.FLAG_ONE_SHOT);        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);        builder.setContentTitle(title);        builder.setSmallIcon(R.mipmap.ic_launcher);        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher));        builder.setAutoCancel(true);        builder.setWhen(System.currentTimeMillis());        builder.setContentIntent(penIntent);        if (progress >= 0){            builder.setContentText(progress+" %");            builder.setProgress(100,progress,false);        }        return builder.build();    }    /*获取NotificationManager*/    private NotificationManager getNotificationManager(){        return ((NotificationManager) getSystemService(NOTIFICATION_SERVICE));    }}

测试使用

import android.Manifest;import android.content.ComponentName;import android.content.Intent;import android.content.ServiceConnection;import android.content.pm.PackageManager;import android.os.Bundle;import android.os.IBinder;import android.support.annotation.NonNull;import android.support.v4.app.ActivityCompat;import android.support.v4.content.ContextCompat;import android.support.v7.app.AppCompatActivity;import android.view.View;import android.widget.Button;import android.widget.Toast;import butterknife.BindView;import butterknife.ButterKnife;import butterknife.OnClick;import down.DownLoadService;public class TestDownLoadActivity extends AppCompatActivity {    @BindView(R.id.start)    Button start;    @BindView(R.id.pause)    Button pause;    @BindView(R.id.cancel)    Button cancel;    @BindView(R.id.agin)    Button agin;    private DownLoadService.DownLoadBinder binder;    private ServiceConnection serviceConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {            binder = (DownLoadService.DownLoadBinder) iBinder;        }        @Override        public void onServiceDisconnected(ComponentName componentName) {        }    };    private String path = "https://raw.githubusercontent.com/guolindev/eclipse/master/eclipse-inst-win64.exe";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_test_down_load);        ButterKnife.bind(this);        Intent intent = new Intent(this, DownLoadService.class);        startService(intent);        bindService(intent, serviceConnection, BIND_AUTO_CREATE);        //检查权限是否授权        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);        }    }    @OnClick({R.id.start, R.id.pause, R.id.cancel,R.id.agin})    public void onViewClicked(View view) {        if (binder == null) {            return;        }        switch (view.getId()) {            case R.id.start:                binder.startDownLoad(path);                break;            case R.id.pause:                binder.pauseDownload();                break;            case R.id.cancel:                binder.cancelDownload();                break;            case R.id.agin:                binder.startDownLoad("http://imgsrc.baidu.com/image/c0%3Dshijue%2C0%2C0%2C245%2C40/sign=2f6a98db3cd3d539d530078052ee8325/8c1001e93901213f5e8ef6f95ee736d12f2e9552.jpg");                break;        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        super.onRequestPermissionsResult(requestCode, permissions, grantResults);        switch (requestCode) {            case 1:                if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED) {                    Toast.makeText(this, "无法使用", Toast.LENGTH_SHORT).show();                    finish();                }        }    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(serviceConnection);    }    @OnClick(R.id.agin)    public void onViewClicked() {    }}

记得在清单文件注册service

            android:name="down.DownLoadService"            android:enabled="true"            android:exported="true" />

所有代码就这么多,除布局文件都已经贴出!

欢迎点赞!

阅读全文
0 0
原创粉丝点击