# HG changeset patch # User Xeli # Date 1310650886 -7200 # Node ID ab055114c7887d0ebcf79bc0ea29555b795d635c # Parent 8e7787065e2d921720fba528bff8b3eaff1dc1c8 Moved download classes to their own dir and fixed the way the dest dir is being 'build' diff -r 8e7787065e2d -r ab055114c788 project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadActivity.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); + } + } +} diff -r 8e7787065e2d -r ab055114c788 project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadAsyncTask.java --- /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 { + + 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]); + } + +} diff -r 8e7787065e2d -r ab055114c788 project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/Downloader/DownloadService.java --- /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 clientList = new ArrayList(); + 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? + } + } + +} diff -r 8e7787065e2d -r ab055114c788 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/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(){ + + } + +}