Android: fixed serviceconnectionleak, made the result code of asynctask a bit better, fix cancel button
authorXeli
Sat, 26 Nov 2011 17:40:25 +0100
changeset 6437 4ed58839b13b
parent 6436 f1a42ba9cab2
child 6439 cb7d84d3ebb4
Android: fixed serviceconnectionleak, made the result code of asynctask a bit better, fix cancel button
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java	Sat Nov 26 16:18:44 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java	Sat Nov 26 17:40:25 2011 +0100
@@ -41,12 +41,19 @@
  * @author Xeli
  *
  */
-public class DownloadAsyncTask extends AsyncTask<DownloadPackage, Object, Long> {
+public class DownloadAsyncTask extends AsyncTask<DownloadPackage, Object, Integer> {
 
 	//private final static String URL_WITHOUT_SUFFIX = "http://www.xelification.com/tmp/firebutton.";
 	private final static String URL_ZIP_SUFFIX = ".zip";
 	private final static String URL_HASH_SUFFIX = ".hash";
-	
+
+	public static final int EXIT_SUCCESS = 0;
+	public static final int EXIT_URLFAIL = 1;
+	public static final int EXIT_CONNERROR = 2;
+	public static final int EXIT_FNF = 3;
+	public static final int EXIT_MD5 = 4;
+	public static final int EXIT_CANCELLED = 5;
+
 	private DownloadTask task;
 	private long lastUpdateMillis = 0;
 
@@ -58,9 +65,9 @@
 	 * 
 	 * @param params - A {@link}DownloadTask which gives information about where to download from and store the files to 
 	 */
-	protected Long doInBackground(DownloadPackage...packages) {
+	protected Integer doInBackground(DownloadPackage...packages) {
 		DownloadPackage pack = packages[0];//just use one task per execute call for now
-		
+
 		HttpURLConnection conn = null;
 		MessageDigest digester = null;
 		String rootZipDest = pack.getPathToStore();
@@ -73,7 +80,7 @@
 			conn = (HttpURLConnection)url.openConnection();
 		} catch (IOException e) {
 			e.printStackTrace();
-			return -1l;
+			return EXIT_URLFAIL;
 		}
 
 		String contentType = conn.getContentType();
@@ -82,6 +89,7 @@
 			int bytesDecompressed = 0;
 			ZipEntry entry = null;
 			ZipInputStream input = null;
+			FileOutputStream output = null;
 			int kbytesToProcess = conn.getContentLength()/1024;
 
 			byte[] buffer = new byte[1024];
@@ -100,25 +108,26 @@
 			}catch(IOException e){
 				e.printStackTrace();
 				if(conn != null) conn.disconnect();
-				return -2l;
+				return EXIT_CONNERROR;
 			}
 
+
+
 			while(entry != null){
+
 				if(isCancelled()) break;
 
-				String fileName = entry.getName();
-				File f = new File(rootZipDest + fileName);
-				bytesDecompressed += entry.getCompressedSize();
+				try {
+					String fileName = entry.getName();
+					File f = new File(rootZipDest + fileName);
+					bytesDecompressed += entry.getCompressedSize();
 
-				if(entry.isDirectory()){
-					f.mkdir();
-				}else{
-					if(f.exists()){
-						f.delete();
-					}
-
-					FileOutputStream output = null;
-					try {
+					if(entry.isDirectory()){
+						f.mkdir();
+					}else{
+						if(f.exists()){
+							f.delete();
+						}
 						f.createNewFile();
 						output = new FileOutputStream(f);
 
@@ -133,49 +142,48 @@
 						}
 						output.flush();
 						input.closeEntry();
-					} catch (FileNotFoundException e) {
-						e.printStackTrace();
-						if(conn != null) conn.disconnect();
-						return -3l;
-					} catch (IOException e) {
-						e.printStackTrace();
-						if(conn != null) conn.disconnect();
-						return -4l;
-					}finally{
-						try {
-							if( output != null) output.close();
-						} catch (IOException e) {}
-					}
-				}
-				try{
+					}//if isDir 
 					entry = input.getNextEntry();
-				}catch(IOException e){
+				} catch (FileNotFoundException e) {
+					e.printStackTrace();
+					if(conn != null) conn.disconnect();
+					return EXIT_FNF;
+				} catch (IOException e) {
 					e.printStackTrace();
 					if(conn != null) conn.disconnect();
-					return -1l;
+					return EXIT_CONNERROR;
+				}finally{
+					try {
+						if( output != null) output.close();
+
+					} catch (IOException e) {}
 				}
 			}//end while(entry != null)
-
-			try {
-				input.close();
-			} catch (IOException e) {}
+			if( input != null)
+				try {
+					input.close();
+				} catch (IOException e) {}
 		}//end if contentType == "zip"
 
 		if(conn != null) conn.disconnect();
 
-		if(checkMD5(digester, pack))return 0l;
-		else return -1l;
+		if(checkMD5(digester, pack))return EXIT_SUCCESS;
+		else return EXIT_MD5;
 	}
 
 	//TODO proper result handling
-	protected void onPostExecute(Long result){
-		task.done(result > -1l);
+	protected void onPostExecute(Integer result){
+		task.done(result);
 	}
 
 	protected void onProgressUpdate(Object...objects){
 		task.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]);
 	}
 
+	protected void onCancelled(){
+		onPostExecute(EXIT_CANCELLED);
+	}
+
 	private boolean checkMD5(MessageDigest digester, DownloadPackage task){
 		if(digester != null) {
 			byte[] messageDigest = digester.digest();
@@ -197,16 +205,16 @@
 						sb.append(Integer.toHexString(tmp));
 					}
 					sb.append('\n');//add newline to become identical with the hash file
-					
+
 					return hash.equals(sb.toString());
 				}
 				return false;
 			} catch (IOException e) {
 				e.printStackTrace();
-				return false;
+				return true;
 			}
 		}else{
-			return false;	
+			return true;	
 		}
 
 	}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java	Sat Nov 26 16:18:44 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadFragment.java	Sat Nov 26 17:40:25 2011 +0100
@@ -32,6 +32,7 @@
 import android.os.Messenger;
 import android.os.RemoteException;
 import android.support.v4.app.Fragment;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -63,22 +64,22 @@
 		DownloadFragment df = new DownloadFragment();
 		Bundle args = new Bundle();
 		args.putParcelable(DownloadFragment.EXTRA_TASK, task);
-		
+
 		df.setArguments(args);
-		
+
 		return df;
 	}
-	
+
 	public void onActivityCreated(Bundle savedInstanceState){
 		super.onActivityCreated(savedInstanceState);
-		
+
 		messageHandler = new Handler(messageCallback);
 		messenger = new Messenger(messageHandler);
-		 Intent i = new Intent(getActivity(), DownloadService.class);
-         getActivity().startService(i);
-         getActivity().bindService(new Intent(getActivity(), DownloadService.class), connection, Context.BIND_AUTO_CREATE);
+		Intent i = new Intent(getActivity().getApplicationContext(), DownloadService.class);
+		getActivity().startService(i);
+		getActivity().bindService(new Intent(getActivity().getApplicationContext(), DownloadService.class), connection, Context.BIND_AUTO_CREATE);
 	}
-	
+
 	public View onCreateView(LayoutInflater inflater, ViewGroup viewgroup, Bundle savedInstanceState){
 		View v = inflater.inflate(R.layout.download_progress, viewgroup, false);
 		progress_sub = (TextView)v.findViewById(R.id.progressbar_sub);
@@ -101,7 +102,7 @@
 	};
 	private OnClickListener cancelClicker = new OnClickListener(){
 		public void onClick(View v){
-			if(messenger != null){
+			if(messengerService != null){
 				Message message = Message.obtain(messageHandler, DownloadService.MSG_CANCEL, pack);
 				try {
 					messengerService.send(message);
@@ -118,7 +119,7 @@
 
 	private OnClickListener tryAgainClicker = new OnClickListener(){
 		public void onClick(View v){
-			if(messenger != null){
+			if(messengerService != null){
 				Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack);
 				message.replyTo = messenger;
 				try {
@@ -130,9 +131,9 @@
 		}
 	};
 
-	public void onStop(){
-		super.onStop();
+	public void onDestroy(){
 		unBindFromService();
+		super.onDestroy();
 	}
 
 	private ServiceConnection connection = new ServiceConnection(){
@@ -142,7 +143,7 @@
 
 			try{
 				//give the service a task
-				if(messenger != null){
+				if(messengerService != null){
 					Message message = Message.obtain(messageHandler, DownloadService.MSG_ADDTASK, pack);
 					message.replyTo = messenger;
 					messengerService.send(message);
@@ -157,21 +158,18 @@
 
 	};
 
-	private void unBindFromService(){
-		if(boundToService){
-			if(messenger != null){
-				try {
-					Message message = Message.obtain(messageHandler, DownloadService.MSG_UNREGISTER_CLIENT, pack);
-					message.replyTo = messenger;
-					messengerService.send(message);
-				} catch (RemoteException e) {
-					e.printStackTrace();
-				}
+	public void unBindFromService(){
+		if(messengerService != null){
+			try {
+				Message message = Message.obtain(messageHandler, DownloadService.MSG_UNREGISTER_CLIENT, pack);
+				message.replyTo = messenger;
+				messengerService.send(message);
+			} catch (RemoteException e) {
+				e.printStackTrace();
 			}
-			
-			boundToService = false;
-			getActivity().unbindService(connection);
-		}	
+		}
+
+		getActivity().unbindService(connection);
 	}
 
 	private Handler.Callback messageCallback = new Handler.Callback() {
@@ -194,16 +192,16 @@
 				progress.setProgress(progress.getMax());
 				progress_sub.setText(R.string.download_done);
 
-			//	positive.setText(R.string.download_back);
-			//	positive.setOnClickListener(doneClicker);
+				//	positive.setText(R.string.download_back);
+				//	positive.setOnClickListener(doneClicker);
 
 				negative.setVisibility(View.INVISIBLE);
 				break;
 			case MSG_FAILED:
 				progress.setProgress(progress.getMax());
 				progress_sub.setText(R.string.download_failed);
-			//	positive.setText(R.string.download_back);
-			//	positive.setOnClickListener(doneClicker);
+				//	positive.setText(R.string.download_back);
+				//	positive.setOnClickListener(doneClicker);
 
 				negative.setText(R.string.download_tryagain);
 				negative.setOnClickListener(tryAgainClicker);
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java	Sat Nov 26 16:18:44 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java	Sat Nov 26 17:40:25 2011 +0100
@@ -6,6 +6,7 @@
 import android.support.v4.app.FragmentActivity;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
+import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -37,6 +38,11 @@
 		downloadQueueContainer = (LinearLayout) findViewById(R.id.downloadQueueContainer);
 	}
 
+	public void onDestroy(){
+		super.onDestroy();
+		Log.d("tag", "on destroy");
+	}
+	
 	public void onNewItemSelected(DownloadPackage _task, int x, int minX, int maxX, int size) {
 		if(layout != null){
 			if(!_task.equals(task)){//if it's a new task refresh the whole thing
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java	Sat Nov 26 16:18:44 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java	Sat Nov 26 17:40:25 2011 +0100
@@ -19,12 +19,10 @@
 
 package org.hedgewars.hedgeroid.Downloader;
 
-import java.util.ArrayList;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.hedgewars.hedgeroid.MainActivity;
 import org.hedgewars.hedgeroid.R;
 
 import android.app.Notification;
@@ -32,7 +30,6 @@
 import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
-import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -61,6 +58,7 @@
 	private RemoteViews contentView;
 
 	private Deque<DownloadTask> downloadTasks = new LinkedList<DownloadTask>();
+	private DownloadTask currentTask = null;
 
 	public class DownloadHandler extends Handler{
 
@@ -87,7 +85,10 @@
 					runNextTask();
 					return;
 				case MSG_CANCEL:
-					if(task != null && task.getPackage().equals(pack) && task.getStatus() == TASK_STATE.RUNNING){
+					if(task != null && task.getPackage().equals(pack) && task.getStatus() == TASK_STATE.PENDING){
+						downloadTasks.remove(task);
+					}
+					if(currentTask.getPackage().equals(pack)){
 						asyncExecutor.cancel(false);
 					}
 					return;
@@ -111,10 +112,10 @@
 
 	private void runNextTask(){
 		if(asyncExecutor == null){//if (task isnt running right now) ...
-			DownloadTask task = downloadTasks.pollFirst();
-			if(task != null){
-				asyncExecutor = new DownloadAsyncTask(task);
-				asyncExecutor.execute(task.getPackage());
+			currentTask = downloadTasks.pollFirst();
+			if(currentTask != null){
+				asyncExecutor = new DownloadAsyncTask(currentTask);
+				asyncExecutor.execute(currentTask.getPackage());
 			}
 		}
 	}
@@ -178,7 +179,7 @@
 			PendingIntent contentIntent = PendingIntent.getActivity(DownloadService.this, 0, new Intent(DownloadService.this, DownloadFragment.class), Intent.FLAG_ACTIVITY_NEW_TASK);
 			progressNotification.contentIntent = contentIntent;
 
-			startForeground(NOTIFICATION_PROCESSING, progressNotification);//TODO werkt het?
+			startForeground(NOTIFICATION_PROCESSING, progressNotification);
 
 			Message msg = Message.obtain(null, DownloadFragment.MSG_START, max, 0);
 			sendMessageToClients(msg);
@@ -196,10 +197,18 @@
 		}
 
 		//Call back from the ASync task when the task has either run into an error or finished otherwise
-		public void done(boolean succesful){
-			if(succesful){
-				sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE));
-			}else sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED));
+		public void done(int result){
+			switch(result){
+			case DownloadAsyncTask.EXIT_SUCCESS: 	sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break;
+			case DownloadAsyncTask.EXIT_CONNERROR:  sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED)); break;
+			case DownloadAsyncTask.EXIT_FNF:		sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED)); break;
+			case DownloadAsyncTask.EXIT_MD5:		sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED)); break;
+			case DownloadAsyncTask.EXIT_URLFAIL:	sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_FAILED)); break;
+			case DownloadAsyncTask.EXIT_CANCELLED:	sendMessageToClients(Message.obtain(handler, DownloadFragment.MSG_DONE)); break;
+				
+				
+			}
+			
 			stopForeground(true);
 			nM.cancel(NOTIFICATION_PROCESSING);