Hedgeroid: Layout experiments for the lobby page
authorMedo <smaxein@googlemail.com>
Mon, 16 Jul 2012 20:16:03 +0200
changeset 7330 867e4fda496e
parent 7328 cd919a2ead4e
child 7332 3f2e130f9715
Hedgeroid: Layout experiments for the lobby page
project_files/Android-build/SDL-android-project/AndroidManifest.xml
project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml
project_files/Android-build/SDL-android-project/res/layout/activity_lobby_paged.xml
project_files/Android-build/SDL-android-project/res/layout/lobby_chat_fragment.xml
project_files/Android-build/SDL-android-project/res/layout/lobby_players_fragment.xml
project_files/Android-build/SDL-android-project/res/layout/lobby_rooms_fragment.xml
project_files/Android-build/SDL-android-project/res/values/strings.xml
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyChatFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayService.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java
project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TestActivity.java
--- a/project_files/Android-build/SDL-android-project/AndroidManifest.xml	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/AndroidManifest.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -68,7 +68,7 @@
             android:windowSoftInputMode="stateUnchanged" >
         </activity>
         <activity
-            android:name=".netplay.LobbyActivity"
+            android:name=".netplay.TestActivity"
             android:label="@string/title_activity_lobby" >
         </activity>
     </application>
--- a/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/layout/activity_lobby.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -1,35 +1,61 @@
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:padding="5dp" >
+
+    <FrameLayout
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_marginBottom="10dp"
+        android:layout_weight="0.3"
+        android:background="@drawable/box" >
 
-    <TextView
-        android:id="@+id/textbox"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentBottom="true"
-        android:layout_below="@+id/editText"
-        android:text=""
-        tools:context=".LobbyActivity" />
+        <fragment
+            android:id="@+id/roomListFragment"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            class="org.hedgewars.hedgeroid.netplay.RoomlistFragment"
+            tools:layout="@layout/lobby_rooms_fragment" />
+    </FrameLayout>
+
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="0.7"
+        android:baselineAligned="false"
+        android:orientation="horizontal" >
 
-    <EditText
-        android:id="@+id/editText"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentTop="true"
-        android:layout_toLeftOf="@+id/lobbySendButton"
-        android:ems="10"
-        android:inputType="text" />
+        <FrameLayout
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_marginRight="10dp"
+            android:layout_weight="0.7"
+            android:background="@drawable/box" >
+
+            <fragment
+                android:id="@+id/chatFragment"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                class="org.hedgewars.hedgeroid.netplay.LobbyChatFragment"
+                tools:layout="@layout/lobby_chat_fragment" />
+        </FrameLayout>
 
-    <Button
-        android:id="@+id/lobbySendButton"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_alignParentRight="true"
-        android:layout_alignParentTop="true"
-        android:text="Send" />
+        <FrameLayout
+            android:layout_width="0dp"
+            android:layout_height="fill_parent"
+            android:layout_weight="0.3"
+            android:background="@drawable/box" >
 
-</RelativeLayout>
+            <fragment
+                android:id="@+id/playerListFragment"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent"
+                class="org.hedgewars.hedgeroid.netplay.PlayerlistFragment"
+                tools:layout="@layout/lobby_players_fragment" />
+        </FrameLayout>
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/activity_lobby_paged.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <android.support.v4.view.ViewPager
+        android:id="@+id/pager"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="5dp" />
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/lobby_chat_fragment.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <ScrollView
+        android:id="@+id/lobbyConsoleScroll"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:requiresFadingEdge="vertical"
+        android:scrollbars="vertical" >
+
+        <TextView
+            android:id="@+id/lobbyConsole"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:autoLink="none"
+            android:freezesText="true"
+            android:text=""
+            tools:context=".LobbyActivity" />
+    </ScrollView>
+
+    <EditText
+        android:id="@+id/lobbyChatInput"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:hint="@string/chat_hint"
+        android:imeOptions="actionSend"
+        android:inputType="text" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/lobby_players_fragment.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingLeft="8dp"
+    android:paddingRight="8dp" >
+
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:drawSelectorOnTop="false"
+        tools:listitem="@android:layout/simple_list_item_1" />
+
+    <TextView
+        android:id="@id/android:empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/no_players_in_list" />
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/res/layout/lobby_rooms_fragment.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingLeft="8dp"
+    android:paddingRight="8dp" >
+
+    <ListView
+        android:id="@id/android:list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:drawSelectorOnTop="false"
+        tools:listitem="@android:layout/simple_list_item_1" />
+
+    <TextView
+        android:id="@id/android:empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:text="@string/no_rooms_in_list" />
+
+</LinearLayout>
\ No newline at end of file
--- a/project_files/Android-build/SDL-android-project/res/values/strings.xml	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/res/values/strings.xml	Mon Jul 16 20:16:03 2012 +0200
@@ -58,4 +58,11 @@
     <string name="bot1">Level 1</string>
 
     <string name="title_activity_lobby">LobbyActivity</string>
+    <string name="chat_hint">Type here to chat</string>
+    
+    <!-- Room list -->
+    <string name="no_rooms_in_list">No rooms</string>
+    
+    <!-- Player list -->
+    <string name="no_players_in_list">No players</string>
 </resources>
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Downloader/DownloadAssets.java	Mon Jul 16 20:16:03 2012 +0200
@@ -15,14 +15,14 @@
 import android.os.AsyncTask;
 import android.util.Log;
 
-public class DownloadAssets extends AsyncTask<Object, Long, Long>{
+public class DownloadAssets extends AsyncTask<Object, Long, Boolean> {
 	private final MainActivity act;
 	
-	public DownloadAssets(MainActivity _act){
-		act = _act;
+	public DownloadAssets(MainActivity act){
+		this.act = act;
 	}
 	
-	private static void copyFileOrDir(AssetManager assetManager, File target, String assetPath) throws IOException {
+	private void copyFileOrDir(AssetManager assetManager, File target, String assetPath) throws IOException {
 		try {
 			Utils.writeStreamToFile(assetManager.open(assetPath), target);
 		} catch(FileNotFoundException e) {
@@ -35,27 +35,27 @@
 				throw new IOException("Unable to create directory "+target);
 			}
 			for (String asset : assetManager.list(assetPath)) {
-				DownloadAssets.copyFileOrDir(assetManager, new File(target, asset), assetPath + "/" + asset);
+				copyFileOrDir(assetManager, new File(target, asset), assetPath + "/" + asset);
 			}
 		}
 	}
 	
 	@Override
-	protected Long doInBackground(Object... params) {
+	protected Boolean doInBackground(Object... params) {
 		try {
 			Utils.resRawToFilesDir(act, R.array.schemes, Scheme.DIRECTORY_SCHEME);
 			Utils.resRawToFilesDir(act, R.array.weapons, Weapon.DIRECTORY_WEAPON);
 			Utils.resRawToFilesDir(act, R.array.teams, Team.DIRECTORY_TEAMS);
-			DownloadAssets.copyFileOrDir(act.getAssets(), Utils.getDataPathFile(act), "Data");
-			return 0l;
+			copyFileOrDir(act.getAssets(), Utils.getDataPathFile(act), "Data");
+			return Boolean.TRUE;
 		} catch(IOException e) {
-			Log.e("org.hedgewars.hedgeroid", e.getMessage(), e);
-			return 1l;
+			Log.e("DownloadAssets", e.getMessage(), e);
+			return Boolean.FALSE;
 		}
 	}
 	
 	@Override
-	protected void onPostExecute(Long result){
-		act.onAssetsDownloaded(result == 0);
+	protected void onPostExecute(Boolean result){
+		act.onAssetsDownloaded(result);
 	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/MainActivity.java	Mon Jul 16 20:16:03 2012 +0200
@@ -21,6 +21,7 @@
 import org.hedgewars.hedgeroid.Downloader.DownloadAssets;
 import org.hedgewars.hedgeroid.Downloader.DownloadListActivity;
 import org.hedgewars.hedgeroid.netplay.LobbyActivity;
+import org.hedgewars.hedgeroid.netplay.TestActivity;
 
 import android.app.AlertDialog;
 import android.app.Dialog;
@@ -52,7 +53,7 @@
 		startGame.setOnClickListener(startGameClicker);
 		joinLobby.setOnClickListener(new OnClickListener() {
 			public void onClick(View v) {
-				startActivity(new Intent(getApplicationContext(), LobbyActivity.class));
+				startActivity(new Intent(getApplicationContext(), TestActivity.class));
 			}
 		});
 
@@ -69,8 +70,8 @@
 
 			if(!assetsCopied){
 				DownloadAssets assetsAsyncTask = new DownloadAssets(this);
-				assetsDialog = ProgressDialog.show(this, "Please wait a moment", "Moving assets...");
-				assetsAsyncTask.execute((Object[])null);
+				assetsDialog = ProgressDialog.show(this, "Please wait a moment", "Moving assets to SD card...");
+				assetsAsyncTask.execute();
 			}
 		}
 	}
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/Utils.java	Mon Jul 16 20:16:03 2012 +0200
@@ -246,4 +246,13 @@
 			writeStreamToFile(resources.openRawResource(resId), f);
 		}
 	}
+	
+	/**
+	 * Crashing - at least it's better than ignoring errors.
+	 */
+	public static void assertZero(int value, String text) {
+		if(value != 0) {
+			throw new RuntimeException("Result is not zero: " + text);
+		}
+	}
 }
--- a/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java	Wed Jul 11 01:52:01 2012 +0200
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyActivity.java	Mon Jul 16 20:16:03 2012 +0200
@@ -15,6 +15,8 @@
 import android.os.Bundle;
 import android.os.CountDownTimer;
 import android.app.Activity;
+import android.support.v4.app.FragmentActivity;
+import android.text.Html;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
@@ -25,7 +27,7 @@
 import android.widget.TextView;
 import android.widget.TextView.OnEditorActionListener;
 
-public class LobbyActivity extends Activity {
+public class LobbyActivity extends FragmentActivity {
 	static {
 		System.loadLibrary("SDL_net");
 	}
@@ -33,7 +35,6 @@
 	
 	TextView textView;
 	EditText editText;
-	Button button;
 	
 	boolean disconnected;
 	JnaFrontlib.NetconnPtr netconn;
@@ -43,7 +44,7 @@
 		if(!disconnected && netconn!=null) {
 			String text = editText.getText().toString();
 			editText.setText("");
-			textView.append("AndroidChatter: " + text + "\n");
+			textView.append(Html.fromHtml("<b>AndroidChatter</b>: " + text + "<br/>"));
 			FRONTLIB.flib_netconn_send_chat(netconn, text);
 		}
 	}
@@ -53,15 +54,19 @@
         super.onCreate(savedInstanceState);
         disconnected = false;
         setContentView(R.layout.activity_lobby);
-        textView = (TextView)findViewById(R.id.textbox);
-        editText = (EditText)findViewById(R.id.editText);
-        button = (Button)findViewById(R.id.lobbySendButton);
+        textView = (TextView)findViewById(R.id.lobbyConsole);
+        editText = (EditText)findViewById(R.id.lobbyChatInput);
         
-        button.setOnClickListener(new OnClickListener() {
-        	public void onClick(View v) {
-        		commitText();
-        	}
-        });
+        editText.setOnEditorActionListener(new OnEditorActionListener() {
+			public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+				boolean handled = false;
+				if(actionId == EditorInfo.IME_ACTION_SEND) {
+					commitText();
+					handled = true;
+				}
+				return handled;
+			}
+		});
         
     	FRONTLIB.flib_init();
     	try {
@@ -122,7 +127,7 @@
 	
     private JnaFrontlib.IntStrCallback handleMessage = new JnaFrontlib.IntStrCallback() {
 		public void callback(Pointer context, int arg1, String arg2) {
-			textView.append(arg2+"\n");
+			textView.append(Html.fromHtml(arg2+"<br/>"));
 		}
 	};
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/LobbyChatFragment.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,85 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v4.app.Fragment;
+import android.text.Html;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+public class LobbyChatFragment extends Fragment {
+	private TextView textView;
+	private EditText editText;
+	private ScrollView scrollView;
+	
+	private void commitText() {
+		String text = editText.getText().toString();
+		int overhang = textView.getHeight()-scrollView.getHeight();
+		boolean followBottom = overhang<=0 || Math.abs(overhang-scrollView.getScrollY())<5;
+		textView.append(Html.fromHtml("<b>Chatter:</b> " + text + "<br/>"));
+		editText.setText("");
+		if(followBottom) {
+			new Handler().post(new Runnable() {
+				public void run() {
+					scrollView.fullScroll(ScrollView.FOCUS_DOWN);
+				}
+			});
+		}
+	}
+	/*
+	@Override
+	public void onStart() {
+		super.onStart();
+		getActivity().bindService(new Intent(getActivity(), NetplayService.class), serviceConnection,
+	            Context.BIND_AUTO_CREATE);
+	}
+	*/
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		View view = inflater.inflate(R.layout.lobby_chat_fragment, container, false);
+		textView = (TextView) view.findViewById(R.id.lobbyConsole);
+		editText = (EditText) view.findViewById(R.id.lobbyChatInput);
+		scrollView = (ScrollView) view.findViewById(R.id.lobbyConsoleScroll);
+		
+        editText.setOnEditorActionListener(new OnEditorActionListener() {
+			public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+				boolean handled = false;
+				if(actionId == EditorInfo.IME_ACTION_SEND) {
+					commitText();
+					handled = true;
+				}
+				return handled;
+			}
+		});
+		
+		return view;
+	}
+	/*
+    private ServiceConnection serviceConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder binder) {
+        	netplayService = ((NetplayBinder) binder).getService();
+        	try {
+				netplayService.connect("AndroidChatter");
+			} catch (IOException e) {
+				throw new RuntimeException(e);
+			}
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+        	// TODO navigate away
+        	netplayService = null;
+        }
+    };
+    */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/NetplayService.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,117 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+
+import org.hedgewars.hedgeroid.Utils;
+import org.hedgewars.hedgeroid.netplay.JnaFrontlib.MetaschemePtr;
+import org.hedgewars.hedgeroid.netplay.JnaFrontlib.NetconnPtr;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.CountDownTimer;
+import android.os.IBinder;
+
+public class NetplayService extends Service {
+	static {
+		System.loadLibrary("SDL_net");
+	}
+	public static final JnaFrontlib FRONTLIB = (JnaFrontlib)Native.loadLibrary("frontlib", JnaFrontlib.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, FrontlibTypeMapper.INSTANCE));
+
+	private final NetplayBinder binder = new NetplayBinder();
+	public NetconnPtr netconn;
+	private CountDownTimer timer;
+	private String playerName;
+	
+	@Override
+	public IBinder onBind(Intent intent) {
+		return binder;
+	}
+	
+	@Override
+	public void onCreate() {
+		if(FRONTLIB.flib_init() != 0) {
+			throw new RuntimeException("Unable to start frontlib");
+		}
+	}
+	
+	@Override
+	public void onDestroy() {
+		disconnect();
+		FRONTLIB.flib_quit();
+	}
+
+	/**
+	 * Connect to the official Hedgewars server.
+	 * 
+	 * @throws IOException if the metascheme file can't be read or the connection to the server fails
+	 */
+	public void connect(String playerName) throws IOException {
+		connect(playerName, "140.247.62.101", 46631);
+	}
+	
+	/**
+	 * Connect to the server with the given hostname and port
+	 * 
+	 * @throws IOException if the metascheme file can't be read or the connection to the server fails
+	 */
+	public void connect(String playerName, String host, int port) throws IOException {
+		if(playerName == null) {
+			playerName = "Player";
+		}
+		this.playerName = playerName;
+		MetaschemePtr meta = null;
+		try {
+			String metaschemePath = new File(Utils.getDataPathFile(this), "metasettings.ini").getAbsolutePath();
+			meta = FRONTLIB.flib_metascheme_from_ini(metaschemePath);
+			if(meta == null) {
+				throw new RuntimeException("Missing metascheme");
+			}
+			netconn = FRONTLIB.flib_netconn_create(playerName, meta, Utils.getDataPathFile(this).getAbsolutePath(), host, port);
+	    	timer = new CountDownTimer(Long.MAX_VALUE, 50) {
+				@Override
+				public void onTick(long millisUntilFinished) {
+					if(netconn != null) {
+						FRONTLIB.flib_netconn_tick(netconn);
+					}
+				}
+				
+				@Override
+				public void onFinish() {
+				}
+			};
+			timer.start();
+		} catch(FileNotFoundException e) {
+			throw new RuntimeException(e);
+		} finally {
+			FRONTLIB.flib_metascheme_release(meta);
+		}
+	}
+	
+	public void disconnect() {
+		if(timer != null) {
+			timer.cancel();
+		}
+		if(netconn != null) {
+			FRONTLIB.flib_netconn_send_quit(netconn, "User quit");
+			FRONTLIB.flib_netconn_destroy(netconn);
+			netconn = null;
+		}
+	}
+	
+	public class NetplayBinder extends Binder {
+		NetplayService getService() {
+            return NetplayService.this;
+        }
+	}
+
+	public String getPlayerName() {
+		return playerName;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/Player.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,26 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.Comparator;
+
+public class Player {
+	public static final ByNameComparator nameComparator = new ByNameComparator(); 
+
+	public final String name;
+	public final long playerId;
+	public final boolean friend;
+	public final boolean ignored;
+	
+	public Player(String name, long playerId, boolean friend, boolean ignored) {
+		super();
+		this.name = name;
+		this.playerId = playerId;
+		this.friend = friend;
+		this.ignored = ignored;
+	}
+	
+	private static class ByNameComparator implements Comparator<Player> {
+		public int compare(Player lhs, Player rhs) {
+			return lhs.name.compareToIgnoreCase(rhs.name);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerListAdapter.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,62 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+public class PlayerListAdapter extends BaseAdapter {
+	private List<Player> players = new ArrayList<Player>();
+	private Context context;
+	
+	public PlayerListAdapter(Context context) {
+		this.context = context;
+	}
+	
+	public int getCount() {
+		return players.size();
+	}
+
+	public Object getItem(int position) {
+		return players.get(position);
+	}
+
+	public long getItemId(int position) {
+		return players.get(position).playerId;
+	}
+
+	public boolean hasStableIds() {
+		return true;
+	}
+
+	public void setPlayerList(Collection<Player> players) {
+		this.players = new ArrayList<Player>(players);
+		Collections.sort(this.players, Player.nameComparator);
+		notifyDataSetChanged();
+	}
+	
+	public View getView(int position, View convertView, ViewGroup parent) {
+		View v = convertView;
+		if (v == null) {
+			LayoutInflater vi = LayoutInflater.from(context);
+			v = vi.inflate(android.R.layout.simple_list_item_1, null);
+			TextView tv = (TextView)v.findViewById(android.R.id.text1);
+			tv.setCompoundDrawablePadding(5);
+			tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.human, 0, 0, 0);
+		}
+
+		String player = players.get(position).name;
+		TextView username = (TextView) v.findViewById(android.R.id.text1);
+		username.setText(player);
+		return v;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/PlayerlistFragment.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,33 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class PlayerlistFragment extends ListFragment {
+	List<Player> playerList;
+	Random random = new Random();
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		playerList = new ArrayList<Player>();
+		PlayerListAdapter playerListAdapter = new PlayerListAdapter(getActivity());
+		playerListAdapter.setPlayerList(playerList);
+		setListAdapter(playerListAdapter);
+	}
+
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		return inflater.inflate(R.layout.lobby_players_fragment, container, false);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/RoomlistFragment.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,28 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.os.Bundle;
+import android.support.v4.app.ListFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class RoomlistFragment extends ListFragment {
+	//List<Player> roomList;
+
+	@Override
+	public void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		/*playerList = new ArrayList<Player>();
+		PlayerListAdapter playerListAdapter = new PlayerListAdapter(getActivity());
+		playerListAdapter.setPlayerList(playerList);
+		setListAdapter(playerListAdapter);*/
+	}
+
+	@Override
+	public View onCreateView(LayoutInflater inflater, ViewGroup container,
+			Bundle savedInstanceState) {
+		return inflater.inflate(R.layout.lobby_rooms_fragment, container, false);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/project_files/Android-build/SDL-android-project/src/org/hedgewars/hedgeroid/netplay/TestActivity.java	Mon Jul 16 20:16:03 2012 +0200
@@ -0,0 +1,41 @@
+package org.hedgewars.hedgeroid.netplay;
+
+import org.hedgewars.hedgeroid.R;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+
+public class TestActivity extends FragmentActivity {
+	@Override
+	protected void onCreate(Bundle arg0) {
+		super.onCreate(arg0);
+		setContentView(R.layout.activity_lobby_paged);
+		ViewPager pager = (ViewPager)findViewById(R.id.pager);
+		pager.setAdapter(new Adapter(getSupportFragmentManager()));
+	}
+	
+	private static class Adapter extends FragmentPagerAdapter {
+		public Adapter(FragmentManager mgr) {
+			super(mgr);
+		}
+		
+		@Override
+		public int getCount() {
+			return 3;
+		}
+		
+		@Override
+		public Fragment getItem(int arg0) {
+			switch(arg0) {
+			case 0: return new RoomlistFragment();
+			case 1: return new LobbyChatFragment();
+			case 2: return new PlayerlistFragment();
+			default: throw new IndexOutOfBoundsException();
+			}
+		}
+	}
+}