Monday 12 September 2011

ArrayList Example in java and find the maximum and minimum element and sum of arraylist

Here is the code:
//Import the util package and classes
import java.util.ArrayList;
import java.util.Collections;
//import java.util.Comparator;
import java.util.Random;
   
    
    public class ArrayListExample{
      
        public static void main(String args[]){
      
            // constructs a new empty ArrayList   
            ArrayList<Integer> arrayList = new ArrayList<Integer>();
          
        
          
            arrayList.add(new Integer(1)); //adding value to ArrayList
            arrayList.add(new Integer(1));
            arrayList.add(new Integer(2));
            arrayList.add(new Integer(18));
            arrayList.add(new Integer(34));
            arrayList.add(new Integer(232));
            arrayList.add(new Integer(34));
            arrayList.add(new Integer(13));
            arrayList.add(new Integer(13));
            arrayList.add(new Integer(5));
            arrayList.add(new Integer(5));
           
            System.out.println("ArrayList contains " + arrayList.size() + " elements.");
           //sorting the arraylist.
           for(int i=0;i<arrayList.size();i++)
          System.out.print("  "+arrayList.get(i));
       //    Comparator comparator = Collections.reverseOrder();
     //      Collections.sort(arrayList,comparator);
           System.out.println("\nafter sorting the array:");
           for(int i=0;i<arrayList.size();i++)
               System.out.print("  "+arrayList.get(i));
        int sum=0;
//finding the sum of the arraylist
       for(int i=0;i<arrayList.size();i++)
        {
            sum+=arrayList.get(i);
        }

        System.out.println("\nSum of the list is ="+sum);

//getting the maximum and minimum element from arraylist.
        System.out.println(" minimum element is:"+Collections.min(arrayList));
        System.out.println(" maximum element is:"+Collections.max(arrayList));
        Random r = new Random();
        int h=r.nextInt(10);
        System.out.println(h);
        Collections.sort(arrayList);
        for(int i=0;i<arrayList.size();i++)
            System.out.print("  "+arrayList.get(i));
        }
      }
   
   

Source code of a simple Android application to download stuff.

Here is the source code:

package com.google.android.downloader;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import org.apache.http.impl.client.DefaultHttpClient;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import java.security.MessageDigest;
import android.util.Log;
import android.util.Xml;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

public class DownloaderActivity extends Activity {

    /**
     * Checks if data has been downloaded. If so, returns true. If not,
     * starts an activity to download the data and returns false. If this
     * function returns false the caller should immediately return from its
     * onCreate method. The calling activity will later be restarted
     * (using a copy of its original intent) once the data download completes.
     * @param activity The calling activity.
     * @param customText A text string that is displayed in the downloader UI.
     * @param fileConfigUrl The URL of the download configuration URL.
     * @param configVersion The version of the configuration file.
     * @param dataPath The directory on the device where we want to store the
     * data.
     * @param userAgent The user agent string to use when fetching URLs.
     * @return true if the data has already been downloaded successfully, or
     * false if the data needs to be downloaded.
     */
    public static boolean ensureDownloaded(Activity activity,
            String customText, String fileConfigUrl,
            String configVersion, String dataPath,
            String userAgent) {
        File dest = new File(dataPath);
        if (dest.exists()) {
            // Check version
            if (versionMatches(dest, configVersion)) {
                Log.i(LOG_TAG, "Versions match, no need to download.");
                return true;
            }
        }
        Intent intent = PreconditionActivityHelper.createPreconditionIntent(
                activity, DownloaderActivity.class);
        intent.putExtra(EXTRA_CUSTOM_TEXT, customText);
        intent.putExtra(EXTRA_FILE_CONFIG_URL, fileConfigUrl);
        intent.putExtra(EXTRA_CONFIG_VERSION, configVersion);
        intent.putExtra(EXTRA_DATA_PATH, dataPath);
        intent.putExtra(EXTRA_USER_AGENT, userAgent);
        PreconditionActivityHelper.startPreconditionActivityAndFinish(
                activity, intent);
        return false;
    }

    /**
     * Delete a directory and all its descendants.
     * @param directory The directory to delete
     * @return true if the directory was deleted successfully.
     */
    public static boolean deleteData(String directory) {
        return deleteTree(new File(directory), true);
    }

    private static boolean deleteTree(File base, boolean deleteBase) {
        boolean result = true;
        if (base.isDirectory()) {
            for (File child : base.listFiles()) {
                result &= deleteTree(child, true);
            }
        }
        if (deleteBase) {
            result &= base.delete();
        }
        return result;
    }

    private static boolean versionMatches(File dest, String expectedVersion) {
        Config config = getLocalConfig(dest, LOCAL_CONFIG_FILE);
        if (config != null) {
            return config.version.equals(expectedVersion);
        }
        return false;
    }

    private static Config getLocalConfig(File destPath, String configFilename) {
        File configPath = new File(destPath, configFilename);
        FileInputStream is;
        try {
            is = new FileInputStream(configPath);
        } catch (FileNotFoundException e) {
            return null;
        }
        try {
            Config config = ConfigHandler.parse(is);
            return config;
        } catch (Exception e) {
            Log.e(LOG_TAG, "Unable to read local config file", e);
            return null;
        } finally {
            quietClose(is);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        setContentView(R.layout.downloader);
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
                R.layout.downloader_title);
        ((TextView) findViewById(R.id.customText)).setText(
                intent.getStringExtra(EXTRA_CUSTOM_TEXT));
        mProgress = (TextView) findViewById(R.id.progress);
        mTimeRemaining = (TextView) findViewById(R.id.time_remaining);
        Button button = (Button) findViewById(R.id.cancel);
        button.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                if (mDownloadThread != null) {
                    mSuppressErrorMessages = true;
                    mDownloadThread.interrupt();
                }
            }
        });
        startDownloadThread();
    }

    private void startDownloadThread() {
        mSuppressErrorMessages = false;
        mProgress.setText("");
        mTimeRemaining.setText("");
        mDownloadThread = new Thread(new Downloader(), "Downloader");
        mDownloadThread.setPriority(Thread.NORM_PRIORITY - 1);
        mDownloadThread.start();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mSuppressErrorMessages = true;
        mDownloadThread.interrupt();
        try {
            mDownloadThread.join();
        } catch (InterruptedException e) {
            // Don't care.
        }
    }

    private void onDownloadSucceeded() {
        Log.i(LOG_TAG, "Download succeeded");
        PreconditionActivityHelper.startOriginalActivityAndFinish(this);
    }

    private void onDownloadFailed(String reason) {
        Log.e(LOG_TAG, "Download stopped: " + reason);
        String shortReason;
        int index = reason.indexOf('\n');
        if (index >= 0) {
            shortReason = reason.substring(0, index);
        } else {
            shortReason = reason;
        }
        AlertDialog alert = new Builder(this).create();
        alert.setTitle(R.string.download_activity_download_stopped);

        if (!mSuppressErrorMessages) {
            alert.setMessage(shortReason);
        }

        alert.setButton(getString(R.string.download_activity_retry),
                new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                startDownloadThread();
            }

        });
        alert.setButton2(getString(R.string.download_activity_quit),
                new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }

        });
        try {
            alert.show();
        } catch (WindowManager.BadTokenException e) {
            // Happens when the Back button is used to exit the activity.
            // ignore.
        }
    }

    private void onReportProgress(int progress) {
        mProgress.setText(mPercentFormat.format(progress / 10000.0));
        long now = SystemClock.elapsedRealtime();
        if (mStartTime == 0) {
            mStartTime = now;
        }
        long delta = now - mStartTime;
        String timeRemaining = getString(R.string.download_activity_time_remaining_unknown);
        if ((delta > 3 * MS_PER_SECOND) && (progress > 100)) {
            long totalTime = 10000 * delta / progress;
            long timeLeft = Math.max(0L, totalTime - delta);
            if (timeLeft > MS_PER_DAY) {
                timeRemaining = Long.toString(
                    (timeLeft + MS_PER_DAY - 1) / MS_PER_DAY)
                    + " "
                    + getString(R.string.download_activity_time_remaining_days);
            } else if (timeLeft > MS_PER_HOUR) {
                timeRemaining = Long.toString(
                        (timeLeft + MS_PER_HOUR - 1) / MS_PER_HOUR)
                        + " "
                        + getString(R.string.download_activity_time_remaining_hours);
            } else if (timeLeft > MS_PER_MINUTE) {
                timeRemaining = Long.toString(
                        (timeLeft + MS_PER_MINUTE - 1) / MS_PER_MINUTE)
                        + " "
                        + getString(R.string.download_activity_time_remaining_minutes);
            } else {
                timeRemaining = Long.toString(
                        (timeLeft + MS_PER_SECOND - 1) / MS_PER_SECOND)
                        + " "
                        + getString(R.string.download_activity_time_remaining_seconds);
            }
        }
        mTimeRemaining.setText(timeRemaining);
    }

    private void onReportVerifying() {
        mProgress.setText(getString(R.string.download_activity_verifying));
        mTimeRemaining.setText("");
    }

    private static void quietClose(InputStream is) {
        try {
            if (is != null) {
                is.close();
            }
        } catch (IOException e) {
            // Don't care.
        }
    }

    private static void quietClose(OutputStream os) {
        try {
            if (os != null) {
                os.close();
            }
        } catch (IOException e) {
            // Don't care.
        }
    }

    private static class Config {
        long getSize() {
            long result = 0;
            for(File file : mFiles) {
                result += file.getSize();
            }
            return result;
        }
        static class File {
            public File(String src, String dest, String md5, long size) {
                if (src != null) {
                    this.mParts.add(new Part(src, md5, size));
                }
                this.dest = dest;
            }
            static class Part {
                Part(String src, String md5, long size) {
                    this.src = src;
                    this.md5 = md5;
                    this.size = size;
                }
                String src;
                String md5;
                long size;
            }
            ArrayList<Part> mParts = new ArrayList<Part>();
            String dest;
            long getSize() {
                long result = 0;
                for(Part part : mParts) {
                    if (part.size > 0) {
                        result += part.size;
                    }
                }
                return result;
            }
        }
        String version;
        ArrayList<File> mFiles = new ArrayList<File>();
    }

    /**
     * <config version="">
     *   <file src="http:..." dest ="b.x" />
     *   <file dest="b.x">
     *     <part src="http:..." />
     *     ...
     *   ...
     * </config>
     *
     */
    private static class ConfigHandler extends DefaultHandler {

        public static Config parse(InputStream is) throws SAXException,
            UnsupportedEncodingException, IOException {
            ConfigHandler handler = new ConfigHandler();
            Xml.parse(is, Xml.findEncodingByName("UTF-8"), handler);
            return handler.mConfig;
        }

        private ConfigHandler() {
            mConfig = new Config();
        }

        @Override
        public void startElement(String uri, String localName, String qName,
                Attributes attributes) throws SAXException {
            if (localName.equals("config")) {
                mConfig.version = getRequiredString(attributes, "version");
            } else if (localName.equals("file")) {
                String src = attributes.getValue("", "src");
                String dest = getRequiredString(attributes, "dest");
                String md5 = attributes.getValue("", "md5");
                long size = getLong(attributes, "size", -1);
                mConfig.mFiles.add(new Config.File(src, dest, md5, size));
            } else if (localName.equals("part")) {
                String src = getRequiredString(attributes, "src");
                String md5 = attributes.getValue("", "md5");
                long size = getLong(attributes, "size", -1);
                int length = mConfig.mFiles.size();
                if (length > 0) {
                    mConfig.mFiles.get(length-1).mParts.add(
                            new Config.File.Part(src, md5, size));
                }
            }
        }

        private static String getRequiredString(Attributes attributes,
                String localName) throws SAXException {
            String result = attributes.getValue("", localName);
            if (result == null) {
                throw new SAXException("Expected attribute " + localName);
            }
            return result;
        }

        private static long getLong(Attributes attributes, String localName,
                long defaultValue) {
            String value = attributes.getValue("", localName);
            if (value == null) {
                return defaultValue;
            } else {
                return Long.parseLong(value);
            }
        }

        public Config mConfig;
    }

    private class DownloaderException extends Exception {
        public DownloaderException(String reason) {
            super(reason);
        }
    }

    private class Downloader implements Runnable {
        public void run() {
            Intent intent = getIntent();
            mFileConfigUrl = intent.getStringExtra(EXTRA_FILE_CONFIG_URL);
            mConfigVersion = intent.getStringExtra(EXTRA_CONFIG_VERSION);
            mDataPath = intent.getStringExtra(EXTRA_DATA_PATH);
            mUserAgent = intent.getStringExtra(EXTRA_USER_AGENT);

            mDataDir = new File(mDataPath);

            try {
                // Download files.
                mHttpClient = new DefaultHttpClient();
                Config config = getConfig();
                filter(config);
                persistantDownload(config);
                verify(config);
                cleanup();
                reportSuccess();
            } catch (Exception e) {
                reportFailure(e.toString() + "\n" + Log.getStackTraceString(e));
            }
        }

        private void persistantDownload(Config config)
        throws ClientProtocolException, DownloaderException, IOException {
            while(true) {
                try {
                    download(config);
                    break;
                } catch(java.net.SocketException e) {
                    if (mSuppressErrorMessages) {
                        throw e;
                    }
                } catch(java.net.SocketTimeoutException e) {
                    if (mSuppressErrorMessages) {
                        throw e;
                    }
                }
                Log.i(LOG_TAG, "Network connectivity issue, retrying.");
            }
        }

        private void filter(Config config)
        throws IOException, DownloaderException {
            File filteredFile = new File(mDataDir, LOCAL_FILTERED_FILE);
            if (filteredFile.exists()) {
                return;
            }

            File localConfigFile = new File(mDataDir, LOCAL_CONFIG_FILE_TEMP);
            HashSet<String> keepSet = new HashSet<String>();
            keepSet.add(localConfigFile.getCanonicalPath());

            HashMap<String, Config.File> fileMap =
                new HashMap<String, Config.File>();
            for(Config.File file : config.mFiles) {
                String canonicalPath =
                    new File(mDataDir, file.dest).getCanonicalPath();
                fileMap.put(canonicalPath, file);
            }
            recursiveFilter(mDataDir, fileMap, keepSet, false);
            touch(filteredFile);
        }

        private void touch(File file) throws FileNotFoundException {
            FileOutputStream os = new FileOutputStream(file);
            quietClose(os);
        }

        private boolean recursiveFilter(File base,
                HashMap<String, Config.File> fileMap,
                HashSet<String> keepSet, boolean filterBase)
        throws IOException, DownloaderException {
            boolean result = true;
            if (base.isDirectory()) {
                for (File child : base.listFiles()) {
                    result &= recursiveFilter(child, fileMap, keepSet, true);
                }
            }
            if (filterBase) {
                if (base.isDirectory()) {
                    if (base.listFiles().length == 0) {
                        result &= base.delete();
                    }
                } else {
                    if (!shouldKeepFile(base, fileMap, keepSet)) {
                        result &= base.delete();
                    }
                }
            }
            return result;
        }

        private boolean shouldKeepFile(File file,
                HashMap<String, Config.File> fileMap,
                HashSet<String> keepSet)
        throws IOException, DownloaderException {
            String canonicalPath = file.getCanonicalPath();
            if (keepSet.contains(canonicalPath)) {
                return true;
            }
            Config.File configFile = fileMap.get(canonicalPath);
            if (configFile == null) {
                return false;
            }
            return verifyFile(configFile, false);
        }

        private void reportSuccess() {
            mHandler.sendMessage(
                    Message.obtain(mHandler, MSG_DOWNLOAD_SUCCEEDED));
        }

        private void reportFailure(String reason) {
            mHandler.sendMessage(
                    Message.obtain(mHandler, MSG_DOWNLOAD_FAILED, reason));
        }

        private void reportProgress(int progress) {
            mHandler.sendMessage(
                    Message.obtain(mHandler, MSG_REPORT_PROGRESS, progress, 0));
        }

        private void reportVerifying() {
            mHandler.sendMessage(
                    Message.obtain(mHandler, MSG_REPORT_VERIFYING));
        }

        private Config getConfig() throws DownloaderException,
            ClientProtocolException, IOException, SAXException {
            Config config = null;
            if (mDataDir.exists()) {
                config = getLocalConfig(mDataDir, LOCAL_CONFIG_FILE_TEMP);
                if ((config == null)
                        || !mConfigVersion.equals(config.version)) {
                    if (config == null) {
                        Log.i(LOG_TAG, "Couldn't find local config.");
                    } else {
                        Log.i(LOG_TAG, "Local version out of sync. Wanted " +
                                mConfigVersion + " but have " + config.version);
                    }
                    config = null;
                }
            } else {
                Log.i(LOG_TAG, "Creating directory " + mDataPath);
                mDataDir.mkdirs();
                mDataDir.mkdir();
                if (!mDataDir.exists()) {
                    throw new DownloaderException(
                            "Could not create the directory " + mDataPath);
                }
            }
            if (config == null) {
                File localConfig = download(mFileConfigUrl,
                        LOCAL_CONFIG_FILE_TEMP);
                InputStream is = new FileInputStream(localConfig);
                try {
                    config = ConfigHandler.parse(is);
                } finally {
                    quietClose(is);
                }
                if (! config.version.equals(mConfigVersion)) {
                    throw new DownloaderException(
                            "Configuration file version mismatch. Expected " +
                            mConfigVersion + " received " +
                            config.version);
                }
            }
            return config;
        }

        private void noisyDelete(File file) throws IOException {
            if (! file.delete() ) {
                throw new IOException("could not delete " + file);
            }
        }

        private void download(Config config) throws DownloaderException,
            ClientProtocolException, IOException {
            mDownloadedSize = 0;
            getSizes(config);
            Log.i(LOG_TAG, "Total bytes to download: "
                    + mTotalExpectedSize);
            for(Config.File file : config.mFiles) {
                downloadFile(file);
            }
        }

        private void downloadFile(Config.File file) throws DownloaderException,
                FileNotFoundException, IOException, ClientProtocolException {
            boolean append = false;
            File dest = new File(mDataDir, file.dest);
            long bytesToSkip = 0;
            if (dest.exists() && dest.isFile()) {
                append = true;
                bytesToSkip = dest.length();
                mDownloadedSize += bytesToSkip;
            }
            FileOutputStream os = null;
            long offsetOfCurrentPart = 0;
            try {
                for(Config.File.Part part : file.mParts) {
                    // The part.size==0 check below allows us to download
                    // zero-length files.
                    if ((part.size > bytesToSkip) || (part.size == 0)) {
                        MessageDigest digest = null;
                        if (part.md5 != null) {
                            digest = createDigest();
                            if (bytesToSkip > 0) {
                                FileInputStream is = openInput(file.dest);
                                try {
                                    is.skip(offsetOfCurrentPart);
                                    readIntoDigest(is, bytesToSkip, digest);
                                } finally {
                                    quietClose(is);
                                }
                            }
                        }
                        if (os == null) {
                            os = openOutput(file.dest, append);
                        }
                        downloadPart(part.src, os, bytesToSkip,
                                part.size, digest);
                        if (digest != null) {
                            String hash = getHash(digest);
                            if (!hash.equalsIgnoreCase(part.md5)) {
                                Log.e(LOG_TAG, "web MD5 checksums don't match. "
                                        + part.src + "\nExpected "
                                        + part.md5 + "\n     got " + hash);
                                quietClose(os);
                                dest.delete();
                                throw new DownloaderException(
                                      "Received bad data from web server");
                            } else {
                               Log.i(LOG_TAG, "web MD5 checksum matches.");
                            }
                        }
                    }
                    bytesToSkip -= Math.min(bytesToSkip, part.size);
                    offsetOfCurrentPart += part.size;
                }
            } finally {
                quietClose(os);
            }
        }

        private void cleanup() throws IOException {
            File filtered = new File(mDataDir, LOCAL_FILTERED_FILE);
            noisyDelete(filtered);
            File tempConfig = new File(mDataDir, LOCAL_CONFIG_FILE_TEMP);
            File realConfig = new File(mDataDir, LOCAL_CONFIG_FILE);
            tempConfig.renameTo(realConfig);
        }

        private void verify(Config config) throws DownloaderException,
        ClientProtocolException, IOException {
            Log.i(LOG_TAG, "Verifying...");
            String failFiles = null;
            for(Config.File file : config.mFiles) {
                if (! verifyFile(file, true) ) {
                    if (failFiles == null) {
                        failFiles = file.dest;
                    } else {
                        failFiles += " " + file.dest;
                    }
                }
            }
            if (failFiles != null) {
                throw new DownloaderException(
                        "Possible bad SD-Card. MD5 sum incorrect for file(s) "
                        + failFiles);
            }
        }

        private boolean verifyFile(Config.File file, boolean deleteInvalid)
                throws FileNotFoundException, DownloaderException, IOException {
            Log.i(LOG_TAG, "verifying " + file.dest);
            reportVerifying();
            File dest = new File(mDataDir, file.dest);
            if (! dest.exists()) {
                Log.e(LOG_TAG, "File does not exist: " + dest.toString());
                return false;
            }
            long fileSize = file.getSize();
            long destLength = dest.length();
            if (fileSize != destLength) {
                Log.e(LOG_TAG, "Length doesn't match. Expected " + fileSize
                        + " got " + destLength);
                if (deleteInvalid) {
                    dest.delete();
                    return false;
                }
            }
            FileInputStream is = new FileInputStream(dest);
            try {
                for(Config.File.Part part : file.mParts) {
                    if (part.md5 == null) {
                        continue;
                    }
                    MessageDigest digest = createDigest();
                    readIntoDigest(is, part.size, digest);
                    String hash = getHash(digest);
                    if (!hash.equalsIgnoreCase(part.md5)) {
                        Log.e(LOG_TAG, "MD5 checksums don't match. " +
                                part.src + " Expected "
                                + part.md5 + " got " + hash);
                        if (deleteInvalid) {
                            quietClose(is);
                            dest.delete();
                        }
                        return false;
                    }
                }
            } finally {
                quietClose(is);
            }
            return true;
        }

        private void readIntoDigest(FileInputStream is, long bytesToRead,
                MessageDigest digest) throws IOException {
            while(bytesToRead > 0) {
                int chunkSize = (int) Math.min(mFileIOBuffer.length,
                        bytesToRead);
                int bytesRead = is.read(mFileIOBuffer, 0, chunkSize);
                if (bytesRead < 0) {
                    break;
                }
                updateDigest(digest, bytesRead);
                bytesToRead -= bytesRead;
            }
        }

        private MessageDigest createDigest() throws DownloaderException {
            MessageDigest digest;
            try {
                digest = MessageDigest.getInstance("MD5");
            } catch (NoSuchAlgorithmException e) {
                throw new DownloaderException("Couldn't create MD5 digest");
            }
            return digest;
        }

        private void updateDigest(MessageDigest digest, int bytesRead) {
            if (bytesRead == mFileIOBuffer.length) {
                digest.update(mFileIOBuffer);
            } else {
                // Work around an awkward API: Create a
                // new buffer with just the valid bytes
                byte[] temp = new byte[bytesRead];
                System.arraycopy(mFileIOBuffer, 0,
                        temp, 0, bytesRead);
                digest.update(temp);
            }
        }

        private String getHash(MessageDigest digest) {
            StringBuilder builder = new StringBuilder();
            for(byte b : digest.digest()) {
                builder.append(Integer.toHexString((b >> 4) & 0xf));
                builder.append(Integer.toHexString(b & 0xf));
            }
            return builder.toString();
        }


        /**
         * Ensure we have sizes for all the items.
         * @param config
         * @throws ClientProtocolException
         * @throws IOException
         * @throws DownloaderException
         */
        private void getSizes(Config config)
            throws ClientProtocolException, IOException, DownloaderException {
            for (Config.File file : config.mFiles) {
                for(Config.File.Part part : file.mParts) {
                    if (part.size < 0) {
                        part.size = getSize(part.src);
                    }
                }
            }
            mTotalExpectedSize = config.getSize();
        }

        private long getSize(String url) throws ClientProtocolException,
            IOException {
            url = normalizeUrl(url);
            Log.i(LOG_TAG, "Head " + url);
            HttpHead httpGet = new HttpHead(url);
            HttpResponse response = mHttpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                throw new IOException("Unexpected Http status code "
                    + response.getStatusLine().getStatusCode());
            }
            Header[] clHeaders = response.getHeaders("Content-Length");
            if (clHeaders.length > 0) {
                Header header = clHeaders[0];
                return Long.parseLong(header.getValue());
            }
            return -1;
        }

        private String normalizeUrl(String url) throws MalformedURLException {
            return (new URL(new URL(mFileConfigUrl), url)).toString();
        }

        private InputStream get(String url, long startOffset,
                long expectedLength)
            throws ClientProtocolException, IOException {
            url = normalizeUrl(url);
            Log.i(LOG_TAG, "Get " + url);

            mHttpGet = new HttpGet(url);
            int expectedStatusCode = HttpStatus.SC_OK;
            if (startOffset > 0) {
                String range = "bytes=" + startOffset + "-";
                if (expectedLength >= 0) {
                    range += expectedLength-1;
                }
                Log.i(LOG_TAG, "requesting byte range " + range);
                mHttpGet.addHeader("Range", range);
                expectedStatusCode = HttpStatus.SC_PARTIAL_CONTENT;
            }
            HttpResponse response = mHttpClient.execute(mHttpGet);
            long bytesToSkip = 0;
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != expectedStatusCode) {
                if ((statusCode == HttpStatus.SC_OK)
                        && (expectedStatusCode
                                == HttpStatus.SC_PARTIAL_CONTENT)) {
                    Log.i(LOG_TAG, "Byte range request ignored");
                    bytesToSkip = startOffset;
                } else {
                    throw new IOException("Unexpected Http status code "
                            + statusCode + " expected "
                            + expectedStatusCode);
                }
            }
            HttpEntity entity = response.getEntity();
            InputStream is = entity.getContent();
            if (bytesToSkip > 0) {
                is.skip(bytesToSkip);
            }
            return is;
        }

        private File download(String src, String dest)
            throws DownloaderException, ClientProtocolException, IOException {
            File destFile = new File(mDataDir, dest);
            FileOutputStream os = openOutput(dest, false);
            try {
                downloadPart(src, os, 0, -1, null);
            } finally {
                os.close();
            }
            return destFile;
        }

        private void downloadPart(String src, FileOutputStream os,
                long startOffset, long expectedLength, MessageDigest digest)
            throws ClientProtocolException, IOException, DownloaderException {
            boolean lengthIsKnown = expectedLength >= 0;
            if (startOffset < 0) {
                throw new IllegalArgumentException("Negative startOffset:"
                        + startOffset);
            }
            if (lengthIsKnown && (startOffset > expectedLength)) {
                throw new IllegalArgumentException(
                        "startOffset > expectedLength" + startOffset + " "
                        + expectedLength);
            }
            InputStream is = get(src, startOffset, expectedLength);
            try {
                long bytesRead = downloadStream(is, os, digest);
                if (lengthIsKnown) {
                    long expectedBytesRead = expectedLength - startOffset;
                    if (expectedBytesRead != bytesRead) {
                        Log.e(LOG_TAG, "Bad file transfer from server: " + src
                                + " Expected " + expectedBytesRead
                                + " Received " + bytesRead);
                        throw new DownloaderException(
                                "Incorrect number of bytes received from server");
                    }
                }
            } finally {
                is.close();
                mHttpGet = null;
            }
        }

        private FileOutputStream openOutput(String dest, boolean append)
            throws FileNotFoundException, DownloaderException {
            File destFile = new File(mDataDir, dest);
            File parent = destFile.getParentFile();
            if (! parent.exists()) {
                parent.mkdirs();
            }
            if (! parent.exists()) {
                throw new DownloaderException("Could not create directory "
                        + parent.toString());
            }
            FileOutputStream os = new FileOutputStream(destFile, append);
            return os;
        }

        private FileInputStream openInput(String src)
            throws FileNotFoundException, DownloaderException {
            File srcFile = new File(mDataDir, src);
            File parent = srcFile.getParentFile();
            if (! parent.exists()) {
                parent.mkdirs();
            }
            if (! parent.exists()) {
                throw new DownloaderException("Could not create directory "
                        + parent.toString());
            }
            return new FileInputStream(srcFile);
        }

        private long downloadStream(InputStream is, FileOutputStream os,
                MessageDigest digest)
                throws DownloaderException, IOException {
            long totalBytesRead = 0;
            while(true){
                if (Thread.interrupted()) {
                    Log.i(LOG_TAG, "downloader thread interrupted.");
                    mHttpGet.abort();
                    throw new DownloaderException("Thread interrupted");
                }
                int bytesRead = is.read(mFileIOBuffer);
                if (bytesRead < 0) {
                    break;
                }
                if (digest != null) {
                    updateDigest(digest, bytesRead);
                }
                totalBytesRead += bytesRead;
                os.write(mFileIOBuffer, 0, bytesRead);
                mDownloadedSize += bytesRead;
                int progress = (int) (Math.min(mTotalExpectedSize,
                        mDownloadedSize * 10000 /
                        Math.max(1, mTotalExpectedSize)));
                if (progress != mReportedProgress) {
                    mReportedProgress = progress;
                    reportProgress(progress);
                }
            }
            return totalBytesRead;
        }

        private DefaultHttpClient mHttpClient;
        private HttpGet mHttpGet;
        private String mFileConfigUrl;
        private String mConfigVersion;
        private String mDataPath;
        private File mDataDir;
        private String mUserAgent;
        private long mTotalExpectedSize;
        private long mDownloadedSize;
        private int mReportedProgress;
        private final static int CHUNK_SIZE = 32 * 1024;
        byte[] mFileIOBuffer = new byte[CHUNK_SIZE];
    }

    private final static String LOG_TAG = "Downloader";
    private TextView mProgress;
    private TextView mTimeRemaining;
    private final DecimalFormat mPercentFormat = new DecimalFormat("0.00 %");
    private long mStartTime;
    private Thread mDownloadThread;
    private boolean mSuppressErrorMessages;

    private final static long MS_PER_SECOND = 1000;
    private final static long MS_PER_MINUTE = 60 * 1000;
    private final static long MS_PER_HOUR = 60 * 60 * 1000;
    private final static long MS_PER_DAY = 24 * 60 * 60 * 1000;

    private final static String LOCAL_CONFIG_FILE = ".downloadConfig";
    private final static String LOCAL_CONFIG_FILE_TEMP = ".downloadConfig_temp";
    private final static String LOCAL_FILTERED_FILE = ".downloadConfig_filtered";
    private final static String EXTRA_CUSTOM_TEXT = "DownloaderActivity_custom_text";
    private final static String EXTRA_FILE_CONFIG_URL = "DownloaderActivity_config_url";
    private final static String EXTRA_CONFIG_VERSION = "DownloaderActivity_config_version";
    private final static String EXTRA_DATA_PATH = "DownloaderActivity_data_path";
    private final static String EXTRA_USER_AGENT = "DownloaderActivity_user_agent";

    private final static int MSG_DOWNLOAD_SUCCEEDED = 0;
    private final static int MSG_DOWNLOAD_FAILED = 1;
    private final static int MSG_REPORT_PROGRESS = 2;
    private final static int MSG_REPORT_VERIFYING = 3;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_DOWNLOAD_SUCCEEDED:
                onDownloadSucceeded();
                break;
            case MSG_DOWNLOAD_FAILED:
                onDownloadFailed((String) msg.obj);
                break;
            case MSG_REPORT_PROGRESS:
                onReportProgress(msg.arg1);
                break;
            case MSG_REPORT_VERIFYING:
                onReportVerifying();
                break;
            default:
                throw new IllegalArgumentException("Unknown message id "
                        + msg.what);
            }
        }

    };

}

Any comment: