Posts Tagged ‘download’

[Android] Async download file from network and save it in external SD card

Tuesday, November 15th, 2011

I created Async download class.

This usage app is..

Push download button. Then it starts downloading file from network.

When downloading is completed, it saves file in external sd card.

Add user permission in AndroidManifest.xml

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/loadStartButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Download" />

</LinearLayout>

AsyncFileLoader.java

I used AsyncTask.
And I read input file little by little and write output file with InputStream and OutputStream.


package com.kinkuma.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.os.AsyncTask;
import android.util.Log;

public class AsyncFileLoader extends AsyncTask<Void, Void, Boolean> {
	private final String TAG = "AsyncFileLoader";
	private String _urlStr;
	private URL _url;
	private URLConnection _urlConnection;
	private final int TIMEOUT_READ = 5000;
	private final int TIMEOUT_CONNECT = 30000;
	private InputStream _inputStream;
	private BufferedInputStream _bufferedInputStream;
	private FileOutputStream _fileOutputStream;
	private File _outputFile;
	private byte[] buff = new byte[5 * 1024];
	
	private int _totalByte = 0;
	private int _currentByte = 0;
	
	public AsyncFileLoader(String urlStr, File outputFile){
		this._urlStr = urlStr;
		this._outputFile = outputFile;
	}
	
	@Override
	protected Boolean doInBackground(Void... params) {
		
		if(isCancelled()){
			return false;
		}
		
		try{
			int len;
			while((len = _bufferedInputStream.read(buff)) != -1){
				_fileOutputStream.write(buff, 0, len);
				_currentByte += len;
				//publishProgress();
				if(isCancelled()){
					break;
				}
			}
	
		}catch(IOException e){
			Log.d(TAG, "error on read file:" + e.toString());
			return false;
		}
		return true;
	}
	
	@Override
	protected void onPreExecute(){
		try{
			connect();
		}catch(IOException e){
			Log.d(TAG, "error on preExecute:" + e.toString());
			cancel(true);
		}
	}
	/*
	@Override
	protected void onProgressUpdate(Void... progress){
		
	}
	*/
	@Override
	protected void onPostExecute(Boolean result){
		if(result == true){
			try{
				close();
			}catch(IOException e){
				Log.d(TAG, "error on postExecute:" + e.toString());
			}
		}else{
			Log.d(TAG, "result: load error");
		}
	}
	
	private void connect() throws IOException
	{
		_url = new URL(_urlStr);
		_urlConnection = _url.openConnection();
		_urlConnection.setReadTimeout(TIMEOUT_READ);
		_urlConnection.setConnectTimeout(TIMEOUT_CONNECT);
		_inputStream = _urlConnection.getInputStream();
		_bufferedInputStream = new BufferedInputStream(_inputStream, 1024 * 5);
		_fileOutputStream = new FileOutputStream(_outputFile);
		
		//_totalByte = _bufferedInputStream.available(); //this is not work
		_totalByte = _urlConnection.getContentLength();
		_currentByte = 0;
	}
	
	private void close() throws IOException
	{
		_fileOutputStream.flush();
		_fileOutputStream.close();
		_bufferedInputStream.close();
	}
	
	public int getLoadedBytePercent()
	{
		if(_totalByte <= 0){
			return 0;
		}
		//Log.d(TAG, Integer.toString(_currentByte) + ":" + Integer.toString(_totalByte));
		return (int)Math.floor(100 * _currentByte/_totalByte);
	}
}

main activity

To get the external sd card path, I used Environment.getExternalStorageDirectory().

package com.myprogress;

import java.io.File;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.kinkuma.util.AsyncFileLoader;

public class DownloadingAndProgressbarActivity extends Activity {
    private final String TAG = "DownloadSample";
	private Button _loadStartButton;
	private ProgressDialog _progressDialog;
	private Handler _progressHandler;
	private final String VIDEO_URL = "http://192.168.1.0/video/sample_movie.mp4";
	private AsyncFileLoader _fileLoader;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        _loadStartButton = (Button)findViewById(R.id.loadStartButton);
        _loadStartButton.setOnClickListener(new View.OnClickListener() {
		
			@Override
			public void onClick(View v) {
				initFileLoader();
				showDialog(0);
				_progressDialog.setProgress(0);
				_progressHandler.sendEmptyMessage(0);
			}
		});
        
        _progressHandler = new Handler(){
        	public void handleMessage(Message msg){
        		super.handleMessage(msg);
        		if(_fileLoader.isCancelled()){
        			_progressDialog.dismiss();
        			Log.d(TAG, "load canceled");
        		}
        		else if(_fileLoader.getStatus() == AsyncTask.Status.FINISHED){
        			_progressDialog.dismiss();
        		}else{
        			_progressDialog.setProgress(_fileLoader.getLoadedBytePercent());
        			_progressHandler.sendEmptyMessageDelayed(0, 100);
        		}
        	}
        };
    }
    
    @Override
    protected void onPause(){
    	Log.d(TAG, "onPause");
    	super.onPause();
    	cancelLoad();
    }
    
    @Override
    protected void onStop(){
    	Log.d(TAG, "onStop");
    	super.onStop();
    	cancelLoad();
    }
    
    private void cancelLoad()
    {
    	if(_fileLoader != null){
    		_fileLoader.cancel(true);
    	}
    }
    
    private void initFileLoader()
    {
    	File sdCard = Environment.getExternalStorageDirectory();
    	File directory = new File(sdCard.getAbsolutePath() + "/SampleFolder");
    	if(directory.exists() == false){
    		directory.mkdir();
    	}
    	File outputFile = new File(directory, "myvideo.mp4");
    	_fileLoader = new AsyncFileLoader(VIDEO_URL, outputFile);
    	_fileLoader.execute();
    }
    
    @Override
    protected Dialog onCreateDialog(int id){
    	switch(id){
    		case 0:
    			_progressDialog = new ProgressDialog(this);
    			_progressDialog.setIcon(R.drawable.ic_launcher);
    			_progressDialog.setTitle("Downloading files..");
    			_progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    			_progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Hide", new DialogInterface.OnClickListener() {
					
				@Override
				public void onClick(DialogInterface dialog, int which) {
						Log.d(TAG, "hide");
					}
				});
    			_progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
					
					@Override
					public void onClick(DialogInterface dialog, int which) {
						Log.d(TAG, "cancel");
						cancelLoad();
					}
				});
    	}
		return _progressDialog;
    }
}