How to download a file after clicking a button (Android Studio)

前端 未结 2 1119
粉色の甜心
粉色の甜心 2020-12-31 23:23

I recently created an activity in my app. Now I wanted the user to download a .pdf file when he/she wants to view the guidelines. I wanted to implement this on a button. Any

相关标签:
2条回答
  • 2021-01-01 00:04

    if you want resumable, speed of download ... follow this steps

    create a class DownloadManager.java

    public class DownloadManager extends AsyncTask<String,String,String>{
    String downloadlink,fileDestination;
    public static final int ON_INIT=100,ON_ERROR=102,ON_PROGRASS=103,ON_COMPLETED=104,STATUS_DOWNLOADED=1500,STATUS_NOT_YET=1501;
    private onUpdateListener onUpdateListener;
    private String downloadedPath="";
    private long downloaded=0;
    private File file;
    private String returnData=null;
    private File cacheDownloadFile;
    public DownloadManager(String downloadlink,String fileDestinationPath){
        this.downloadlink=downloadlink;
        this.fileDestination=fileDestinationPath;
        file=new File(fileDestination, Tools.getFileName(downloadlink));
        cacheDownloadFile=new File(AppCostants.CHACHE_PATH+Tools.getFileName(downloadlink));
        try {
            if(cacheDownloadFile.isFile())
                downloaded=Tools.getFileSize(cacheDownloadFile);
            else
                downloaded=0;
            Log.d("FILE_DOWNLOAD_TAG_p",downloaded+" <- "+cacheDownloadFile.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        fireOnUpdate(ON_INIT,"init ...");
    
    }
    @Override
    protected String doInBackground(String... params) {
        try {
            File dir=new File(fileDestination);
            File chacheDir=new File(AppCostants.CHACHE_PATH);
            if(!chacheDir.isDirectory())
                chacheDir.mkdirs();
            if(!dir.isDirectory()){
                dir.mkdirs();
            }
    
            if(file.exists()) {
                Log.d("FILE_DOWNLOAD_TAG","File exist return complete");
                return "COMPLETED";//file exist
            }
            if(!cacheDownloadFile.exists()){
                cacheDownloadFile.createNewFile();
            }
            Log.d("FILE_DOWNLOAD_TAG","LINK "+downloadlink);
            URL url=new URL(downloadlink);
            HttpURLConnection urlConnection= (HttpURLConnection) url.openConnection();
            if(downloaded>0)
                urlConnection.setRequestProperty("Range","byte="+downloaded);
            urlConnection.connect();
            int status = urlConnection.getResponseCode();
            InputStream inputStream=urlConnection.getInputStream();
            int totalSize=urlConnection.getContentLength();
            if(totalSize<=downloaded){
                returnData= "COMPLETED";
                publishProgress("File checked "+Tools.getFileName(file.getAbsolutePath()));
                return returnData;
            }
            this.downloadedPath=cacheDownloadFile.getAbsolutePath();
            byte[] buffer=new byte[1024];
            int bufferLength=0;
            FileOutputStream fileOutput=new FileOutputStream(cacheDownloadFile);
            long d=0;
            long starttime=System.currentTimeMillis();
            while ((bufferLength=inputStream.read(buffer))>0){
                fileOutput.write(buffer,0,bufferLength);
                downloaded+=bufferLength;
                d+=bufferLength;
                //String l=" "+Tools.getFileName(file.getAbsolutePath())+" ( "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" )";
                String l="  "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" ( "+getDownloadSpeed(starttime,d)+" )";
                publishProgress(l);
                if(downloaded>=totalSize){
                    break;
                }
            }
            Log.d("FILE_DOWNLOAD_TAG","DWONLOADED TO "+downloadedPath+" ("+cacheDownloadFile.length()+")");
            fileOutput.close();
            if(Tools.fileCopy(file,cacheDownloadFile)){
                Log.d("FILE_DOWNLOAD_TAG","file Copied, delete cache");
                cacheDownloadFile.delete();
            }
            returnData="COMPLETED";
        } catch (MalformedURLException e) {
            returnData=null;
            e.printStackTrace();
            publishProgress(e.toString());
            Log.d("###################",e+"");
    
        } catch (IOException e) {
            returnData=null;
            e.printStackTrace();
            publishProgress(e.toString());
        }
    
        return returnData;
    }
    
    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
        fireOnUpdate(ON_PROGRASS,values[0]);
    }
    
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if(s!=null){
            fireOnUpdate(ON_COMPLETED,downloadedPath);
        }else{
            fireOnUpdate(ON_ERROR,"Download failed");
        }
    }
    
    public interface onUpdateListener{
        void onUpdate(int code,String message);
    }
    public void setOnUpdateListener(onUpdateListener onUpdateListener){
        this.onUpdateListener=onUpdateListener;
    }
    private void fireOnUpdate(int code,String message){
        if(onUpdateListener!=null)
            onUpdateListener.onUpdate(code,message);
    }
    
    private String getDownloadSpeed(long starttime,float totalDownloaded) {
        long elapsedTime = System.currentTimeMillis() - starttime;
        //byte :
        float speed=1000f * totalDownloaded / elapsedTime;
        return convert(speed);
    }
    private String convert(float value){
        long kb=1024
                ,mb=kb*1024
                ,gb=mb*1024;
    
        if(value<kb){
            String speed=(value+"");
            speed=speed.substring(0,speed.indexOf('.')+2);
            return speed+" B/s";
        }else if(value<mb){
            value=value/kb;
            String speed=(value+"");
            speed=speed.substring(0,speed.indexOf('.'));
            return (speed)+" KB/s";
        }else if(value<gb){
            value=(value/mb);
            String speed=(value+"");
            speed=speed.substring(0,speed.indexOf('.'));
            return speed+" MB/s";
        }
        return "";
    }
    }
    
    1. use this code in onClick() DownloadManager downloadManager = new DownloadManager(url,filepath);

    2. set event

      downloadManager.setOnUpdateListener(new DownloadManager.onUpdateListener() {
      @Override
      public void onUpdate(int code, String message) {
      if (code == DownloadManager.ON_COMPLETED) {
      
                      }
                      if(DownloadManager.ON_PROGRASS==code){}
      
                  }
              });
      
    3. start download by

      downloadManager.execute();
      
    4. lib setup

      compile "commons-io:commons-io:+"
      
    5. Tools.java

      public static long getFileSize(File file) throws IOException {
      FileOutputStream fileOutputStream=new FileOutputStream(file);
      fileOutputStream.close();
      return file.length();
      }
      public static boolean fileCopy(File dest,File source){
      try {
          FileUtils.copyFile(source,dest);
          return true;
      } catch (IOException e) {
          e.printStackTrace();
          return false;
      }
      }
      
    0 讨论(0)
  • 2021-01-01 00:06

    It is really bad idea to download file in main thread. Use separate Thread for this

    Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
             //your downloading here
        }
    });
    thread.start();
    

    it`s better, but still not so good. There are some problems with it:

    1) User know nothing about downloading

    So better to show additional layout which overlays screen with progress bar, probably indeterminate if you want to write less code. Then after downloading is finished you just hide your layout.

    You can use runOnUiThread inside run method in thread for it.

    runOnUiThread(new Runnable() {
       @Override
       public void run() {
            //just hide some popup
            //or do what you want after downloading is finished
            popupLayout.serVisibility(View.GONE);
       }
    });
    

    2) If user will do action which re-creates activity/fragment (like changing screen orientaion) with running thread you will get memory leak and probably activity will not know about end of download.

    There are few ways to solve this problem:

    • You can block screen orientation at this screen, at least while downloading. Probably easiest way in your case.
    • You can use downloading in foreground service. Its really good
      practice, but you will have to learn about services.
    • You can try to interrupt downloading by calling thread.interrupt() method in onDestroy of your Activity/Fragment
    • You can use something like rxJava/rxAndroid (so you don not use threads at all, but you need some time for learn rxJava)

    UPD

    About threads

    Not so bad tutorial about threads in android

    You can use AsyncTask instead of Thread, but I highly recommend to use threads especially for long operations.

    0 讨论(0)
提交回复
热议问题