zoukankan      html  css  js  c++  java
  • 实现下载功能

    1.定义一个接口,用于下载过程中各种状态的回调监听。

    public interface DownloadListener {
        void onProgress(int progress);
        void onSuccess();
        void onFailed();
        void onPause();
        void onCanceled();
    }
    

     2.接口完成我们写下载程序,并且使它继承AsyncTask<>,泛型方法中第一个为string类型,后两个为Integer类型,作用string 给后台发送字符串数据,第二个作为显示进度,第三个反馈执行结果

    我们在这个类中定义4个常量,分别表示下载成功,暂停,下载失败,终止

        public static final int TYPE_SUCCESS=0;
        public static final int TYPE_FAILED=1;
        public static final int TYPE_PAUSED=2;
        public static final int TYPE_CANCELED=3;
    

     紧接着重写最重要的doInBackground(),onProgressUpdate(),onPostExecte()方法。

    我们在doInBackground()方法中获取文件的储存路径,并且判断文件是否存在,如果存在获取文件的大小,我们还用通过下载路径获取需要下载文件的大小,利用getContentLengh()方法获取。

    获取后判断获取的值,如果获取的值为0则表示下载文件不存在,如果它和已存在文件大小相等大小证明下载完成

     1   protected Integer doInBackground(String... params) {
     2         RandomAccessFile saveFile = null;
     3         File file=null;
     4         try {
     5             //记录文件长度
     6             long downloadLength = 0;
     7             //获取url
     8             String downloadUrl = params[0];
     9             //获取文件名
    10            String fileName= downloadUrl.substring(downloadUrl.lastIndexOf("/"));
    11             //指定下载路径
    12           String dierctory=  Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
    13             //拼接
    14             file=new File(dierctory+fileName);
    15             //判断文件是否存在如果存在读取文件字节大小
    16             if (file.exists()){
    17                 downloadLength=file.length();
    18             }
    19             //通过getContentLength()方法获取需要下载文件大小
    20             long contentLength = getContentLength(downloadUrl);
    21             if (contentLength==0){
    22                 return TYPE_FAILED;
    23             }else if (contentLength==downloadLength){
    24                 return TYPE_SUCCESS;
    25             }

    下面我们通过URL的方法发送地址HttpURLConnection我定义为了全局变量

    。。。。    
    URL url = new URL(downloadUrl);
                connection = (HttpURLConnection)url.openConnection();
                connection.setRequestMethod("GET");
                connection.setRequestProperty("RANGE","bytes="+downloadLength+"-");//在已存在文件的基础上继续写入
                in = connection.getInputStream();//得到返回值,这里的返回值是以字节流的形式返回

    下面进行判断和关闭流

     if (in!=null){
                    saveFile =new RandomAccessFile(file,"rw");
                    //跳过已经下载的字节
                    saveFile.seek(downloadLength);
                    //写入
                    byte[] b = new byte[1024];
                    int total = 0;
                    int len;
                    while ((len=in.read(b))!=-1){
                        if (isCanceled){
                            return TYPE_CANCELED;
                        }else if (isPause){
                            return TYPE_PAUSED;
                        }else {
                            total+=len;
                            saveFile.write(b,0,len);
                            //计算一下载的百分比
                            int progress= (int) ((total+downloadLength)*100/contentLength);
                            //以进度条的形式显示
                            publishProgress(progress);
                        }
                    }
                    //下载完成关闭获取数据流
                    in.close();
                    return TYPE_SUCCESS;
                }
    
            }catch (Exception e){
    
            }finally {
                try {
                //关闭写入流
                if (in!=null){
                        in.close();
                    }
                    if (saveFile!=null){
                        saveFile.close();
                    }
                    if (isCanceled && file!=null){
                        file.delete();
                    }
                }catch (Exception e){}
            }
            return TYPE_FAILED;
        }

    接下来是onProgressUpdate()方法,它的作用是获取得到当前的下载速度有过有变化就调用DownloadListenter的onProgress()方法来通知下载进度更新

        protected void onProgressUpdate(Integer... values) {
            int progress = values[0];
            if (progress>lastProgress){
                listener.onProgress(progress);
                lastProgress=progress;
            }
        }

    onPostExecte()方法根据传入的参数回调放发

       protected void onPostExecute(Integer status) {
            switch (status){
                case TYPE_SUCCESS:
                    listener.onSuccess();
                    break;
                case TYPE_FAILED:
                    listener.onFailed();
                    break;
                case TYPE_PAUSED:
                    listener.onPause();
                    break;
                case TYPE_CANCELED:
                    listener.onCanceled();
                    default:
                    break;
            }
        }
        //通知下载更新进度
        public void pauseDownload(){
    
            isPause =true;
        }
        public void canceDownload(){
            isCanceled = true;
        }
        private long getContentLength(String downloadUri) throws IOException{
            //发送url
            URL url = new URL(downloadUri);
            connection= (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
    
            InputStream is = connection.getInputStream();
    
            //读取返回的文件
            if (is!=null){
                //获取文件大小
    
                long contentLength=  connection.getContentLength();
                is.close();//关闭请求
                return contentLength;
            }
            return 0;
        }
    

    下载功能写完了就创建一个下载服务并且继承Service.我们在其中创建了DownloadListener的匿名实例

    我们先创建一个NotificationManager

        private NotificationManager getNotificationManager(){
            return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        }
    

     然后用它调用notify()方法去触发这个通知可以当前的下载进度。接下来我们创建Notification实例实现通知,

     private Notification getNotification(String title,int progress){
          Intent intent= new Intent(this,MainActivity.class);
           PendingIntent pi= PendingIntent.getActivity(this,0,intent,0);
            //设置通知
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
            builder.setSmallIcon(R.mipmap.ic_launcher_round);
            builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher_round));
            //设置点击
            builder.setContentIntent(pi);
            builder.setContentTitle(title);
    
            if (progress>=0){
                //显示下载进度
                builder.setContentText(progress+"%");
                builder.setProgress(100,progress,false);//false 使进度条显现出来
            }
            return builder.build();
        }

    我们创建了匿名实例后它会实现接口中我们定义的那5种方法

        private DownloadListener listener = new DownloadListener() {
            @Override
            public void onProgress(int progress) {
                getNotificationManager().notify(1,getNotification("准备下载",progress));
            }
    
            @Override
            public void onSuccess() {
                downloadTask =null;
                //关闭前台服务
                stopForeground(true);
                getNotificationManager().notify(1,getNotification("下载成功",-1));
                Toast.makeText(DownloadService.this,"下载成功",Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onFailed() {
                downloadTask=null;
                stopForeground(true);
                getNotificationManager().notify(1,getNotification("下载失败",-1));
                Toast.makeText(DownloadService.this,"下载失败",Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onPause() {
                downloadTask=null;
                Toast.makeText(DownloadService.this,"下载暂停",Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onCanceled() {
                downloadTask=null;
                stopForeground(true);
                Toast.makeText(DownloadService.this,"下载停止",Toast.LENGTH_SHORT).show();
            }
        };

    下面我们创建了DownloadBinder,它提供了startDownload(),pauseDownload()和cancelDownload()方法

    在startDownload()中我们创建了DownloadTask的实例,将DownloadListener作为参数传入,然后用execute()方法开启下载,在其中我们还调用了stsrtForeground()方法这样就会创建一个持续运行的通知了

        private DownlosdBind mBind = new DownlosdBind();
        public IBinder onBind(Intent intent) {
            return mBind;
        }
        class DownlosdBind extends Binder{
            public void startDownload(String url){
                if (downloadTask==null){
                    downloadUrl=url;
                    downloadTask = new DownloadTask(listener);
                    downloadTask.execute(downloadUrl);
                    startForeground(1,getNotification("Downloading...",0));
                    Toast.makeText(DownloadService.this,"Downloading...",Toast.LENGTH_SHORT).show();
                }
            }
          public void pauseDownload(){
                if (downloadTask!=null){
                    downloadTask.pauseDownload();
                }
            }

    下面我们介绍一下取消,当我们点击取消后删除我们没有下载完的文件

    首先判断url是不是存在,如果存在就获取我们所下载文件的位置,然后调用删除方法

       public void cancelDownload(){
                if (downloadTask!=null){
                    downloadTask.canceDownload();
                }else {
                    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);
                        Toast.makeText(DownloadService.this,"Canceled 取消",Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }

    在主函数中首先我们创建ServiceConnection的匿名类,然后在onServiceConnected()方法中的到DownloadBinder实例

        DownloadService.DownlosdBind downlosdBind;
        ServiceConnection connection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                downlosdBind = (DownloadService.DownlosdBind) service;
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
        };

    在onCreate()方法中通过意图开启活动并且通过bindSrevice()方法绑定服务

       protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Intent intent = new Intent(this,DownloadService.class);
            startService(intent);
            bindService(intent,connection,BIND_AUTO_CREATE);
    //运行权限
    if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1); } }

    在点击按钮中调用对应的方法

      public void click1(View v){
            String url = "http://sw.bos.baidu.com/sw-search-sp/software/b9e8735a86508/huya_audience_1.0.2.0.exe";
            downlosdBind.startDownload(url);
        }
        public void click2(View v){
            downlosdBind.pauseDownload();
        }
        public void click3(View v){
            downlosdBind.cancelDownload();
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(connection);
        }
  • 相关阅读:
    SQL Server AUTO_FIX_Login_Users
    SQL Server Always On 切换主机Login和User无法匹配解决方案
    SQL Server 目标主体名称不正确,无法生成 SSPI 上下文
    SQL Server Rebuild Index
    jqery和js如何判断checkbox是否选中 (转)
    jxl
    jxl 管理excel
    Bootstrap库之Modals
    jquery attr()
    js 验证数字(验证字符串是否是数字)
  • 原文地址:https://www.cnblogs.com/lyl123/p/7211196.html
Copyright © 2011-2022 走看看