diff options
author | Kjetil Ørbekk <kjetil.orbekk@gmail.com> | 2012-02-14 10:01:07 +0100 |
---|---|---|
committer | Kjetil Ørbekk <kjetil.orbekk@gmail.com> | 2012-02-14 10:01:07 +0100 |
commit | a43a6e3ea279a58815edafaf552a571789835e7f (patch) | |
tree | 835abf534c451ce5a41b281b53345753126aefbc /same-android/src/main/java/com/orbekk/same | |
parent | 10920b6036c13f82df151e5912f6b1fbbd7aca02 (diff) |
Rename com.orbekk{=>.same} in Android project.
Diffstat (limited to 'same-android/src/main/java/com/orbekk/same')
5 files changed, 491 insertions, 0 deletions
diff --git a/same-android/src/main/java/com/orbekk/same/GameController.java b/same-android/src/main/java/com/orbekk/same/GameController.java new file mode 100644 index 0000000..144d6af --- /dev/null +++ b/same-android/src/main/java/com/orbekk/same/GameController.java @@ -0,0 +1,80 @@ +package com.orbekk.same; + +import java.util.ArrayList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbekk.same.SameInterface; +import com.orbekk.same.StateChangedListener; +import com.orbekk.same.UpdateConflict; + +import android.graphics.Paint; + +public class GameController implements StateChangedListener { + private Logger logger = LoggerFactory.getLogger(getClass()); + private List<Player> remotePlayers = new ArrayList<Player>(); + private Player localPlayer; + private ChangeListener changeListener = null; + private SameInterface same; + + public static class Player { + public Paint color; + public float posX; + public float posY; + } + + public interface ChangeListener { + void playerStatesChanged(); + } + + public static Player newPlayer() { + Player player = new Player(); + player.color = new Paint(); + player.color.setARGB(255, 255, 0, 0); + player.posX = 0.5f; + player.posY = 0.5f; + return player; + } + + public static GameController create(Player localPlayer, + SameInterface same) { + GameController controller = new GameController(localPlayer, same); + same.addStateChangedListener(controller); + return controller; + } + + GameController(Player localPlayer, SameInterface same) { + this.localPlayer = localPlayer; + this.same = same; + } + + public void setMyPosition(float x, float y) { + this.localPlayer.posX = x; + this.localPlayer.posY = y; + changeListener.playerStatesChanged(); + try { + same.set("position", x + "," + y); + } catch (UpdateConflict e) { + logger.warn("Update failed.", e); + } + } + + public Player getLocalPlayer() { + return localPlayer; + } + + public List<Player> getRemotePlayers() { + return remotePlayers; + } + + public void setChangeListener(ChangeListener listener) { + this.changeListener = listener; + } + + @Override + public void stateChanged(String id, String data) { + logger.info("StateChanged({}, {})", id, data); + } +} diff --git a/same-android/src/main/java/com/orbekk/same/GameView.java b/same-android/src/main/java/com/orbekk/same/GameView.java new file mode 100644 index 0000000..b8463d2 --- /dev/null +++ b/same-android/src/main/java/com/orbekk/same/GameView.java @@ -0,0 +1,120 @@ +package com.orbekk.same; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbekk.same.State.Component; +import com.orbekk.same.ClientService; +import com.orbekk.same.Client; +import com.orbekk.same.SameInterface; +import com.orbekk.same.UpdateConflict; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +public class GameView extends SurfaceView implements SurfaceHolder.Callback { + private Logger logger = LoggerFactory.getLogger(getClass()); + private GameThread thread; + + static class GameThread extends Thread + implements GameController.ChangeListener { + private Logger logger = LoggerFactory.getLogger(getClass()); + private int height = 0; + private int width = 0; + private SurfaceHolder holder; + private Context context; + private Paint background; + private GameController controller; + + public GameThread(SurfaceHolder holder, Context context, + GameController controller) { + this.holder = holder; + this.context = context; + this.controller = controller; + this.controller.setChangeListener(this); + background = new Paint(); + background.setARGB(255, 0, 0, 0); + } + + public void setSize(int width, int height) { + synchronized(holder) { + this.width = width; + this.height = height; + } + } + + private void doDraw(Canvas c) { + c.drawRect(0.0f, 0.0f, width+1.0f, height+1.0f, background); + for (GameController.Player p : controller.getRemotePlayers()) { + c.drawCircle(p.posX * width, p.posY * height, 20.0f, p.color); + } + GameController.Player localPlayer = controller.getLocalPlayer(); + c.drawCircle(localPlayer.posX * width, localPlayer.posY * height, + 20.0f, localPlayer.color); + } + + @Override public void run() { + Canvas c = null; + try { + c = holder.lockCanvas(); + synchronized(holder) { + doDraw(c); + } + } finally { + holder.unlockCanvasAndPost(c); + } + } + + private synchronized void setPosition(float x, float y) { + controller.setMyPosition(x / this.width, y / this.height); + } + + @Override + public void playerStatesChanged() { + run(); + } + } + + public GameView(Context context, GameController controller) { + super(context); + getHolder().addCallback(this); + thread = new GameThread(getHolder(), context, controller); + } + + @Override + protected void onDraw(Canvas canvas) { + Paint paint = new Paint(); + paint.setARGB(255, 255, 0, 0); + canvas.drawCircle(50.0f, 50.0f, 50.0f, paint); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, + int height) { + logger.info("SurfaceChanged(w={}, h={})", width, height); + thread.setSize(width, height); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + logger.info("SurfaceCreated()"); + thread.start(); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + logger.info("SurfaceDestroyed()"); + // TODO: Stop thread. + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + thread.setPosition(e.getX(), e.getY()); + return true; + } + +} diff --git a/same-android/src/main/java/com/orbekk/same/MainActivity.java b/same-android/src/main/java/com/orbekk/same/MainActivity.java new file mode 100644 index 0000000..49053c8 --- /dev/null +++ b/same-android/src/main/java/com/orbekk/same/MainActivity.java @@ -0,0 +1,31 @@ +package com.orbekk.same; + +import com.orbekk.R; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Toast; + +public class MainActivity extends Activity { + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } + + @Override public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.main_menu, menu); + return true; + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.same_settings) { + startActivity(new Intent(this, SameControllerActivity.class)); + } + return true; + } +} diff --git a/same-android/src/main/java/com/orbekk/same/SameControllerActivity.java b/same-android/src/main/java/com/orbekk/same/SameControllerActivity.java new file mode 100644 index 0000000..e6bf257 --- /dev/null +++ b/same-android/src/main/java/com/orbekk/same/SameControllerActivity.java @@ -0,0 +1,131 @@ +package com.orbekk.same; + +import java.util.ArrayList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbekk.R; +import com.orbekk.same.android.net.Broadcaster; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.TextView; + +public class SameControllerActivity extends Activity { + private Logger logger = LoggerFactory.getLogger(getClass()); + private Messenger sameService = null; + + private ServiceConnection sameConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + sameService = new Messenger(service); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + sameService = null; + } + }; + + private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (SameService.AVAILABLE_NETWORKS_UPDATE.equals(intent.getAction())) { + ArrayList<String> networkList = intent.getStringArrayListExtra( + SameService.AVAILABLE_NETWORKS); + ListView list = (ListView)findViewById(R.id.network_list); + list.setAdapter(new ArrayAdapter<String>( + SameControllerActivity.this, + R.layout.list_text_item, networkList)); + } + } + }; + + public void createNetwork(View unused) { + logger.info("Creating network"); + Intent intent = new Intent(this, SameService.class); + intent.setAction("create"); + startService(intent); + } + + public void joinNetwork(View unused) { + logger.info("Joining network"); + Intent intent = new Intent(this, SameService.class); + intent.setAction("join"); + // InetAddress address = new Broadcaster(this).getBroadcastAddress(); + EditText t = (EditText)findViewById(R.id.master_service_url); + intent.putExtra("masterUrl", t.getText().toString()); + startService(intent); + } + + private void showIpAddress() { + TextView t = (TextView)findViewById(R.id.ipAddress); + t.setText("My IP: "); + t.append(new Broadcaster(this).getWlanAddress().getHostAddress()); + } + + public void doneClicked(View unused) { + finish(); + } + + public void searchNetworks(View unused) { + logger.info("SearchNetworks()"); + Message searchMessage = Message.obtain(null, SameService.SEARCH_NETWORKS); + try { + sameService.send(searchMessage); + } catch (RemoteException e) { + logger.error("Failed to send message", e); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + System.setProperty("java.net.preferIPv4Stack", "true"); + System.setProperty("java.net.preferIPv6Addresses", "false"); + + setContentView(R.layout.controller); + showIpAddress(); + } + + @Override public void onResume() { + super.onResume(); + + Intent intent = new Intent(this, SameService.class); + bindService(intent, sameConnection, Context.BIND_AUTO_CREATE); + + IntentFilter sameServiceUpdates = new IntentFilter( + SameService.AVAILABLE_NETWORKS_UPDATE); + registerReceiver(broadcastReceiver, sameServiceUpdates); + } + + @Override public void onStop() { + super.onStop(); + if (sameService != null) { + unbindService(sameConnection); + } + unregisterReceiver(broadcastReceiver); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } +} + diff --git a/same-android/src/main/java/com/orbekk/same/SameService.java b/same-android/src/main/java/com/orbekk/same/SameService.java new file mode 100644 index 0000000..f4cf3e2 --- /dev/null +++ b/same-android/src/main/java/com/orbekk/same/SameService.java @@ -0,0 +1,129 @@ +package com.orbekk.same; + +import java.util.ArrayList; +import java.util.Properties; + +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.widget.Toast; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.orbekk.same.NetworkNotificationListener; +import com.orbekk.same.SameController; +import com.orbekk.same.android.net.AndroidBroadcasterFactory; +import com.orbekk.same.android.net.Broadcaster; +import com.orbekk.same.config.Configuration; + +public class SameService extends Service { + public final static int DISPLAY_MESSAGE = 1; + public final static int SEARCH_NETWORKS = 2; + + public final static String AVAILABLE_NETWORKS_UPDATE = + "com.orbekk.same.SameService.action.AVAILABLE_NETWORKS_UPDATE"; + public final static String AVAILABLE_NETWORKS = + "com.orbekk.same.SameService.action.AVAILABLE_NETWORKS"; + + final static int SERVICE_PORT = 15068; + final static int DISCOVERY_PORT = 15066; + + private Logger logger = LoggerFactory.getLogger(getClass()); + private SameController sameController = null; + private Configuration configuration = null; + + private ArrayList<String> networkNames = new ArrayList<String>(); + private ArrayList<String> networkUrls = new ArrayList<String>(); + + private NetworkNotificationListener networkListener = + new NetworkNotificationListener() { + @Override + public void notifyNetwork(String networkName, String masterUrl) { + logger.info("notifyNetwork({})", networkName); + networkNames.add(networkName); + networkUrls.add(masterUrl); + Intent intent = new Intent(AVAILABLE_NETWORKS_UPDATE); + intent.putStringArrayListExtra(AVAILABLE_NETWORKS, + networkNames); + sendBroadcast(intent); + } + }; + + class InterfaceHandler extends Handler { + @Override public void handleMessage(Message message) { + switch (message.what) { + case DISPLAY_MESSAGE: + Toast.makeText(SameService.this, + (String)message.obj, Toast.LENGTH_SHORT) + .show(); + break; + case SEARCH_NETWORKS: + logger.info("SEARCH_NETWORKS"); + sameController.searchNetworks(); + break; + default: + super.handleMessage(message); + } + } + } + + private final Messenger messenger = new Messenger(new InterfaceHandler()); + + private void initializeConfiguration() { + Properties properties = new Properties(); + properties.setProperty("port", ""+SERVICE_PORT); + properties.setProperty("localIp", + new Broadcaster(this).getWlanAddress().getHostAddress()); + properties.setProperty("masterUrl", "http://10.0.0.6:10010/MasterService.json"); + properties.setProperty("discoveryPort", ""+DISCOVERY_PORT); + configuration = new Configuration(properties); + } + + @Override + public IBinder onBind(Intent intent) { + logger.info("onBind()"); + + // Make sure service continues to run after it is unbound. + Intent service = new Intent(this, getClass()); + startService(service); + + return messenger.getBinder(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + logger.info("onStartCommand()"); + return START_STICKY; + } + + @Override + public void onCreate() { + logger.info("onCreate()"); + + if (sameController == null) { + initializeConfiguration(); + sameController = SameController.create( + new AndroidBroadcasterFactory(this), + configuration); + try { + sameController.start(); + sameController.getClient().setNetworkListener(networkListener); + } catch (Exception e) { + logger.error("Failed to start server", e); + } + } + } + + @Override + public void onDestroy() { + logger.info("onDestroy()"); + if (sameController != null) { + sameController.stop(); + } + } + +} |