Moved download classes to their own dir and fixed the way the dest dir is being 'build' hedgeroid
authorXeli
Thu, 14 Jul 2011 15:41:26 +0200
branchhedgeroid
changeset 5412 ab055114c788
parent 5410 8e7787065e2d
child 5414 34663c4743f7
Moved download classes to their own dir and fixed the way the dest dir is being 'build'
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadAsyncTask.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadService.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadThread.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadActivity.java	Thu Jul 14 15:41:26 2011 +0200
@@ -0,0 +1,141 @@
+package org.hedgewars.mobile.Downloader;
+
+import org.hedgewars.mobile.MainActivity;
+import org.hedgewars.mobile.R;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+public class DownloadActivity extends Activity{
+
+	private Messenger messageService;
+	private boolean boundToService = false;
+	
+	private TextView progress_sub;
+	private ProgressBar progress;
+	private Button positive, negative;
+	
+	public static final int MSG_START = 0;
+	public static final int MSG_UPDATE = 1;
+	public static final int MSG_DONE = 2;
+	private Handler.Callback messageCallback = new Handler.Callback() {
+		
+		@Override
+		public boolean handleMessage(Message msg) {
+			switch(msg.what){
+			case MSG_START:
+				progress.setMax(msg.arg1);
+				progress_sub.setText(String.format("%dkb/%dkb\n%s", 0, msg.arg1, ""));
+				break;
+			case MSG_UPDATE:
+				progress_sub.setText(String.format("%d%% - %dkb/%dkb\n%s",(msg.arg1*100)/msg.arg2, msg.arg1, msg.arg2, msg.obj));
+				progress.setProgress(msg.arg1);
+				break;
+			case MSG_DONE:
+				progress.setProgress(progress.getMax());
+				progress_sub.setText(R.string.download_done);
+				
+				positive.setText(R.string.download_back);
+				positive.setOnClickListener(doneClicker);
+				break;
+			}
+			return false;
+		}
+	};
+	private Handler messageHandler = new Handler(messageCallback);
+	private Messenger messenger = new Messenger(messageHandler);
+	
+	public void onCreate(Bundle savedInstanceState){
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.download);
+		
+		progress_sub = (TextView)findViewById(R.id.progressbar_sub);
+		progress = (ProgressBar)findViewById(R.id.progressbar);
+		
+		positive = (Button) findViewById(R.id.background);
+		negative = (Button) findViewById(R.id.cancelDownload);
+		positive.setOnClickListener(backgroundClicker);
+		negative.setOnClickListener(cancelClicker);
+		
+	}
+	
+	private OnClickListener backgroundClicker = new OnClickListener(){
+		public void onClick(View v){
+			finish();
+		}
+	};
+	private OnClickListener cancelClicker = new OnClickListener(){
+		public void onClick(View v){
+			Intent i = new Intent(getApplicationContext(), DownloadService.class);
+			i.putExtra("taskID", DownloadService.TASKID_CANCEL);
+			startService(i);
+			finish();
+		}
+	};
+	private OnClickListener doneClicker = new OnClickListener(){
+		public void onClick(View v){
+			finish();
+			startActivity(new Intent(getApplicationContext(), MainActivity.class));
+		}
+	};
+	
+	public void onStart(){
+		super.onStart();
+		bindToService();
+	}
+	
+	public void onStop(){
+		super.onStop();
+		unBindFromService();
+	}
+	
+	private ServiceConnection connection = new ServiceConnection(){
+
+		@Override
+		public void onServiceConnected(ComponentName name, IBinder service) {
+			messageService = new Messenger(service);
+			
+			try{
+				Message msg = Message.obtain(null, DownloadService.MSG_REGISTER_CLIENT);
+				msg.replyTo = messenger;
+				messageService.send(msg);
+				
+			}catch (RemoteException e){}
+		}
+
+		@Override
+		public void onServiceDisconnected(ComponentName name) {
+			messageService = null;
+		}
+		
+	};
+	
+	private void bindToService(){
+		Intent i = new Intent(getApplicationContext(), DownloadService.class);
+		i.putExtra("taskID", DownloadService.TASKID_START);
+		startService(i);
+		bindService(new Intent(getApplicationContext(), DownloadService.class), connection, Context.BIND_AUTO_CREATE);
+		boundToService = true;
+	}
+	
+	private void unBindFromService(){
+		if(boundToService){
+			boundToService = false;
+			unbindService(connection);
+		}	
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadAsyncTask.java	Thu Jul 14 15:41:26 2011 +0200
@@ -0,0 +1,115 @@
+package org.hedgewars.mobile.Downloader;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import android.os.AsyncTask;
+import android.util.Log;
+/**
+ * This is an AsyncTask which will download a zip from an URL and unzip it to a specified path
+ * 
+ *  a typical call to start the task would be new DownloadAsyncTask().execute(getExternalStorage(), "www.hedgewars.org/data.zip");
+ * @author Xeli
+ *
+ */
+public class DownloadAsyncTask extends AsyncTask<String, Object, Long> {
+
+	private DownloadService service;
+	private long lastUpdateMillis = 0;
+	
+	public DownloadAsyncTask(DownloadService _service){
+		service = _service;
+	}
+	
+	/**
+	 * 
+	 * @param params - 2 Strings, first is the path where the unzipped files will be stored, second is the URL to download from
+	 */
+	protected Long doInBackground(String... params) {
+		HttpURLConnection conn = null;
+		try {
+			String rootZipDest = params[0];
+
+			File rootDest = new File(rootZipDest);
+			rootDest.mkdir();
+			
+			URL url = new URL(params[1]);
+			conn = (HttpURLConnection)url.openConnection();
+			String contentType = conn.getContentType();
+
+			if(contentType == null || contentType.contains("zip")){ //Seeing as we provide the url if the contentType is unknown lets assume zips
+				ZipInputStream input = new ZipInputStream(conn.getInputStream());
+				int bytesDecompressed = 0;
+				final int kbytesToProcess = conn.getContentLength()/1024;
+				
+				service.start(kbytesToProcess);
+				
+				ZipEntry entry = null;
+				while((entry = input.getNextEntry()) != null){
+					String fileName = entry.getName();
+					
+					if(isCancelled()) break;
+					else if(System.currentTimeMillis() - lastUpdateMillis > 1000){
+						lastUpdateMillis = System.currentTimeMillis();
+						publishProgress(bytesDecompressed, kbytesToProcess, fileName);
+					}
+					
+					Log.e("bla", fileName);
+					bytesDecompressed += entry.getCompressedSize();
+					
+					File f = new File(rootZipDest + fileName);
+
+					if(entry.isDirectory()){
+						f.mkdir();
+					}else{
+						if(f.exists()){
+							f.delete();
+						}
+
+						try {
+							f.createNewFile();
+							FileOutputStream out = new FileOutputStream(f);
+
+							byte[] buffer = new byte[1024];
+							int count = 0;
+							while((count = input.read(buffer)) != -1){
+								out.write(buffer, 0, count);
+							}
+							out.flush();
+							out.close();
+							input.closeEntry();
+						} catch (FileNotFoundException e) {
+							e.printStackTrace();
+						} catch (IOException e) {
+							e.printStackTrace();
+						}
+					}
+				}
+				input.close();
+			}else{
+				Log.e("bla", "contenttype = " + contentType);
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}finally{
+			if(conn != null) conn.disconnect();
+		}
+		return null;
+	}
+	
+	//TODO propper result handling
+	protected void onPostExecute(Long result){
+		service.done(true);
+	}
+	
+	protected void onProgressUpdate(Object...objects){
+		service.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]);
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadService.java	Thu Jul 14 15:41:26 2011 +0200
@@ -0,0 +1,164 @@
+package org.hedgewars.mobile.Downloader;
+
+import java.util.ArrayList;
+
+import org.hedgewars.mobile.MainActivity;
+import org.hedgewars.mobile.R;
+import org.hedgewars.mobile.Utils;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.util.Log;
+import android.widget.RemoteViews;
+
+public class DownloadService extends Service {
+
+	private final static String URL = "http://www.xelification.com/tmp/data.zip";
+	public static final int MSG_CANCEL = 0;
+	public static final int MSG_REGISTER_CLIENT = 1;
+	public static final int MSG_UNREGISTER_CLIENT = 2;
+
+	public static final int NOTIFICATION_PROCESSING = 0;
+	public static final int NOTIFICATION_DONE = 1;
+
+	private DownloadAsyncTask downloadTask;
+	private final Messenger messenger = new Messenger(new DownloadHandler());
+	private NotificationManager nM;
+	private RemoteViews contentView;
+	private Notification notification;
+
+	private ArrayList<Messenger> clientList = new ArrayList<Messenger>();
+	private Message onRegisterMessage = null;
+
+
+	class DownloadHandler extends Handler{
+
+		public void handleMessage(Message msg){
+			switch(msg.what){
+			case MSG_CANCEL:
+				downloadTask.cancel(false);
+				break;
+			case MSG_REGISTER_CLIENT:
+				clientList.add(msg.replyTo);
+				if(onRegisterMessage != null){
+					try {
+						msg.replyTo.send(Message.obtain(onRegisterMessage));
+					} catch (RemoteException e) {
+						e.printStackTrace();
+					}
+				}
+				break;
+			case MSG_UNREGISTER_CLIENT:
+				clientList.remove(msg.replyTo);
+				break;
+			}
+		}
+	}
+
+	public final static int TASKID_START = 0;
+	public final static int TASKID_CANCEL = 1;
+	
+	public int onStartCommand(Intent intent, int flags, int startId){
+		switch(intent.getIntExtra("taskID", TASKID_START)){
+		case TASKID_START:
+			nM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+
+			notification = new Notification(R.drawable.statusbar, getString(R.string.notification_title), System.currentTimeMillis());
+			//notification.flags |= Notification.FLAG_ONGOING_EVENT;// | Notification.FLAG_NO_CLEAR | Notification.FLAG_FOREGROUND_SERVICE;
+			notification.flags |= Notification.FLAG_ONGOING_EVENT;
+
+			contentView = new RemoteViews(getPackageName(), R.layout.notification);
+			contentView.setProgressBar(R.id.notification_progress, 100, 34, false);
+			notification.contentView = contentView;
+
+			PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, DownloadActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK);
+			notification.contentIntent = contentIntent;
+
+			//nM.notify(NOTIFICATION_PROCESSING, notification);
+			startForeground(NOTIFICATION_PROCESSING, notification);
+
+			if(downloadTask == null){
+				downloadTask = new DownloadAsyncTask(this);
+				downloadTask.execute(Utils.getDownloadPath(this), URL);
+			}	
+			break;
+		case TASKID_CANCEL:
+			downloadTask.cancel(false);
+			stopService();
+			break;
+		}		
+		return 0;
+	}
+
+	public void onDestroy(){
+		Log.e("bla", "onDestroy");
+		downloadTask.cancel(false);	
+	}
+
+	public IBinder onBind(Intent intent) {
+		return messenger.getBinder();
+	}
+
+	/*
+	 * Thread safe method to let clients know the processing is starting and will process int max kbytes
+	 * 
+	 */
+	public void start(int max){
+		onRegisterMessage = Message.obtain(null, DownloadActivity.MSG_START, max, -1);
+		sendMessageToClients(onRegisterMessage);
+	}
+
+	public void update(int progress, int max, String fileName){
+		progress = (progress/1024);
+		updateNotification(progress, max, fileName);
+
+		sendMessageToClients(Message.obtain(null, DownloadActivity.MSG_UPDATE, progress, max, fileName));
+	}
+	public void done(boolean succesful){
+		sendMessageToClients(Message.obtain(null, DownloadActivity.MSG_DONE));
+		stopService();//stopService clears all notifications and thus must be called before we show the ready notification
+		showDoneNotification();
+	}
+
+	private void stopService(){
+		nM.cancelAll();
+		stopForeground(true);
+		stopSelf();
+	}
+	
+	private void updateNotification(int progress, int max, String fileName){
+
+		contentView.setProgressBar(R.id.notification_progress, max, progress, false);
+		contentView.setTextViewText(R.id.progressbar_sub, String.format("%dkb/%dkb (Compressed sizes)", progress, max));
+		nM.notify(NOTIFICATION_PROCESSING, notification);
+	}
+
+	private void showDoneNotification(){
+		nM.cancelAll();
+		stopForeground(true);
+
+		String title = getString(R.string.notification_title);
+
+		notification = new Notification(R.drawable.icon, title, System.currentTimeMillis());
+		notification.flags |= Notification.FLAG_AUTO_CANCEL;
+		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), Intent.FLAG_ACTIVITY_NEW_TASK);
+		notification.setLatestEventInfo(this, title, getString(R.string.notification_done), contentIntent);
+		nM.notify(NOTIFICATION_DONE, notification);
+	}	
+	private void sendMessageToClients(Message msg){
+		for(Messenger m : clientList){
+			try {
+				m.send(Message.obtain(msg));
+			} catch (RemoteException e) {}//TODO should we catch this properly?
+		}
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadThread.java	Thu Jul 14 15:41:26 2011 +0200
@@ -0,0 +1,13 @@
+package org.hedgewars.mobile.Downloader;
+
+public class DownloadThread extends Thread{
+	
+	public DownloadThread(){
+		
+	}
+	
+	public void run(){
+		
+	}
+
+}