简体   繁体   English

单击按钮后如何下载文件(Android Studio)

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

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. 现在我希望用户在他/她想要查看指南时下载.pdf文件。 I wanted to implement this on a button. 我想在一个按钮上实现它。 Any idea how to do this properly? 知道如何正确地做到这一点?

Heres my code below: 下面是我的代码:

public class Exhibitor_Registration_Activity extends AppCompatActivity  {

    Button buttonDownload;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exhibitor_registration_);

        this.setTitle("Buyer Registration");

        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
        setSupportActionBar(myToolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        myToolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);

        final Button buttonDownload = (Button) findViewById(R.id.buttonDownload);

        buttonDownload.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                try {
                    //this is the file you want to download from the remote server
                    String path ="http://www.manilafame.com/website-assets/downloads/exhibitor-application-kit/local/201704/1-Summary-of-Participation-Details-April-2017_MN_002.pdfp";
                    //this is the name of the local file you will create
                    String targetFileName = null;
                    boolean eof = false;
                    URL u = new URL(path);
                    HttpURLConnection c = (HttpURLConnection) u.openConnection();
                    c.setRequestMethod("GET");
                    c.setDoOutput(true);
                    c.connect();
                    FileOutputStream f = new FileOutputStream(new File("c:\\junk\\"+targetFileName));
                    InputStream in = c.getInputStream();
                    byte[] buffer = new byte[1024];
                    int len1 = 0;
                    while ( (len1 = in.read(buffer)) > 0 ) {
                        f.write(buffer,0, len1);
                    }
                    f.close();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ProtocolException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
    }
}

I also got the source code from here and here . 我也从这里这里得到了源代码。

if you want resumable, speed of download ... follow this steps 如果您想要可恢复,下载速度...请按照以下步骤操作

create a class DownloadManager.java 创建一个类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); 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 lib设置

     compile "commons-io:commons-io:+" 
  5. Tools.java 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; } } 

It is really bad idea to download file in main thread. 在主线程中下载文件真是个坏主意。 Use separate Thread for this 为此使用单独的Thread

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 1)用户对下载一无所知

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里面的run方法。

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. 2)如果用户将使用正在运行的线程执行重新创建活动/片段(如更改屏幕方向)的操作,您将获得内存泄漏,并且可能活动将不知道下载结束。

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 . 您可以在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 您可以尝试通过调用Activity / Fragment onDestroythread.interrupt()方法来中断下载
  • You can use something like rxJava / rxAndroid (so you don not use threads at all, but you need some time for learn rxJava ) 你可以使用类似rxJava / rxAndroid东西(所以你根本不使用线程,但是你需要一些时间来学习rxJava

UPD UPD

About threads 关于线程

Not so bad tutorial about threads in android 关于android中的线程的教程不是那么糟糕

You can use AsyncTask instead of Thread , but I highly recommend to use threads especially for long operations. 您可以使用AsyncTask而不是Thread ,但我强烈建议使用线程,尤其是长时间操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 单击Android Studio中的按钮后,如何在TextView中显示输入的文本? - How to display inputted text in a TextView after clicking a button in Android studio? 在android中单击按钮后如何重绘linearlayout? - how to redraw linearlayout after clicking on button in android? Android点击后如何隐藏按钮 - How to hide the button after clicking in Android Android Studio - 单击按钮后,当前活动重新打开 - Android Studio - After clicking button current activity reopens 如何在运行时解决android studio项目应用程序而不是单击按钮后崩溃 - How to solve android studio project application when run than crashing after clicking on button 在Android Studio中单击“提交”按钮后,如何将输入的值存储到变量并在屏幕上显示它们? - How to store entered values to variables and display them on screen after clicking submit button in Android Studio? 如何在Android Studio中下载和查看hprof文件 - How to download and view hprof file in Android Studio 如何通过单击android studio中的按钮使图像可见和不可见? - How to make visible and invisible an image by clicking a button in android studio? 如何在Android Studio中通过单击不同活动中的按钮来在活动中启动图像 - how to launch an image in a activity by clicking a button in a diffrent activity in android studio 单击按钮后绘制Android - draw after clicking button Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM