<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/items/Obstacle.java<|end_filename|>
package com.spiretos.spaceremote.game.items;

import android.graphics.RectF;

import java.util.Random;

/**
 * Created by spiretos on 3/4/2016.
 */
public class Obstacle
{

    int margin = 50;
    int position;

    boolean active;

    long creationTime;
    float speed;

    float size;


    public Obstacle(int spaceWidth)
    {
        creationTime = System.currentTimeMillis();

        active = true;
        position = new Random().nextInt(spaceWidth - 2 * margin) + margin;
        size = new Random().nextFloat() * 50f + 50f;
        speed = new Random().nextFloat() * 250f + 250f;
    }


    public int getPosition()
    {
        return position;
    }


    public boolean isActive()
    {
        return active;
    }

    public void setActive(boolean active)
    {
        this.active = active;
    }

    public float getDistance()
    {
        long elapsedTime = System.currentTimeMillis() - creationTime;
        return elapsedTime * speed / 1000f;
    }

    public float getSize()
    {
        return size;
    }

    public RectF getRect(float obstacleDistance)
    {
        return new RectF((float) position - size / 2f, obstacleDistance - size / 2f, (float) position + size / 2f, obstacleDistance + size / 2f);
    }
}


<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/utils/DataUtils.java<|end_filename|>
package com.spiretos.wearemote.utils;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Created by spiretos on 27/3/2016.
 */
public class DataUtils
{

    public static byte[] getByteArrayFrom(float value)
    {
        return ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putFloat(value).array();
    }
    public static float getFloatFrom(byte[] bytes)
    {
        return ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getFloat();
    }

    public static byte[] getByteArray(String text)
    {
        try
        {
            return text.getBytes("UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
            return new byte[0];
        }
    }
    public static String getStringFrom(byte[] bytes)
    {
        try
        {
            return new String(bytes, "UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
            return "";
        }
    }

    public static float getFloatFrom(String text)
    {
        try
        {
            return Float.parseFloat(text);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            return 0f;
        }
    }

}


<|start_filename|>SpaceRemote/wear/src/main/java/com/spiretos/spaceremote/SpaceRemoteActivity.java<|end_filename|>
package com.spiretos.spaceremote;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;

import com.spiretos.wearemote.communication.Communicator;
import com.spiretos.wearemote.sensor.SensorActivity;
import com.spiretos.wearemote.sensor.WearSensor;

public class SpaceRemoteActivity extends SensorActivity
{

    private ImageView mShipImage;

    float tempY, tempValue, lastSendValue;



    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_space_remote);
        setAmbientEnabled();

        mShipImage = (ImageView) findViewById(R.id.ship_image);

        addSensor("accelerometer", Sensor.TYPE_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME);

        setCommunicationType(Communicator.TYPE_MESSAGE_API);
        //setCommunicationType(Communicator.TYPE_CHANNEL_API);
    }


    @Override
    protected void onGotSensorData(WearSensor sensor, SensorEvent event)
    {
        if (sensor.getName().equals("accelerometer"))
        {
            tempY = event.values[1];
            tempValue = 0;

            if (tempY < -6)
                tempValue = -3f;
            else if (tempY < -4)
                tempValue = -2f;
            else if (tempY < -2)
                tempValue = -1f;
            else if (tempY > 6)
                tempValue = 3f;
            else if (tempY > 4)
                tempValue = 2f;
            else if (tempY > 2)
                tempValue = 1f;
            else
                tempValue = 0;

            if (tempValue != lastSendValue)
            {
                lastSendValue = tempValue;
                sendSensorData("accelerometer_Y", lastSendValue);
                updateImage((int) lastSendValue);
            }
        }
    }

    private void updateImage(int value)
    {
        if (value == 0)
            mShipImage.setImageResource(R.drawable.ship0);
        else if (value == 1)
            mShipImage.setImageResource(R.drawable.ship2r);
        else if (value == -1)
            mShipImage.setImageResource(R.drawable.ship2l);
        else if (value == 2)
            mShipImage.setImageResource(R.drawable.ship2r);
        else if (value == -2)
            mShipImage.setImageResource(R.drawable.ship2l);
        else if (value == 3)
            mShipImage.setImageResource(R.drawable.ship3r);
        else if (value == -3)
            mShipImage.setImageResource(R.drawable.ship3l);
        else if (value == 4)
            mShipImage.setImageResource(R.drawable.ship4r);
        else if (value == -4)
            mShipImage.setImageResource(R.drawable.ship4l);
    }

}

<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/items/SpaceShip.java<|end_filename|>
package com.spiretos.spaceremote.game.items;

/**
 * Created by spiretos on 12/4/2016.
 */
public class SpaceShip
{

    float position;
    float speed;
    float availableWidth;

    private long lastTime;



    public SpaceShip()
    {
        lastTime = System.currentTimeMillis();
        position = -1;
    }

    public void setSpeed(float speed)
    {
        this.speed = speed;
    }

    public void setAvailableSpace(float width)
    {
        availableWidth = width;
    }

    public void calculatePosition()
    {
        if (position == -1) //first time
            position = availableWidth / 2f;
        else
        {
            long elapsedTime = System.currentTimeMillis() - lastTime;
            position += elapsedTime * speed / 1000f;

            if (position < 30)
                position = 30;
            else if (position > availableWidth - 20)
                position = availableWidth - 20;

            lastTime = System.currentTimeMillis();
        }
    }

    public float getPosition()
    {
        return position;
    }
}

<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/receiver/ReceiverActivity.java<|end_filename|>
package com.spiretos.wearemote.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.spiretos.wearemote.communication.AppListenerService;
import com.spiretos.wearemote.communication.Communicator;

/**
 * Created by spiretos on 8/4/2016.
 */
public abstract class ReceiverActivity extends AppCompatActivity
{

    Communicator mCommunicator;


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        mCommunicator = new Communicator(this);
        mCommunicator.setCommunicationListener(new Communicator.CommunicationListener()
        {
            @Override
            public void onConnected()
            {
                OnConnectedWithWear();
            }
        });
        mCommunicator.connect();
    }


    protected void OnConnectedWithWear()
    {
        mCommunicator.sendMessage(Communicator.MESSAGE_START_ACTIVITY);
    }


    @Override
    protected void onResume()
    {
        super.onResume();

        LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("sensor_data"));
    }

    @Override
    protected void onPause()
    {
        if (mMessageReceiver != null)
        {
            LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
        }

        super.onPause();
    }


    protected abstract void OnReceivedRemoteValue(String type, float value);

    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver()
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            String type=intent.getStringExtra("type");
            float yValue = intent.getFloatExtra("value", 0);

            //Log.w("m-", "*** GOT '" + type + "'=" + yValue);

            //onYchanged(yValue);
            OnReceivedRemoteValue(type, yValue);
        }
    };


    protected Communicator getCommunicator()
    {
        return mCommunicator;
    }
}

<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/sensor/WearSensor.java<|end_filename|>
package com.spiretos.wearemote.sensor;

import android.hardware.Sensor;

/**
 * Created by spiretos on 11/4/2016.
 */
public class WearSensor
{

    private String name;
    private Sensor sensor;
    private int delay;
    private int sensorType;


    public WearSensor(String sensorName, Sensor sensor, int sensorDelay)
    {
        name = sensorName;
        this.sensor = sensor;
        delay = sensorDelay;

        sensorType = sensor.getType();
    }


    public String getName()
    {
        return name;
    }

    public Sensor getSensor()
    {
        return sensor;
    }

    public int getSensorDelay()
    {
        return delay;
    }

    public int getSensorType()
    {
        return sensorType;
    }

}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/GameActivity.java<|end_filename|>
package com.spiretos.spaceremote.game;

import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;

import com.spiretos.spaceremote.R;
import com.spiretos.spaceremote.communication.GameDataReceiver;
import com.spiretos.spaceremote.game.canvas.BasicSurfaceCallback;
import com.spiretos.spaceremote.game.canvas.GameLoopThread;
import com.spiretos.wearemote.receiver.ReceiverActivity;

public class GameActivity extends ReceiverActivity
{

    public static final String GAME_SPACE = "game_space";


    TextView mDataText;

    SurfaceView mSurface;
    SpaceRemoteGameEngine mGameEngine;
    GameLoopThread mGameLoop;


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_game);

        setupGame();

        mDataText = (TextView) findViewById(R.id.game_datatext);
    }


    private void setupGame()
    {
        mSurface = (SurfaceView) findViewById(R.id.game_surface);

        SurfaceHolder mSurfaceHolder = mSurface.getHolder();

        String game = getIntent().getStringExtra("game");
        if (game.equals(GAME_SPACE))
        {
            mGameEngine = new SpaceRemoteGameEngine(this);
            mGameLoop = new GameLoopThread(mSurfaceHolder, mGameEngine);
            mSurfaceHolder.addCallback(new BasicSurfaceCallback(mGameLoop));
        }
    }


    @Override
    protected void OnReceivedRemoteValue(String type, float value)
    {
        if (mGameEngine != null)
        {
            mGameEngine.setShipSpeed(value);
        }
    }


    @Override
    protected void onResume()
    {
        super.onResume();

        if (mGameLoop != null)
            mGameLoop.setRunning(true);
    }

    @Override
    protected void onPause()
    {
        if (mGameLoop != null)
            mGameLoop.setRunning(false);

        super.onPause();
    }
}


<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/communication/WearCommandsReceiver.java<|end_filename|>
package com.spiretos.wearemote.communication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Created by spiretos on 12/4/2016.
 */
public abstract class WearCommandsReceiver extends BroadcastReceiver
{

    @Override
    public void onReceive(Context context, Intent intent)
    {
        executeCommand(context, intent);
    }

    protected abstract void executeCommand(Context context, Intent intent);

}

<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/SpaceRemoteGameEngine.java<|end_filename|>
package com.spiretos.spaceremote.game;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;

import com.spiretos.spaceremote.R;
import com.spiretos.spaceremote.game.canvas.BasicGameEngine;
import com.spiretos.spaceremote.game.items.Obstacle;
import com.spiretos.spaceremote.game.items.SpaceShip;

import java.util.ArrayList;

/**
 * Created by spiretos on 29/3/2016.
 */
public class SpaceRemoteGameEngine implements BasicGameEngine
{

    private SpaceShip mShip;

    Paint backPaint;
    Paint shipPaint;

    ArrayList<Obstacle> mObstacles;

    int spawnObstacleInterval = 800;
    long lastObstacleTime = System.currentTimeMillis();


    Obstacle obstacle;
    float obstacleDistance;

    Bitmap shipImage, asteroidImage;
    Rect shipRect, asteroidRect;




    public SpaceRemoteGameEngine(Context context)
    {
        backPaint = new Paint();
        backPaint.setColor(Color.BLACK);

        shipPaint = new Paint();
        shipPaint.setColor(Color.YELLOW);

        mObstacles = new ArrayList<>();

        mShip = new SpaceShip();

        shipImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.ship);
        shipRect = new Rect(0, 0, shipImage.getWidth(), shipImage.getHeight());
        asteroidImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.asteroid);
        asteroidRect = new Rect(0, 0, asteroidImage.getWidth(), asteroidImage.getHeight());
    }



    @Override
    public void update(Canvas canvas)
    {
        long currentTime = System.currentTimeMillis();

        mShip.setAvailableSpace(canvas.getWidth());
        mShip.calculatePosition();

        for (int i = mObstacles.size() - 1; i >= 0; i--)
        {
            obstacle = mObstacles.get(i);
            if (!obstacle.isActive())
                mObstacles.remove(i);
        }

        if (currentTime - lastObstacleTime > spawnObstacleInterval)
        {
            obstacle = new Obstacle(canvas.getWidth());
            mObstacles.add(obstacle);
            lastObstacleTime = currentTime;
        }
    }

    @Override
    public void Draw(Canvas canvas)
    {
        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), backPaint);

        for (int i = 0; i < mObstacles.size(); i++)
        {
            obstacle = mObstacles.get(i);
            if (obstacle.isActive())
            {
                obstacleDistance = obstacle.getDistance();

                //canvas.drawCircle(obstacle.getPosition(), obstacle.getDistance(), obstacle.getSize(), shipPaint);
                canvas.drawBitmap(asteroidImage, asteroidRect, obstacle.getRect(obstacleDistance), backPaint);
                if (obstacleDistance > canvas.getHeight() + 100)
                    obstacle.setActive(false);
            }
        }

        //float x = canvas.getWidth() / 2f + mShip.getPosition() * 1000f;
        float x = mShip.getPosition();

        //canvas.drawCircle(x, canvas.getHeight() - 50f, 10f, shipPaint);
        float shipSize = 60f;
        canvas.drawBitmap(shipImage, asteroidRect,
                new RectF((float) x - shipSize / 2f, canvas.getHeight() - 50f - shipSize / 2f,
                        (float) x + shipSize / 2f, canvas.getHeight() - 50f + shipSize / 2f)
                , backPaint);
    }

    public void setShipSpeed(float y)
    {
        mShip.setSpeed(y * 130f);
    }

}


<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/sensor/SensorActivity.java<|end_filename|>
package com.spiretos.wearemote.sensor;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.wearable.activity.WearableActivity;
import android.util.Log;

import com.spiretos.wearemote.communication.Communicator;
import com.spiretos.wearemote.utils.DataUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by spiretos on 9/4/2016.
 */
public abstract class SensorActivity extends WearableActivity implements SensorEventListener
{

    private SensorManager mSensorManager;
    private List<WearSensor> mSensors;

    Communicator mCommunicator;
    private int mCommunicationType = Communicator.TYPE_MESSAGE_API;


    WearSensor tempSensor;



    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        mCommunicator = new Communicator(this);
        mCommunicator.connect();

        mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mSensors = new ArrayList<>();
    }



    protected void addSensor(String sensorName, int sensorType)
    {
        addSensor(sensorName, sensorType, SensorManager.SENSOR_DELAY_NORMAL);
    }

    protected void addSensor(String sensorName, int sensorType, int sensorDelay)
    {
        if (mSensorManager != null)
        {
            Sensor sensor = mSensorManager.getDefaultSensor(sensorType);

            WearSensor newSensor = new WearSensor(sensorName, sensor, sensorDelay);

            mSensors.add(newSensor);
        }
    }


    protected void setCommunicationType(int communicationType)
    {
        mCommunicationType = communicationType;
    }


    @Override
    protected void onResume()
    {
        super.onResume();

        if (mSensorManager != null)
        {
            for (WearSensor sensor : mSensors)
            {
                mSensorManager.registerListener(this, sensor.getSensor(), sensor.getSensorDelay());
            }
        }
    }

    @Override
    protected void onPause()
    {
        if (mSensorManager != null)
            mSensorManager.unregisterListener(this);

        super.onPause();
    }




    @Override
    public void onSensorChanged(SensorEvent event)
    {
        tempSensor = getSensor(event);
        onGotSensorData(tempSensor, event);
    }

    protected abstract void onGotSensorData(WearSensor sensor, SensorEvent event);

    private WearSensor getSensor(SensorEvent event)
    {
        for (WearSensor sensor : mSensors)
            if (sensor.getSensor().getType() == event.sensor.getType())
                return sensor;
        return null;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy)
    {

    }


    protected void sendSensorData(String tag, float value)
    {
        if (mCommunicator != null)
        {
            if (mCommunicationType == Communicator.TYPE_MESSAGE_API)
            {
                mCommunicator.sendMessage(tag, DataUtils.getByteArray(String.valueOf(value)));
            }
            else if (mCommunicationType == Communicator.TYPE_CHANNEL_API && mCommunicator.isChannelCreated())
            {
                mCommunicator.writeData(tag, DataUtils.getByteArray(String.valueOf(value) + "!"));
            }
        }
    }

}

<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/communication/AppListenerService.java<|end_filename|>
package com.spiretos.wearemote.communication;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.Channel;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import com.spiretos.wearemote.utils.DataUtils;

import java.io.InputStream;

/**
 * Created by spiretos on 27/3/2016.
 */
public class AppListenerService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
{

    public static final String RECEIVED_Y_DATA = "RECEIVED_Y_DATA";

    private GoogleApiClient mGoogleApiClient;
    private Channel mDataChannel;



    @Override
    public void onMessageReceived(MessageEvent messageEvent)
    {
        super.onMessageReceived(messageEvent);

        //Log.w("m-", "message received");

        if (messageEvent.getPath().equals(Communicator.MESSAGE_START_ACTIVITY))
        {
            Log.w("received", Communicator.MESSAGE_START_ACTIVITY);
            Intent intent = new Intent(Communicator.BROADCAST_SENSOR_ACTIVITY_COMMAND);
            intent.putExtra("command",Communicator.MESSAGE_START_ACTIVITY);
            sendBroadcast(intent);
        }
        if (messageEvent.getPath().equals(Communicator.MESSAGE_FINISH_ACTIVITY))
        {
            Log.w("received", Communicator.MESSAGE_FINISH_ACTIVITY);
            Intent intent = new Intent(Communicator.BROADCAST_SENSOR_ACTIVITY_COMMAND);
            intent.putExtra("command",Communicator.MESSAGE_FINISH_ACTIVITY);
            sendBroadcast(intent);
        }
        else
        {
            try
            {
                float sensorValue = DataUtils.getFloatFrom(DataUtils.getStringFrom(messageEvent.getData()));

                //Log.w("m-", "got '" + messageEvent.getPath() + "'=" + sensorValue);

                Intent intent = new Intent("sensor_data");
                intent.putExtra("type",messageEvent.getPath());
                intent.putExtra("value", sensorValue);
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public void onChannelOpened(Channel channel)
    {
        super.onChannelOpened(channel);

        Log.v("channel", "openned");
        mDataChannel = channel;

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        mGoogleApiClient.connect();

    }

    @Override
    public void onConnected(@Nullable Bundle bundle)
    {
        /*if (mDataChannel != null)
        {
            mDataChannel.getInputStream(mGoogleApiClient).setResultCallback(new ResultCallback<Channel.GetInputStreamResult>()
            {
                @Override
                public void onResult(@NonNull Channel.GetInputStreamResult getInputStreamResult)
                {
                    Thread t = new Thread(new TestThread(getInputStreamResult));
                    t.start();
                }
            });
        }*/
    }

    public class TestThread implements Runnable
    {

        private final Channel.GetInputStreamResult getInputStreamResult;

        public TestThread(Channel.GetInputStreamResult getInputStreamResult)
        {
            this.getInputStreamResult = getInputStreamResult;
        }

        @Override
        public void run()
        {
            try
            {
                InputStream inputStream = getInputStreamResult.getInputStream();
                int i;
                char c;
                String s = "";
                while ((i = inputStream.read()) != -1)
                {
                    c = (char) i;

                    if (c == '!')
                    {
                        final float yValue = DataUtils.getFloatFrom(s);

                        Intent intent = new Intent(RECEIVED_Y_DATA);
                        intent.putExtra("data_y", yValue);
                        LocalBroadcastManager.getInstance(AppListenerService.this).sendBroadcast(intent);

                        Thread.sleep(5);
                        s = "";
                    }
                    else
                        s += c;
                }
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public void onConnectionSuspended(int i)
    {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
    {

    }
}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/canvas/BasicGameCanvas.java<|end_filename|>
package com.spiretos.spaceremote.game.canvas;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by spiretos on 29/3/2016.
 */
public class BasicGameCanvas extends SurfaceView implements SurfaceHolder.Callback
{

    GameLoopThread mGameLoop;
    SurfaceHolder mSurfaceHolder;


    public BasicGameCanvas(Context context)
    {
        super(context);

        initialize();
    }

    public BasicGameCanvas(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        initialize();
    }

    public BasicGameCanvas(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);

        initialize();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public BasicGameCanvas(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);

        initialize();
    }

    private void initialize()
    {
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);

        //mGameLoop = new GameLoopThread(mSurfaceHolder);

        //setFocusable(true);
    }




    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        mGameLoop.setRunning(true);
        mGameLoop.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        boolean retry = true;
        while (retry)
        {
            try
            {
                mGameLoop.join();
                retry = false;
            }
            catch (InterruptedException e)
            {
                // try again shutting down the thread
            }
        }
    }

}


<|start_filename|>SpaceRemote/wear/src/main/java/communication/AppListenerService123.java<|end_filename|>
package communication;

import android.content.Intent;
import android.os.Vibrator;

import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.WearableListenerService;
import com.spiretos.spaceremote.SpaceRemoteActivity;

/**
 * Created by spiretos on 26/3/2016.
 */
public class AppListenerService123 extends WearableListenerService
{

    public static final String START_ACTIVITY_PATH = "/start/MainActivity";


    @Override
    public void onMessageReceived(MessageEvent messageEvent)
    {
        super.onMessageReceived(messageEvent);

        if (messageEvent.getPath().equals(START_ACTIVITY_PATH))
        {
            Intent intent = new Intent(this, SpaceRemoteActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

            Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
            long[] vibrationPattern = {0, 75, 50, 75};
            vibrator.vibrate(vibrationPattern, -1);
        }
    }

}


<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/communication/Communicator.java<|end_filename|>
package com.spiretos.wearemote.communication;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.Channel;
import com.google.android.gms.wearable.ChannelApi;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.Wearable;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by spiretos on 27/3/2016.
 */
public class Communicator implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener
{

    public static final int TYPE_MESSAGE_API = 0;
    public static final int TYPE_CHANNEL_API = 1;

    public static final String MESSAGE_START_ACTIVITY="MESSAGE_START_ACTIVITY";
    public static final String MESSAGE_FINISH_ACTIVITY="MESSAGE_FINISH_ACTIVITY";

    public static final String BROADCAST_SENSOR_ACTIVITY_COMMAND="com.spiretos.wearemote.SENSOR_ACTIVITY_COMMAND";


    GoogleApiClient mGoogleApiClient;
    Context mContext;

    Node mNode;
    private OutputStream mOutputStream;

    boolean channelCreated;



    public Communicator(Context context)
    {
        mContext = context;
    }

    public void connect()
    {
        mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        mGoogleApiClient.connect();
    }


    @Override
    public void onConnected(@Nullable Bundle bundle)
    {
        Log.v("app", "onConnected");

        Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>()
        {
            @Override
            public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult)
            {
                int nodesSize = getConnectedNodesResult.getNodes().size();

                Log.v("app", "getConnectedNodes: " + nodesSize);

                if (nodesSize > 0)
                {
                    mNode = getConnectedNodesResult.getNodes().get(0);
                    sendConnected();

                    //createChannel();
                }
            }
        });
    }

    @Override
    public void onConnectionSuspended(int i)
    {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult)
    {

    }


    public void sendMessage(String command)
    {
        sendMessage(command, new byte[0]);
    }

    public void sendMessage(String command, byte[] data)
    {
        if (mNode == null)
            return;

        Wearable.MessageApi.sendMessage(mGoogleApiClient, mNode.getId(), command, data).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>()
        {
            @Override
            public void onResult(MessageApi.SendMessageResult sendMessageResult)
            {
                /*if (!sendMessageResult.getStatus().isSuccess())
                {

                }*/
            }
        });
    }



    private void createChannel()
    {
        Wearable.ChannelApi.openChannel(mGoogleApiClient, mNode.getId(), "data_channel").setResultCallback(new ResultCallback<ChannelApi.OpenChannelResult>()
        {
            @Override
            public void onResult(@NonNull ChannelApi.OpenChannelResult openChannelResult)
            {
                Channel channel = openChannelResult.getChannel();
                channel.getOutputStream(mGoogleApiClient).setResultCallback(new ResultCallback<Channel.GetOutputStreamResult>()
                {
                    @Override
                    public void onResult(@NonNull Channel.GetOutputStreamResult getOutputStreamResult)
                    {
                        mOutputStream = getOutputStreamResult.getOutputStream();
                        Log.v("channel", "created");
                        channelCreated=true;
                    }
                });
            }
        });
    }

    public void writeData(String command, byte[] data)
    {
        try
        {
            if (mOutputStream!=null)
            {
                mOutputStream.write(data);
                //Log.v("data","wear sent");
            }
        }
        catch (IOException e)
        {
            //e.printStackTrace();
        }
    }


    public boolean isChannelCreated()
    {
        return channelCreated;
    }






    // EVENTS

    public void setCommunicationListener(CommunicationListener listener)
    {
        addListener(listener);
    }

    public void removeCommunicationListener(CommunicationListener listener)
    {
        removeListener(listener);
    }

    private void sendConnected()
    {
        for (CommunicationListener l : mListeners)
        {
            l.onConnected();
        }
    }

    public interface CommunicationListener
    {
        public void onConnected();
    }

    List<CommunicationListener> mListeners = new ArrayList<CommunicationListener>();

    private void addListener(CommunicationListener toAdd)
    {
        mListeners.add(toAdd);
    }

    public void removeListener(CommunicationListener toRemove)
    {
        mListeners.remove(toRemove);
    }

}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/canvas/BasicGameEngine.java<|end_filename|>
package com.spiretos.spaceremote.game.canvas;

import android.graphics.Canvas;

/**
 * Created by spiretos on 29/3/2016.
 */
public interface BasicGameEngine
{

    void update(Canvas canvas);
    void Draw(Canvas canvas);

}


<|start_filename|>SpaceRemote/wear/src/main/java/com/spiretos/spaceremote/SpaceRemoteCommandsReceiver.java<|end_filename|>
package com.spiretos.spaceremote;

import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;

import com.spiretos.wearemote.communication.Communicator;
import com.spiretos.wearemote.communication.WearCommandsReceiver;

/**
 * Created by spiretos on 12/4/2016.
 */
public class SpaceRemoteCommandsReceiver extends WearCommandsReceiver
{

    @Override
    protected void executeCommand(Context context, Intent intent)
    {
        String message=intent.getStringExtra("command");

        if (message.equals(Communicator.MESSAGE_START_ACTIVITY))
        {
            startActivity(context);
        }
        /*else if (message.equals(Communicator.MESSAGE_FINISH_ACTIVITY))
        {
            //local broadcast to finish activity?
        }*/
    }

    private void startActivity(Context context)
    {
        Intent intent = new Intent(context, SpaceRemoteActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);

        Vibrator vibrator = (Vibrator) context.getSystemService(context.VIBRATOR_SERVICE);
        long[] vibrationPattern = {0, 75, 50, 75};
        vibrator.vibrate(vibrationPattern, -1);
    }

}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/MainActivity.java<|end_filename|>
package com.spiretos.spaceremote;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

import com.spiretos.spaceremote.game.GameActivity;

public class MainActivity extends AppCompatActivity
{

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button spaceRemoteButton=(Button) findViewById(R.id.main_spaceremote_button);
        spaceRemoteButton.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent gameIntent=new Intent(MainActivity.this, GameActivity.class);
                gameIntent.putExtra("game",GameActivity.GAME_SPACE);
                startActivity(gameIntent);
            }
        });
    }
}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/canvas/GameLoopThread.java<|end_filename|>
package com.spiretos.spaceremote.game.canvas;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

/**
 * Created by spiretos on 29/3/2016.
 */
public class GameLoopThread extends Thread
{

    private boolean mIsRunning;

    SurfaceHolder mHolder;
    BasicGameEngine mEngine;



    public GameLoopThread(SurfaceHolder holder, BasicGameEngine engine)
    {
        mHolder = holder;
        mEngine = engine;
    }




    public void setRunning(boolean running)
    {
        this.mIsRunning = running;
    }

    @Override
    public void run()
    {
        while (mIsRunning)
        {
            Canvas canvas = mHolder.lockCanvas(null);

            if (canvas != null)
                mEngine.update(canvas);

            if (canvas != null)
            {
                synchronized (mHolder)
                {
                    mEngine.Draw(canvas);
                }
                mHolder.unlockCanvasAndPost(canvas);
            }

            try
            {
                Thread.sleep(10);
            }
            catch (InterruptedException ex)
            {
                ex.printStackTrace();
            }
        }
    }

}




<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/communication/GameDataReceiver.java<|end_filename|>
package com.spiretos.spaceremote.communication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by spiretos on 28/3/2016.
 */
public class GameDataReceiver extends BroadcastReceiver
    {
        @Override
        public void onReceive(Context context, Intent intent)
        {
            float yValue= intent.getFloatExtra("data_y", 0);
            //Log.v("data1", yValue + "");

            sendYchanged(yValue);
        }



        // EVENTS

        public void setGameDataListener(GameDataListener listener)
        {
            addListener(listener);
        }

        public void removeGameDataListener(GameDataListener listener)
        {
            removeListener(listener);
        }

        private void sendYchanged(float yValue)
        {
            for (GameDataListener l : mListeners)
            {
                l.onYchanged(yValue);
            }
        }

        public interface GameDataListener
        {
            public void onYchanged(float yValue);
        }

        List<GameDataListener> mListeners = new ArrayList<GameDataListener>();

        private void addListener(GameDataListener toAdd)
        {
            mListeners.add(toAdd);
        }

        public void removeListener(GameDataListener toRemove)
        {
            mListeners.remove(toRemove);
        }

}


<|start_filename|>SpaceRemote/wearemote/src/main/java/com/spiretos/wearemote/receiver/ReceiverActivity1.java<|end_filename|>
package com.spiretos.wearemote.receiver;

import android.os.Bundle;

/**
 * Created by spiretos on 9/4/2016.
 */
public class ReceiverActivity1// extends ReceiverActivity
{

    /*@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);


    }

    @Override
    protected void OnConnectedWithWear()
    {
        super.OnConnectedWithWear();


    }*/

}


<|start_filename|>SpaceRemote/mobile/src/main/java/com/spiretos/spaceremote/game/canvas/BasicSurfaceCallback.java<|end_filename|>
package com.spiretos.spaceremote.game.canvas;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * Created by spiretos on 29/3/2016.
 */
public class BasicSurfaceCallback implements SurfaceHolder.Callback
{

    GameLoopThread mGameLoop;


    public BasicSurfaceCallback(GameLoopThread gameloop)
    {
        mGameLoop=gameloop;
    }




    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        mGameLoop.setRunning(true);
        mGameLoop.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
    {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        boolean retry = true;
        while (retry)
        {
            try
            {
                mGameLoop.join();
                retry = false;
            }
            catch (InterruptedException e)
            {
                // try again shutting down the thread
            }
        }
    }

}
