首页 > 学院 > 开发设计 > 正文

第一行代码笔记 一个下载的demo

2019-11-06 09:56:44
字体:
来源:转载
供稿:网友

第一步:创建一个处理下载结果的接口

public interface DownloadListener {//    更新进度条    void onPRegress(int progress);//    下载成功    void onSuccess();//    下载失败    void onFaild();//    暂停下载    void onPaused();//    取消下载    void onCanceled();}

第二步:创建下载的异步任务,引用了okhttp

/** * AsyncTask三个参数 * 参数1:在执行AsyncTask时需要传入的参数。可用于后台任务中 * 参数2.后台任务执行时,如需显示进度,则使用这里指定的泛型作为进度单位 * 参数3.但任务执行完毕后,如果需要返回结果,则这里指定的泛型作为返回值类型 */public class DownLoadTask extends AsyncTask<String, Integer, Integer> {    public static final int TYPE_SUCCESS = 0;    public static final int TYPE_FAIL = 2;    public static final int TYPE_PAUSED = 3;    public static final int TYPE_CANCLE = 4;    private DownloadListener listener;    private boolean isCanceled = false;    private boolean isPaused = false;    private int lastProgress;    public DownLoadTask(DownloadListener downloadListener) {        listener = downloadListener;    }    /**     * 在后台任务执行之前调用,用于进行界面上的初始化操作,比如显示一个进度对话框     */    @Override    protected void onPreExecute() {        super.onPreExecute();    }    /**     * 在这里处理所有的耗时任务,任务一旦完成通过return返回     * 这里不能对UI进行操作,因为此处代码都运行在子线程中。     *     * @param params     * @return     */    @Override    protected Integer doInBackground(String... params) {        InputStream inputStream = null;        RandomaccessFile saveFile = null;        File file = null;        try {//            记录已下载文件的长度            long downLoadLenght = 0;            String downloadUrl = params[0];            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));//            SD卡的download目录            String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();            file = new File(directory + fileName);            if (file.exists()) {                downLoadLenght = file.length();            }//            获取文件的总长度            long contentLenght = getContentLenght(downloadUrl);            if (contentLenght == 0) {                return TYPE_FAIL;            } else if (contentLenght == downLoadLenght) {//                已下载的字节和文件总字节相等,说明下载已经完成                return TYPE_SUCCESS;            }            OkHttpClient client = new OkHttpClient();            Request request = new Request.Builder()//                    断点下载,指定从哪一个节点开始下载                    .addHeader("RANGE", "bytes=" + downLoadLenght + "-")                    .url(downloadUrl)                    .build();            Response response = client.newCall(request).execute();            if (response != null) {                inputStream = response.body().byteStream();                saveFile = new RandomAccessFile(file, "rw");                saveFile.seek(downLoadLenght);//跳过已下载的字节            }            byte[] b = new byte[1024];            int total = 0;            int len;            while ((len = inputStream.read(b)) != -1) {                if (isCanceled) {                    return TYPE_CANCLE;                } else if (isPaused) {                    return TYPE_PAUSED;                } else {                    total += len;                    saveFile.write(b, 0, len);                    int progress = (int) ((total + downLoadLenght) * 100 / contentLenght);//                    通知进度条更新                    publishProgress(progress);                }            }            response.body().close();            return TYPE_SUCCESS;        } catch (Exception e) {            e.printStackTrace();        } finally {            try {                if (inputStream != null) {                    inputStream.close();                }                if (saveFile != null) {                    saveFile.close();                }                if (isCanceled && file != null) {                    file.delete();                }            } catch (Exception e) {            }        }        return TYPE_FAIL;    }    /**     * 获取文件的总长度     * @param downloadUrl     * @return     * @throws IOException     */    private long getContentLenght(String downloadUrl) throws IOException {        OkHttpClient client = new OkHttpClient();        Request request = new Request.Builder()                .url(downloadUrl)                .build();        Response response = client.newCall(request).execute();        if (response != null && response.isSuccessful()) {            long contentLenght = response.body().contentLength();            response.close();            return contentLenght;        }        return 0;    }    /**     * 这里可以更新UI了     *     * @param values     */    @Override    protected void onProgressUpdate(Integer... values) {        super.onProgressUpdate(values);//        从参数中获取到当前的下载进度,和上一次下载进度对比,有变化则通知进度条更新        int progress = values[0];        if (progress > lastProgress) {            listener.onPregress(progress);            lastProgress = progress;        }    }    /**     * 但后台任务完成后return后这个方法马上会执行     * 并且rentur的值可以在参数中获得。这里做收尾工作     */    @Override    protected void onPostExecute(Integer integer) {        switch (integer) {            case TYPE_CANCLE:                listener.onCanceled();                break;            case TYPE_SUCCESS:                listener.onSuccess();                break;            case TYPE_PAUSED:                listener.onPaused();                break;            case TYPE_FAIL:                listener.onFaild();                break;        }    }    public void pauseDownload(){        isPaused =true;    }    public void cancleDownload(){        isCanceled =true;    }        /**     * 执行这个异步任务通过这个异步类的对象.execute()     */    }

第三步:创建一个服务,并通过通知通知下载进度

//保证DownLoadTask可以一直在后台运行,我们需要创建一个下载的服务//通过new -> service 创建一个service 这样就可以自动去清单文件注册了public class DownloadService extends Service {    private DownLoadTask downLoadTask;    private String downloadUrl;    private DownloadListener downloadListener = new DownloadListener() {        @Override        public void onPregress(int progress) {            getNotificationManager().notify(1, getNotification("Dowing...", progress));        }        @Override        public void onSuccess() {            downLoadTask = null;//            下载成功时将前台服务通知关闭,并创建一个下载成功的通知            stopForeground(true);            getNotificationManager().notify(1, getNotification("Download Success", -1));            Toast.makeText(DownloadService.this, "Download Success", Toast.LENGTH_SHORT).show();        }        @Override        public void onFaild() {            downLoadTask = null;//            下载失败时通知将前台服务关闭,并创建一个下载失败的通知            stopForeground(true);            getNotificationManager().notify(1, getNotification("Download Fail", -1));            Toast.makeText(DownloadService.this, "Download Fail", Toast.LENGTH_SHORT).show();        }        @Override        public void onPaused() {            downLoadTask = null;            Toast.makeText(DownloadService.this, "Download Paused", Toast.LENGTH_SHORT).show();        }        @Override        public void onCanceled() {            downLoadTask = null;            stopForeground(true);            Toast.makeText(DownloadService.this, "Download Cancle", Toast.LENGTH_SHORT).show();        }    };    private DownloadBinder binder = new DownloadBinder();    /**     *     */    class DownloadBinder extends Binder {        public void startDownload(String url) {            if (downLoadTask == null) {                downloadUrl = url;                downLoadTask = new DownLoadTask(downloadListener);//                在这里开启下载                downLoadTask.execute(downloadUrl);//                让这个服务成为一个前台服务。这样就可以在系统状态栏中创建一个持续运行的通知了                startForeground(1, getNotification("Downloading...", 0));                Toast.makeText(DownloadService.this, "Downing...", Toast.LENGTH_SHORT);            }        }        public void pauseDownload() {            if (downLoadTask != null) {                downLoadTask.pauseDownload();            }        }        public void cancelDownload() {            if (downLoadTask != null) {                downLoadTask.cancleDownload();            } else {                if (downloadUrl != null) {//                    取消下载时需将文件删除,并将通知关闭                    String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));                    String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();                    File file = new File(directory + fileName);                    if (file.exists()) {                        file.delete();                    }                    getNotificationManager().cancel(1);                    stopForeground(true);                    Toast.makeText(DownloadService.this, "Cancled", Toast.LENGTH_SHORT).show();                }            }        }    }    private NotificationManager getNotificationManager() {        return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);    }    /**     * 用于显示下载进度的通知     * @param title     * @param progress     * @return     */    private Notification getNotification(String title, int progress) {        Intent intent = new Intent(this, DownloadActivity.class);        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);        builder.setSmallIcon(R.mipmap.ic_launcher);        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.a8));        builder.setContentTitle(title);        builder.setContentIntent(pendingIntent);        if (progress > 0) {//            当progress大于或等于0时才需要显示下载进度            builder.setContentText(progress + "%");//           参数1:通知的做大进度。 2.通知的当前进度。 3.是否使用模糊进度条            builder.setProgress(100, progress, false);        }        return builder.build();    }    public DownloadService() {    }    @Override    public IBinder onBind(Intent intent) {        // TODO: Return the communication channel to the service.//        throw new UnsupportedOperationException("Not yet implemented");        return binder;    }}

第四步:使用

public class DownloadActivity extends AppCompatActivity implements View.OnClickListener {    private DownloadService.DownloadBinder downloadBinder;    private ServiceConnection connection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            downloadBinder = (DownloadService.DownloadBinder) service;        }        @Override        public void onServiceDisconnected(ComponentName name) {        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_download);        initView();    }    private void initView() {        findViewById(R.id.start).setOnClickListener(this);        findViewById(R.id.pause).setOnClickListener(this);        findViewById(R.id.cancle).setOnClickListener(this);        Intent intent = new Intent(this, DownloadService.class);        startService(intent); //启动服务        bindService(intent,connection,BIND_AUTO_CREATE); //绑定服务        if (ContextCompat.checkSelfPermission(DownloadActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){            ActivityCompat.requestPermissions(DownloadActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);        }    }    @Override    public void onClick(View v) {        if (downloadBinder == null){            return;        }        switch (v.getId()) {            case R.id.start:                String url = "http://218.201.198.108:8081/apk/oil1.apk";                downloadBinder.startDownload(url);                break;            case R.id.pause:                downloadBinder.pauseDownload();                break;            case R.id.cancle:                downloadBinder.cancelDownload();                break;        }    }    @Override    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {        switch (requestCode){            case  1:                if (grantResults.length>0 &&grantResults[0]!= PackageManager.PERMISSION_GRANTED){                    Toast.makeText(this,"权限被拒绝了呦",Toast.LENGTH_SHORT).show();                    finish();                }                break;        }    }    @Override    protected void onDestroy() {        super.onDestroy();//        要记得解绑,不然可能会造成内存溢出        unbindService(connection);    }}布局文件

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_download"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.lvyequeen.test.day06.DownloadActivity">    <Button        android:text="start download"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:layout_alignParentLeft="true"        android:layout_marginLeft="23dp"        android:layout_marginTop="31dp"        android:id="@+id/start" />    <Button        android:text="pause download"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@+id/start"        android:layout_alignRight="@+id/start"        android:layout_marginTop="36dp"        android:id="@+id/pause" />    <Button        android:text="cancle download"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@+id/pause"        android:layout_alignLeft="@+id/pause"        android:layout_marginTop="36dp"        android:id="@+id/cancle" /></RelativeLayout>


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表