[英]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 "";
}
}
use this code in onClick() DownloadManager downloadManager = new DownloadManager(url,filepath); 在onClick()中使用此代码DownloadManager downloadManager = new DownloadManager(url,filepath);
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){} } });
start download by 开始下载
downloadManager.execute();
lib setup lib设置
compile "commons-io:commons-io:+"
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: 解决此问题的方法很少:
foreground service
. foreground service
使用下载。 Its really good thread.interrupt()
method in onDestroy
of your Activity
/ Fragment
Activity
/ Fragment
onDestroy
的thread.interrupt()
方法来中断下载 rxJava
/ rxAndroid
(so you don not use threads at all, but you need some time for learn rxJava
) rxJava
/ rxAndroid
东西(所以你根本不使用线程,但是你需要一些时间来学习rxJava
) UPD UPD
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.