--- a/hedgewars/uAI.pas Mon Nov 14 17:59:26 2011 +0100
+++ b/hedgewars/uAI.pas Mon Nov 14 18:03:31 2011 +0100
@@ -325,6 +325,7 @@
{$ELSE}
ThinkThread := SDL_CreateThread(@Think, Me);
{$ENDIF}
+{$ENDIF}
AddFileLog('Thread started');
end;
--- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml Mon Nov 14 17:59:26 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml Mon Nov 14 18:03:31 2011 +0100
@@ -28,6 +28,13 @@
android:launchMode="singleTask">
</activity>
+ <activity android:name=".Downloader.DownloadListActivity"
+ android:label="@string/app_name"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+ </activity>
+
+ <service android:name=".Downloader.DownloadService"/>
+
<activity android:name="StartGameActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
@@ -38,12 +45,10 @@
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation='landscape'>
</activity>
- <activity android:name="TeamCreatorActivity"
+ <activity android:name="TeamCreatorActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation='landscape'>
</activity>
-
- <service android:name=".Downloader.DownloadService"/>
</application>
</manifest>
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadActivity.java Mon Nov 14 17:59:26 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadActivity.java Mon Nov 14 18:03:31 2011 +0100
@@ -114,7 +114,7 @@
private OnClickListener cancelClicker = new OnClickListener(){
public void onClick(View v){
Intent i = new Intent(getApplicationContext(), DownloadService.class);
- i.putExtra("taskID", DownloadService.TASKID_CANCEL);
+ i.putExtra(DownloadService.INTENT_TASKID, DownloadService.TASKID_CANCEL);
startService(i);
finish();
}
@@ -128,13 +128,13 @@
private OnClickListener tryAgainClicker = new OnClickListener(){
public void onClick(View v){
- bindToService(DownloadService.TASKID_RETRY);
+ bindToService(DownloadService.TASKID_ADDTASK);
}
};
public void onStart(){
super.onStart();
- bindToService(DownloadService.TASKID_START);
+ bindToService(DownloadService.TASKID_SETUP);
}
public void onStop(){
@@ -163,7 +163,7 @@
private void bindToService(int taskId){
Intent i = new Intent(getApplicationContext(), DownloadService.class);
- i.putExtra("taskID", taskId);
+ i.putExtra(DownloadService.INTENT_TASKID, taskId);
startService(i);
bindService(new Intent(getApplicationContext(), DownloadService.class), connection, Context.BIND_AUTO_CREATE);
boundToService = true;
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java Mon Nov 14 17:59:26 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAsyncTask.java Mon Nov 14 18:03:31 2011 +0100
@@ -32,7 +32,6 @@
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
*
@@ -40,13 +39,12 @@
* @author Xeli
*
*/
-public class DownloadAsyncTask extends AsyncTask<String, Object, Long> {
+public class DownloadAsyncTask extends AsyncTask<DownloadTask, Object, Long> {
- private final static String URL_WITHOUT_SUFFIX = "http://hedgewars.googlecode.com/files/data_5631.";
//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";
-
+ private final static String URL_ZIP_SUFFIX = ".zip";
+ private final static String URL_HASH_SUFFIX = ".hash";
+
private DownloadService service;
private long lastUpdateMillis = 0;
@@ -56,18 +54,20 @@
/**
*
- * @param params - 2 Strings, first is the path where the unzipped files will be stored, second is the URL to download from
+ * @param params - A {@link}DownloadTask which gives information about where to download from and store the files to
*/
- protected Long doInBackground(String... params) {
+ protected Long doInBackground(DownloadTask...tasks) {
+ DownloadTask task = tasks[0];//just use one task per execute call for now
+
HttpURLConnection conn = null;
MessageDigest digester = null;
- String rootZipDest = params[0];
+ String rootZipDest = task.getPathToStore();
File rootDest = new File(rootZipDest);//TODO check for nullpointer, it hints to the absence of an sdcard
rootDest.mkdir();
try {
- URL url = new URL(URL_WITHOUT_SUFFIX + URL_ZIP_SUFFIX);
+ URL url = new URL(task.getURL() + URL_ZIP_SUFFIX);
conn = (HttpURLConnection)url.openConnection();
} catch (IOException e) {
e.printStackTrace();
@@ -161,7 +161,7 @@
if(conn != null) conn.disconnect();
- if(checkMD5(digester))return 0l;
+ if(checkMD5(digester, task))return 0l;
else return -1l;
}
@@ -174,12 +174,12 @@
service.update((Integer)objects[0], (Integer)objects[1], (String)objects[2]);
}
- private boolean checkMD5(MessageDigest digester){
+ private boolean checkMD5(MessageDigest digester, DownloadTask task){
if(digester != null) {
byte[] messageDigest = digester.digest();
try {
- URL url = new URL(URL_WITHOUT_SUFFIX + URL_HASH_SUFFIX);
+ URL url = new URL(task.getURL() + URL_HASH_SUFFIX);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
byte[] buffer = new byte[1024];//size is large enough to hold the entire hash
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadListActivity.java Mon Nov 14 18:03:31 2011 +0100
@@ -0,0 +1,36 @@
+package org.hedgewars.hedgeroid.Downloader;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+
+public class DownloadListActivity extends ListActivity implements OnItemClickListener{
+
+
+ public void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ DownloadTask[] tasks = new DownloadTask[3];
+ tasks[0] = new DownloadTask("url1", "/home/path/1", 1, "entry 1");
+ tasks[1] = new DownloadTask("url2", "/home/path/2", 1, "entry 2");
+ tasks[2] = new DownloadTask("url3", "/home/path/3", 1, "entry 3");
+
+ ArrayAdapter<DownloadTask> adapter = new ArrayAdapter<DownloadTask>(this, android.R.layout.simple_list_item_1, tasks);
+ this.setListAdapter(adapter);
+ this.getListView().setOnItemClickListener(this);
+
+ }
+
+ public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
+ DownloadTask task = (DownloadTask)arg0.getAdapter().getItem(position);
+ }
+
+// public static class Dialog extends DialogFragment{
+
+// }
+
+}
+
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java Mon Nov 14 17:59:26 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadService.java Mon Nov 14 18:03:31 2011 +0100
@@ -20,6 +20,7 @@
package org.hedgewars.hedgeroid.Downloader;
import java.util.ArrayList;
+import java.util.LinkedList;
import org.hedgewars.hedgeroid.MainActivity;
import org.hedgewars.hedgeroid.R;
@@ -30,6 +31,7 @@
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;
@@ -41,6 +43,13 @@
public class DownloadService extends Service {
+ public final static int TASKID_SETUP = 0;
+ public final static int TASKID_CANCEL = 1;
+ public final static int TASKID_ADDTASK = 2;
+
+ public final static String INTENT_TASKID = "taskId";
+ public final static String INTENT_TASK = "task";
+
public static final String PREF_DOWNLOADED = "downloaded";
public static final int MSG_CANCEL = 0;
public static final int MSG_REGISTER_CLIENT = 1;
@@ -49,12 +58,13 @@
public static final int NOTIFICATION_PROCESSING = 0;
public static final int NOTIFICATION_DONE = 1;
- private DownloadAsyncTask downloadTask;
+ private DownloadAsyncTask asyncExecutor;
private final Messenger messenger = new Messenger(new DownloadHandler());
private NotificationManager nM;
private RemoteViews contentView;
private Notification notification;
+ private LinkedList<DownloadTask> downloadTasks = new LinkedList<DownloadTask>();
private ArrayList<Messenger> clientList = new ArrayList<Messenger>();
private Message onRegisterMessage = null;
@@ -64,7 +74,7 @@
public void handleMessage(Message msg){
switch(msg.what){
case MSG_CANCEL:
- downloadTask.cancel(false);
+ asyncExecutor.cancel(false);
break;
case MSG_REGISTER_CLIENT:
clientList.add(msg.replyTo);
@@ -82,23 +92,19 @@
}
}
}
+ public IBinder onBind(Intent intent) {
+ return messenger.getBinder();
+ }
- public final static int TASKID_START = 0;
- public final static int TASKID_CANCEL = 1;
- public final static int TASKID_RETRY = 2;
-
+ /**
+ * This is the main method which controls how DownloadService and DownloadAsyncTask are running
+ */
public int onStartCommand(Intent intent, int flags, int startId){
- switch(intent.getIntExtra("taskID", TASKID_START)){
- case TASKID_RETRY:
- if(downloadTask != null){
- downloadTask.cancel(false);
- downloadTask = null;
- }
- case TASKID_START:
+ switch(intent.getIntExtra("taskID", TASKID_SETUP)){
+ case TASKID_SETUP:
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);
@@ -108,67 +114,66 @@
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));
- }
+ asyncExecutor = new DownloadAsyncTask(this);
+ break;
+ case TASKID_ADDTASK:
+ //Add downloadtask to the queue
+ DownloadTask task = intent.getParcelableExtra(DownloadService.INTENT_TASK);
+ downloadTasks.offer(task);
+ runNextTask();
break;
case TASKID_CANCEL:
- downloadTask.cancel(false);
- stopService();
+ asyncExecutor.cancel(false);
break;
}
return 0;
}
- public void onDestroy(){
- Log.e("bla", "onDestroy");
- downloadTask.cancel(false);
+ private synchronized void runNextTask(){
+ if(!asyncExecutor.getStatus().equals(AsyncTask.Status.RUNNING)){//if the task isnt running right now...
+ DownloadTask task = downloadTasks.poll();
+ if(task == null){
+ startForeground(NOTIFICATION_PROCESSING, notification);
+ asyncExecutor.execute(task);
+ }
+ }
}
- public IBinder onBind(Intent intent) {
- return messenger.getBinder();
+ public void onDestroy(){
+ super.onDestroy();
+ asyncExecutor.cancel(false);
}
/*
- * Thread safe method to let clients know the processing is starting and will process int max kbytes
+ * Callbacks called from the async tasks
*/
+
+ //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);
}
- /*
- * periodically gets called by the ASyncTask, we can't tell for sure when it's called
- */
+ //periodically gets called by the ASyncTask, we can't tell for sure when it's called
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));
}
-
- /*
- * Call back from the ASync task when the task has either run into an error or finished otherwise
- */
+
+ //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){
- PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean(DownloadService.PREF_DOWNLOADED, true).commit();
sendMessageToClients(Message.obtain(null, DownloadActivity.MSG_DONE));
}else sendMessageToClients(Message.obtain(null, DownloadActivity.MSG_FAILED));
- stopService();//stopService clears all notifications and thus must be called before we show the ready notification
+ nM.cancel(NOTIFICATION_PROCESSING);
+ stopForeground(true);
showDoneNotification();
+ runNextTask();//see if there are more tasks
}
- 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);
@@ -177,9 +182,6 @@
}
private void showDoneNotification(){
- nM.cancelAll();
- stopForeground(true);
-
String title = getString(R.string.notification_title);
notification = new Notification(R.drawable.icon, title, System.currentTimeMillis());
@@ -187,7 +189,8 @@
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 {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadTask.java Mon Nov 14 18:03:31 2011 +0100
@@ -0,0 +1,158 @@
+/*
+ * Hedgewars for Android. An Android port of Hedgewars, a free turn based strategy game
+ * Copyright (c) 2011 Richard Deurwaarder <xeli@xelification.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+package org.hedgewars.hedgeroid.Downloader;
+
+import java.io.IOException;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class DownloadTask implements Parcelable{
+
+ private String url_without_suffix;
+ private String pathToStore;
+ private String representation;
+ private int attempts;
+ private int versionNumber;
+
+
+ public DownloadTask(Parcel in){
+ readFromParcel(in);
+ }
+
+ public DownloadTask(String _url_without_suffix, String path, int version, String _representation){
+ url_without_suffix = _url_without_suffix;
+ pathToStore = path;
+ representation = _representation;
+ versionNumber = version;
+ attempts = 0;
+ }
+
+ public int getAttempts(){
+ return attempts;
+ }
+
+ public String getURL(){
+ return url_without_suffix;
+ }
+
+ public String getPathToStore(){
+ return pathToStore;
+ }
+
+ public void incrementAttempts(){
+ attempts++;
+ }
+
+ public String toString(){
+ return representation;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(url_without_suffix);
+ dest.writeString(pathToStore);
+ dest.writeString(representation);
+ dest.writeInt(versionNumber);
+ dest.writeInt(attempts);
+ }
+
+ private void readFromParcel(Parcel src){
+ url_without_suffix = src.readString();
+ pathToStore = src.readString();
+ representation = src.readString();
+ versionNumber = src.readInt();
+ attempts = src.readInt();
+ }
+
+ public static final Parcelable.Creator<DownloadTask> CREATOR = new Parcelable.Creator<DownloadTask>() {
+ public DownloadTask createFromParcel(Parcel source) {
+ return new DownloadTask(source);
+ }
+ public DownloadTask[] newArray(int size) {
+ return new DownloadTask[size];
+ }
+ };
+
+ /*
+ * We enter with a XmlPullParser.Start_tag with name "task"
+ */
+ public static DownloadTask getTaskFromXML(XmlPullParser xmlPuller) throws XmlPullParserException, IOException{
+ String url = null;
+ String path = null;
+ String representation = null;
+ int version = -1;
+
+ int eventType = xmlPuller.getEventType();//get the next token, should be a start tag
+ while(eventType != XmlPullParser.END_DOCUMENT){
+ switch(eventType){
+ case XmlPullParser.START_TAG:
+ String name = xmlPuller.getName().toLowerCase();
+ if(name.equals("url")){
+ if(xmlPuller.getEventType() == XmlPullParser.TEXT){
+ url = xmlPuller.getText();
+ }
+ }else if(name.equals("version")){
+ if(xmlPuller.getEventType() == XmlPullParser.TEXT){
+ version = Integer.parseInt(xmlPuller.getText());
+ }
+ }else if(name.equals("path")){
+ if(xmlPuller.getEventType() == XmlPullParser.TEXT){
+ path = xmlPuller.getText();
+ }
+ }else if(name.equals("representation")){
+ if(xmlPuller.getEventType() == XmlPullParser.TEXT){
+ representation = xmlPuller.getText();
+ }
+ }
+
+ xmlPuller.getEventType();//endtag
+ break;
+ case XmlPullParser.END_TAG:
+ if(xmlPuller.getName().toLowerCase().equals("task") && url != null && path != null && version != -1 && representation != null){
+ return new DownloadTask(url, path, version, representation);
+ }else{
+ throw new XmlPullParserException(null);
+ }
+ default:
+ throw new XmlPullParserException(null);
+ }
+ eventType = getEventType(xmlPuller);
+ }
+
+ throw new XmlPullParserException(null);
+ }
+
+ /**
+ * Skips whitespaces..
+ */
+ private static int getEventType(XmlPullParser xmlPuller)throws XmlPullParserException, IOException{
+ int eventType = xmlPuller.next();
+ while(eventType == XmlPullParser.TEXT && xmlPuller.isWhitespace()){
+ eventType = xmlPuller.next();
+ }
+ return eventType;
+ }
+}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Mon Nov 14 17:59:26 2011 +0100
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java Mon Nov 14 18:03:31 2011 +0100
@@ -19,6 +19,7 @@
package org.hedgewars.hedgeroid;
import org.hedgewars.hedgeroid.Downloader.DownloadActivity;
+import org.hedgewars.hedgeroid.Downloader.DownloadListActivity;
import org.hedgewars.hedgeroid.Downloader.DownloadService;
import android.app.Activity;
@@ -49,7 +50,8 @@
private OnClickListener downloadClicker = new OnClickListener(){
public void onClick(View v){
- startActivityForResult(new Intent(getApplicationContext(), DownloadActivity.class), 0);
+ //startActivityForResult(new Intent(getApplicationContext(), DownloadActivity.class), 0);
+ startActivityForResult(new Intent(getApplicationContext(), DownloadListActivity.class), 0);
}
};