Added download functionality and changed some icons hedgeroid
authorXeli
Tue, 05 Jul 2011 18:27:18 +0200
branchhedgeroid
changeset 5397 4ae1b082e4ba
parent 5395 5caae9d7e12e
child 5399 cdef954f8aec
Added download functionality and changed some icons
project_files/Android-build/SDL-android-project/AndroidManifest.xml
project_files/Android-build/SDL-android-project/default.properties
project_files/Android-build/SDL-android-project/default.properties.orig
project_files/Android-build/SDL-android-project/local.properties
project_files/Android-build/SDL-android-project/res/drawable-mdpi/statusbar.png
project_files/Android-build/SDL-android-project/res/layout/download.xml
project_files/Android-build/SDL-android-project/res/layout/main.xml
project_files/Android-build/SDL-android-project/res/layout/notification.xml
project_files/Android-build/SDL-android-project/res/values/strings.xml
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadAsyncTask.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadService.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadThread.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/MainActivity.java
--- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml	Tue Jul 05 18:23:54 2011 +0200
+++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml	Tue Jul 05 18:27:18 2011 +0200
@@ -1,17 +1,33 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="org.hedgewars"
+      package="org.hedgewars.mobile"
       android:versionCode="1"
       android:versionName="1.0">
+    <uses-sdk android:targetSdkVersion="8" android:minSdkVersion="5"></uses-sdk>
+    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
     <application android:label="@string/app_name" android:icon="@drawable/icon">
-        <activity android:name="SDLActivity"
+        <activity android:name=".MainActivity"
                   android:label="@string/app_name"
- 		  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
-		  android:screenOrientation='landscape'>
+ 		  		  android:theme="@android:style/Theme"
+ 		  		  android:launchMode="singleTask">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity android:name=".SDLActivity"
+                  android:label="@string/app_name"
+ 		  android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+		  android:screenOrientation='landscape'>
+        </activity>
+        
+        <activity android:name=".DownloadActivity"
+                  android:label="@string/app_name"
+				  android:theme="@android:style/Theme.Dialog"
+ 		  		  android:launchMode="singleTask">
+        </activity>
+        
+        <service android:name=".DownloadService"/>
     </application>
 </manifest> 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/default.properties	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/default.properties.orig	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must be checked in Version Control Systems.
+# 
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/local.properties	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,10 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+# 
+# This file must *NOT* be checked in Version Control Systems,
+# as it contains information specific to your local configuration.
+
+# location of the SDK. This is only used by Ant
+# For customization when using a Version Control System, please read the
+# header note.
+sdk.dir=/home/richard/SoftDev/android/android-sdk-linux_86
Binary file project_files/Android-build/SDL-android-project/res/drawable-mdpi/statusbar.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/download.xml	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+	android:id="@+id/container"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:padding="5dp">
+    <ProgressBar
+    	android:id="@+id/progressbar"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_alignLeft="@+id/background"
+    	android:layout_alignRight="@+id/cancelDownload"
+    	android:progressDrawable="@android:drawable/progress_horizontal"
+		android:indeterminate="false" android:indeterminateOnly="false"/>
+	<TextView
+    	android:id="@+id/progressbar_sub"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_below="@id/progressbar"
+    	android:layout_alignLeft="@+id/background"
+    	android:layout_alignRight="@+id/cancelDownload"
+    	android:text="@string/notification_title"
+    	android:textColor="#FFF"
+    	android:textSize="14dp"/> 	
+    <Button
+    	android:id="@id/background"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_below="@id/progressbar_sub"
+    	android:text="@string/download_background"/>
+    <Button
+    	android:id="@+id/cancelDownload"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_below="@id/progressbar_sub"
+    	android:layout_toRightOf="@id/background"
+    	android:text="@string/download_cancel"/>
+    	
+</RelativeLayout>
+
--- a/project_files/Android-build/SDL-android-project/res/layout/main.xml	Tue Jul 05 18:23:54 2011 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/main.xml	Tue Jul 05 18:27:18 2011 +0200
@@ -9,5 +9,18 @@
     android:layout_height="wrap_content" 
     android:text="Hello World, SDLActivity"
     />
+    
+    <Button
+    	android:id="@+id/downloader"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:text="downloader"/>
+    	
+    <Button
+    	android:id="@+id/startGame"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:text="startgame"/>
+    	
 </LinearLayout>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/notification.xml	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="3dp">
+	<ImageView
+		android:id="@+id/icon"
+    	android:layout_width="wrap_content" 
+    	android:layout_height="fill_parent"
+    	android:scaleType="centerInside"
+    	android:src="@drawable/icon"/>
+    
+    <TextView
+    	android:id="@+id/title"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_toRightOf="@id/icon"
+    	android:text="@string/notification_title"
+    	android:textColor="#000"
+    	android:textSize="17dp"
+    	android:textStyle="bold"/>
+    			
+	<TextView
+    	android:id="@+id/progressbar_sub"
+    	android:layout_width="wrap_content"
+    	android:layout_height="wrap_content"
+    	android:layout_toRightOf="@id/icon"
+    	android:layout_alignParentBottom="true"
+    	android:text="@string/notification_title"
+    	android:textColor="#000"
+    	android:textSize="10dp"/> 	
+	<ProgressBar
+		android:id="@+id/notification_progress"
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_toRightOf="@id/icon"
+		android:layout_below="@id/title"
+		android:layout_above="@id/progressbar_sub"
+		android:progressDrawable="@android:drawable/progress_horizontal"
+		android:indeterminate="false" android:indeterminateOnly="false"
+		android:paddingRight="5dp"
+		android:paddingTop="5dp"/>   
+
+</RelativeLayout>
+
--- a/project_files/Android-build/SDL-android-project/res/values/strings.xml	Tue Jul 05 18:23:54 2011 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml	Tue Jul 05 18:27:18 2011 +0200
@@ -1,4 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="app_name">SDL App</string>
+    <string name="app_name">Hedgewars</string>
+    
+    <!-- SDCARD -->
+    <string name="sdcard_not_mounted">There\'s been an error when accessing the sdcard, is it connected to another computer?</string>
+        
+    <!-- Notification -->
+    <string name="notification_title">Downloading hedgewars files...</string>
+    <string name="notification_done">Success - Download complete</string>
+    
+    <!-- Download Activity -->
+    <string name="download_background">Continue in background</string>
+    <string name="download_cancel">Cancel</string>
+    <string name="download_done">Done</string>
+    <string name="download_back">Back to main menu</string>
+    
 </resources>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadActivity.java	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,139 @@
+package org.hedgewars.mobile;
+
+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/DownloadAsyncTask.java	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,111 @@
+package org.hedgewars.mobile;
+
+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];
+
+			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);
+					}
+					
+					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/DownloadService.java	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,171 @@
+package org.hedgewars.mobile;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+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;
+import android.widget.Toast;
+
+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(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?
+		}
+	}
+	public static String getDownloadPath(Context c){
+		File f =  c.getExternalCacheDir();
+		if(f != null){
+			return f.getAbsolutePath();
+		}else{
+			Toast.makeText(c, R.string.sdcard_not_mounted, Toast.LENGTH_LONG);
+			return null;
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/DownloadThread.java	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,13 @@
+package org.hedgewars.mobile;
+
+public class DownloadThread extends Thread{
+	
+	public DownloadThread(){
+		
+	}
+	
+	public void run(){
+		
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/mobile/MainActivity.java	Tue Jul 05 18:27:18 2011 +0200
@@ -0,0 +1,39 @@
+package org.hedgewars.mobile;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+public class MainActivity extends Activity {
+
+	Button downloader, startGame;
+	
+	public void onCreate(Bundle sis){
+		super.onCreate(sis);
+		setContentView(R.layout.main);
+		
+		downloader = (Button)findViewById(R.id.downloader);
+		startGame = (Button)findViewById(R.id.startGame);
+		
+		downloader.setOnClickListener(downloadClicker);
+		startGame.setOnClickListener(startGameClicker);
+	}
+	
+	
+	
+	private OnClickListener downloadClicker = new OnClickListener(){
+		public void onClick(View v){
+			startActivityForResult(new Intent(getApplicationContext(), DownloadActivity.class), 0);
+		}
+	};
+
+	private OnClickListener startGameClicker = new OnClickListener(){
+		public void onClick(View v){
+			startActivity(new Intent(getApplicationContext(), SDLActivity.class));
+		}
+	};
+	
+}