project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadAsyncTask.java
branchhedgeroid
changeset 6047 10011f051f9c
parent 6045 9a7cc0f29430
child 6049 7bc38086d771
equal deleted inserted replaced
6045:9a7cc0f29430 6047:10011f051f9c
     1 /*
       
     2  * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
       
     3  * Copyright (c) 2011 Richard Deurwaarder <xeli@xelification.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
       
    17  */
       
    18 
       
    19 
       
    20 package org.hedgewars.mobile.Downloader;
       
    21 
       
    22 import java.io.BufferedInputStream;
       
    23 import java.io.File;
       
    24 import java.io.FileNotFoundException;
       
    25 import java.io.FileOutputStream;
       
    26 import java.io.IOException;
       
    27 import java.net.HttpURLConnection;
       
    28 import java.net.URL;
       
    29 import java.security.MessageDigest;
       
    30 import java.security.NoSuchAlgorithmException;
       
    31 import java.util.zip.ZipEntry;
       
    32 import java.util.zip.ZipInputStream;
       
    33 
       
    34 import android.os.AsyncTask;
       
    35 import android.util.Log;
       
    36 /**
       
    37  * This is an AsyncTask which will download a zip from an URL and unzip it to a specified path
       
    38  * 
       
    39  *  a typical call to start the task would be new DownloadAsyncTask().execute(getExternalStorage(), "www.hedgewars.org/data.zip");
       
    40  * @author Xeli
       
    41  *
       
    42  */
       
    43 public class DownloadAsyncTask extends AsyncTask<String, Object, Long> {
       
    44 
       
    45 	private final static String URL_WITHOUT_SUFFIX = "http://hedgewars.googlecode.com/files/data_5631.";
       
    46 	//private final static String URL_WITHOUT_SUFFIX = "http://www.xelification.com/tmp/firebutton.";
       
    47 	private final static String URL_ZIP_SUFFIX = "zip";
       
    48 	private final static String URL_HASH_SUFFIX = "hash";
       
    49 
       
    50 	private DownloadService service;
       
    51 	private long lastUpdateMillis = 0;
       
    52 
       
    53 	public DownloadAsyncTask(DownloadService _service){
       
    54 		service = _service;
       
    55 	}
       
    56 
       
    57 	/**
       
    58 	 * 
       
    59 	 * @param params - 2 Strings, first is the path where the unzipped files will be stored, second is the URL to download from
       
    60 	 */
       
    61 	protected Long doInBackground(String... params) {
       
    62 		HttpURLConnection conn = null;
       
    63 		MessageDigest digester = null;
       
    64 		String rootZipDest = params[0];
       
    65 
       
    66 		File rootDest = new File(rootZipDest);//TODO check for nullpointer, it hints to the absence of an sdcard
       
    67 		rootDest.mkdir();
       
    68 
       
    69 		try {
       
    70 			URL url = new URL(URL_WITHOUT_SUFFIX + URL_ZIP_SUFFIX);
       
    71 			conn = (HttpURLConnection)url.openConnection();
       
    72 		} catch (IOException e) {
       
    73 			e.printStackTrace();
       
    74 			return -1l;
       
    75 		}
       
    76 
       
    77 		String contentType = conn.getContentType();
       
    78 
       
    79 		if(contentType == null || contentType.contains("zip")){ //Seeing as we provide the url if the contentType is unknown lets assume zips
       
    80 			int bytesDecompressed = 0;
       
    81 			ZipEntry entry = null;
       
    82 			ZipInputStream input = null;
       
    83 			int kbytesToProcess = conn.getContentLength()/1024;
       
    84 
       
    85 			byte[] buffer = new byte[1024];
       
    86 			service.start(kbytesToProcess);
       
    87 
       
    88 			try {
       
    89 				digester = MessageDigest.getInstance("MD5");
       
    90 
       
    91 			} catch (NoSuchAlgorithmException e1) {
       
    92 				e1.printStackTrace();
       
    93 			}
       
    94 
       
    95 			try{
       
    96 				input = new ZipInputStream(conn.getInputStream());
       
    97 				entry = input.getNextEntry();	
       
    98 			}catch(IOException e){
       
    99 				e.printStackTrace();
       
   100 				if(conn != null) conn.disconnect();
       
   101 				return -1l;
       
   102 			}
       
   103 
       
   104 			while(entry != null){
       
   105 				if(isCancelled()) break;
       
   106 
       
   107 				String fileName = entry.getName();
       
   108 				File f = new File(rootZipDest + fileName);
       
   109 				bytesDecompressed += entry.getCompressedSize();
       
   110 
       
   111 				if(entry.isDirectory()){
       
   112 					f.mkdir();
       
   113 				}else{
       
   114 					if(f.exists()){
       
   115 						f.delete();
       
   116 					}
       
   117 
       
   118 					FileOutputStream output = null;
       
   119 					try {
       
   120 						f.createNewFile();
       
   121 						output = new FileOutputStream(f);
       
   122 
       
   123 						int count = 0;
       
   124 						while((count = input.read(buffer)) != -1){
       
   125 							output.write(buffer, 0, count);
       
   126 							digester.update(buffer, 0, count);
       
   127 							if(System.currentTimeMillis() - lastUpdateMillis > 1000){
       
   128 								lastUpdateMillis = System.currentTimeMillis();
       
   129 								publishProgress(bytesDecompressed, kbytesToProcess, fileName);
       
   130 							}
       
   131 						}
       
   132 						output.flush();
       
   133 						input.closeEntry();
       
   134 					} catch (FileNotFoundException e) {
       
   135 						e.printStackTrace();
       
   136 						if(conn != null) conn.disconnect();
       
   137 						return -1l;
       
   138 					} catch (IOException e) {
       
   139 						e.printStackTrace();
       
   140 						if(conn != null) conn.disconnect();
       
   141 						return -1l;
       
   142 					}finally{
       
   143 						try {
       
   144 							if( output != null) output.close();
       
   145 						} catch (IOException e) {}
       
   146 					}
       
   147 				}
       
   148 				try{
       
   149 					entry = input.getNextEntry();
       
   150 				}catch(IOException e){
       
   151 					e.printStackTrace();
       
   152 					if(conn != null) conn.disconnect();
       
   153 					return -1l;
       
   154 				}
       
   155 			}//end while(entry != null)
       
   156 
       
   157 			try {
       
   158 				input.close();
       
   159 			} catch (IOException e) {}
       
   160 		}//end if contentType == "zip"
       
   161 
       
   162 		if(conn != null) conn.disconnect();
       
   163 
       
   164 		if(checkMD5(digester))return 0l;
       
   165 		else return -1l;
       
   166 	}
       
   167 
       
   168 	//TODO proper result handling
       
   169 	protected void onPostExecute(Long result){
       
   170 		service.done(result > -1l);
       
   171 	}
       
   172 
       
   173 	protected void onProgressUpdate(Object...objects){
       
   174 		service.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]);
       
   175 	}
       
   176 
       
   177 	private boolean checkMD5(MessageDigest digester){
       
   178 		if(digester != null) {
       
   179 			byte[] messageDigest = digester.digest();
       
   180 
       
   181 			try {
       
   182 				URL url = new URL(URL_WITHOUT_SUFFIX + URL_HASH_SUFFIX);
       
   183 				HttpURLConnection conn = (HttpURLConnection)url.openConnection();
       
   184 
       
   185 				byte[] buffer = new byte[1024];//size is large enough to hold the entire hash
       
   186 				BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
       
   187 				int bytesRead = bis.read(buffer);
       
   188 				if(bytesRead > -1){
       
   189 					String hash = new String(buffer, 0, bytesRead);
       
   190 					StringBuffer sb = new StringBuffer();
       
   191 					Integer tmp = 0;
       
   192 					for(int i = 0; i < messageDigest.length; i++){
       
   193 						tmp = 0xFF & messageDigest[i];
       
   194 						if(tmp < 0xF) sb.append('0');
       
   195 						sb.append(Integer.toHexString(tmp));
       
   196 					}
       
   197 					sb.append('\n');//add newline to become identical with the hash file
       
   198 					
       
   199 					return hash.equals(sb.toString());
       
   200 				}
       
   201 				return false;
       
   202 			} catch (IOException e) {
       
   203 				e.printStackTrace();
       
   204 				return false;
       
   205 			}
       
   206 		}else{
       
   207 			return false;	
       
   208 		}
       
   209 
       
   210 	}
       
   211 
       
   212 }