From 0c6e649539bfc3d66f163687aa5cb409c3084c80 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Mon, 17 Apr 2017 01:06:29 +0200 Subject: [PATCH 01/48] Added working upd multicast --- .../jackss/ag/macroboard/network/Beacon.java | 123 ++++++++++++++++++ .../ui/activities/MainActivity.java | 18 +++ 2 files changed, 141 insertions(+) create mode 100644 app/src/main/java/com/jackss/ag/macroboard/network/Beacon.java diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/Beacon.java b/app/src/main/java/com/jackss/ag/macroboard/network/Beacon.java new file mode 100644 index 0000000..38c8479 --- /dev/null +++ b/app/src/main/java/com/jackss/ag/macroboard/network/Beacon.java @@ -0,0 +1,123 @@ +package com.jackss.ag.macroboard.network; + +import android.util.Log; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.InetAddress; +import java.net.MulticastSocket; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * + */ +public class Beacon +{ + private static final String TAG = "Beacon"; + + /** Task which multicast a DatagramPacket over the network. Can be cancelled */ + private static class BeaconTask implements Runnable + { + @Override + public void run() + { + final int port = 4545; + MulticastSocket multicastSocket = null; + + Log.v(TAG, "Beacon start..."); + + try + { + InetAddress group = InetAddress.getByName("230.185.192.108"); + multicastSocket = new MulticastSocket(port); //TODO: needs to call leaveGroup? + + // {/* + // {Enumeration l = NetworkInterface.getNetworkInterfaces(); + // while(l.hasMoreElements()) + // { + // NetworkInterface i = l.nextElement(); + // + // if(i.isUp() && !i.isLoopback()) + // { + // TAG.v(TAG, i.getName()); + // } + // + // } + // multicastSocket.setNetworkInterface(NetworkInterface.getByName("rndis0"));} + // TAG.v(TAG, "run: Beacon starting on: " + multicastSocket.getNetworkInterface().getName()); + // */} + /**/ + + // create the packet + byte[] message = "Hey dude".getBytes(StandardCharsets.UTF_8); + DatagramPacket packet = new DatagramPacket(message, message.length, group, port); + + // send the packet until is cancelled + for(;;) + { + multicastSocket.send(packet); + + // sleep to prevent too many unnecessary messages + try{ Thread.sleep(1000); } catch (InterruptedException e) { break; } + } + } + catch (IOException e) + { + e.printStackTrace(); + } + finally + { + if(multicastSocket != null) multicastSocket.close(); + } + } + } + + + + /** Executor used to run a BeaconTask */ + private ExecutorService beaconExecutor = Executors.newSingleThreadExecutor(); + + /** Future of the running beacon. If null no BeaconTask is running */ + private Future beaconFuture = null; + + + + /** Is currently sending packets? */ + public boolean isRunning() + { + return beaconExecutor != null && !beaconExecutor.isShutdown() && !beaconExecutor.isTerminated() //TODO: too many checks? + && beaconFuture != null && !beaconFuture.isCancelled() && !beaconFuture.isDone(); + } + + /** Start sending packet */ + public void startBroadcast() + { + if(!isRunning()) + { + try + { + beaconFuture = beaconExecutor.submit(new BeaconTask()); + } + catch (Exception e){ e.printStackTrace(); } + } + else + { + Log.e(TAG, "Beacon is already running"); + } + } + + /** Stop sending packets */ + public void stopBroadcast() + { + if(beaconFuture != null) + { + beaconFuture.cancel(true); + beaconFuture = null; + } + + Log.i(TAG, "Beacon future has been shutdown"); + } +} diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index 5dbc14c..4638256 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -4,10 +4,12 @@ import android.os.Bundle; import android.support.v7.widget.Toolbar; import com.jackss.ag.macroboard.R; +import com.jackss.ag.macroboard.network.Beacon; public class MainActivity extends AppCompatActivity { Toolbar toolbar; + Beacon mBeacon; @Override protected void onCreate(Bundle savedInstanceState) @@ -17,5 +19,21 @@ protected void onCreate(Bundle savedInstanceState) toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitle("Dumb Title"); + + mBeacon = new Beacon(); + } + + @Override + protected void onStart() + { + super.onStart(); + mBeacon.startBroadcast(); + } + + @Override + protected void onStop() + { + super.onStop(); + mBeacon.stopBroadcast(); } } From 770825cd89839ad49e2548ced041ccf17f459dd9 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Mon, 17 Apr 2017 23:59:53 +0200 Subject: [PATCH 02/48] Created working UdpSender class Using only sendData(data) function --- .../ag/macroboard/network/UdpSender.java | 60 +++++++++++++++++++ .../ui/activities/MainActivity.java | 59 ++++++++++++++++-- 2 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java new file mode 100644 index 0000000..010423e --- /dev/null +++ b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java @@ -0,0 +1,60 @@ +package com.jackss.ag.macroboard.network; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; + +import java.net.*; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +/** + * Send udp packets to a specific address and port + */ +public class UdpSender +{ + private static final String TAG = "UdpSender"; + + private ExecutorService executorService; + + + /** Runnable used to send strings to udp host, port */ + private class SendingTask implements Runnable + { + private final int port; + private final InetAddress address; + private final String data; + + SendingTask(InetAddress address, int port, String data) + { + this.address = address; + this.port = port; + this.data = data; + } + + @Override + public void run() + { + try (DatagramSocket socket = new DatagramSocket()) + { + byte buff[] = data.getBytes(StandardCharsets.UTF_8); + DatagramPacket packet = new DatagramPacket(buff, buff.length, address, port); + socket.send(packet); + } + catch (Exception e) { e.printStackTrace(); } + } + } + + public UdpSender() + { + executorService = Executors.newSingleThreadExecutor(); + } + + public void sendData(InetAddress address, int port, String data) + { + executorService.execute(new SendingTask(address, port, data)); + } +} diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index 4638256..941696d 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -1,15 +1,29 @@ package com.jackss.ag.macroboard.ui.activities; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.View; +import android.widget.Button; import com.jackss.ag.macroboard.R; import com.jackss.ag.macroboard.network.Beacon; +import com.jackss.ag.macroboard.network.UdpSender; + +import java.net.InetAddress; +import java.net.UnknownHostException; public class MainActivity extends AppCompatActivity { Toolbar toolbar; - Beacon mBeacon; + InetAddress address; + + UdpSender sender; + + @Override protected void onCreate(Bundle savedInstanceState) @@ -20,20 +34,57 @@ protected void onCreate(Bundle savedInstanceState) toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitle("Dumb Title"); - mBeacon = new Beacon(); + + sender = new UdpSender(); + try + { + address = InetAddress.getByName("192.168.1.5"); + } + catch (UnknownHostException e) + { + e.printStackTrace(); + } + + Button start = (Button) findViewById(R.id.btn_media_prev); + start.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + + } + }); + + Button stop = (Button) findViewById(R.id.btn_media_next); + stop.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + + } + }); + + final Button send = (Button) findViewById(R.id.btn_media_play); + send.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(View v) + { + sender.sendData(address, 4545,"Hey dummy"); + } + }); } @Override protected void onStart() { super.onStart(); - mBeacon.startBroadcast(); } @Override protected void onStop() { super.onStop(); - mBeacon.stopBroadcast(); } } From ec00f3f2c483c687c2d1229923b7a2a607404491 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Tue, 18 Apr 2017 01:16:09 +0200 Subject: [PATCH 03/48] Added TCP connection manager Class name: TcpConnection --- .../ag/macroboard/network/TcpConnection.java | 258 ++++++++++++++++++ .../ui/activities/MainActivity.java | 5 + 2 files changed, 263 insertions(+) create mode 100644 app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java new file mode 100644 index 0000000..f71c786 --- /dev/null +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -0,0 +1,258 @@ +package com.jackss.ag.macroboard.network; + +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.util.Log; + +import java.io.*; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * Manages a TCP connection + * + */ +public class TcpConnection +{ + private static final String TAG = "TcpConnection"; + + private static final int WHAT_DATA = 200; + private static final int WHAT_ERROR = 400; + + private Socket clientSocket; + + private OnTcpListener listener; + + private ConnectionTask connectionTask; + + private Thread inputThread; + + private PrintWriter outputPrinter; + + + public interface OnTcpListener + { + void onData(String data); + + void onConnectionState(int state); + } + + class ConnectionTask extends AsyncTask + { + @Override + protected Socket doInBackground(Integer... portArgs) + { + int port = portArgs[0]; + + try(ServerSocket serverSocket = new ServerSocket(port)) + { + return serverSocket.accept(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return null; + } + + @Override + protected void onPostExecute(Socket socket) + { + // only if the task is not cancelled + if(!isCancelled()) onConnectionResult(socket); + } + } + + private class InputHandler implements Runnable + { + private Handler mainHandler; + private final Socket clientSocket; + + InputHandler(Socket socket) + { + this.clientSocket = socket; + } + + private void createMainHandler() + { + mainHandler = new Handler(Looper.getMainLooper()) + { + @Override + public void handleMessage(Message msg) + { + // MAIN THREAD HERE + switch(msg.what) + { + case WHAT_DATA: + String data = (String) msg.obj; + Log.v(TAG, "On main thread data: " + data); + break; + + case WHAT_ERROR: + Log.e(TAG, "Tcp connection error"); + Log.v(TAG, String.valueOf(clientSocket.isConnected())); + break; + } + } + }; + } + + @Override + public void run() + { + createMainHandler(); + + try + { + BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + Log.v(TAG, "Started input thread"); + + while(true) + { + if(Thread.interrupted()) break; + + String readData = br.readLine(); + if(readData != null) + { + Log.v(TAG, "Read line: " + readData); + mainHandler.obtainMessage(0, readData).sendToTarget(); + } + else + { + mainHandler.sendEmptyMessage(WHAT_ERROR); + } + } + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + Log.v(TAG, String.valueOf(clientSocket.isClosed())); + mainHandler.sendEmptyMessage(WHAT_ERROR); + } + } + } + + + private void onConnectionResult(Socket socket) + { + clientSocket = socket; + connectionTask = null; + + if(isConnected()) + { + onConnected(); + } + else Log.e(TAG, "Connection failed"); + } + + private void onConnected() + { + Log.v(TAG, "Connected to: " + clientSocket.getInetAddress().getHostAddress()); + + try + { + clientSocket.setKeepAlive(true); + + outputPrinter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true); + + if(inputThread != null) inputThread.interrupt(); + inputThread = new Thread(new InputHandler(clientSocket)); + inputThread.start(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + private boolean isConnected() + { + return clientSocket != null && clientSocket.isConnected(); + } + + private boolean isConnecting() + { + return connectionTask != null // valid ref + && connectionTask.getStatus() == AsyncTask.Status.RUNNING // task running + && !connectionTask.isCancelled(); // task not cancelled + } + + public void setTcpListener(OnTcpListener listener) + { + this.listener = listener; + } + + public void accept(int port) + { + if(!isConnecting()) + { + connectionTask = new ConnectionTask(); + connectionTask.execute(port); + Log.v(TAG, "Task started"); + } + } + + public void disconnect() + { + + } + + public void sendData(String data) + { + if(isConnected()) + { + if(outputPrinter != null) + outputPrinter.println(data); + else + throw new AssertionError("outputPrinter is null while the socket is connected!"); + } + else Log.e(TAG, "socket is not connected"); + } +} + + + + + + + + + + +// class OutputHandler implements Runnable +// { +// final Socket socket; +// +// Handler handler; +// +// OutputHandler(Socket socket) +// { +// this.socket = socket; +// } +// +// @Override +// public void run() +// { +// Looper.prepare(); +// +// handler = new Handler() +// { +// @Override +// public void handleMessage(Message msg) +// { +// +// } +// }; +// +// +// +// +// Looper.loop(); +// } +// } diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index 941696d..bc1f0f6 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -11,6 +11,7 @@ import android.widget.Button; import com.jackss.ag.macroboard.R; import com.jackss.ag.macroboard.network.Beacon; +import com.jackss.ag.macroboard.network.TcpConnection; import com.jackss.ag.macroboard.network.UdpSender; import java.net.InetAddress; @@ -45,6 +46,9 @@ protected void onCreate(Bundle savedInstanceState) e.printStackTrace(); } + final TcpConnection connection = new TcpConnection(); + connection.accept(4545); + Button start = (Button) findViewById(R.id.btn_media_prev); start.setOnClickListener(new View.OnClickListener() { @@ -72,6 +76,7 @@ public void onClick(View v) public void onClick(View v) { sender.sendData(address, 4545,"Hey dummy"); + connection.sendData("Hello"); } }); } From f5963587e88251ea660142845c66fdaa562c157b Mon Sep 17 00:00:00 2001 From: jackss011 Date: Tue, 18 Apr 2017 02:01:23 +0200 Subject: [PATCH 04/48] Improved TcpConnection class - Added port field to costructor - Fixed mainHandler --- .../ag/macroboard/network/TcpConnection.java | 170 ++++++++++-------- .../ui/activities/MainActivity.java | 4 +- 2 files changed, 102 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index f71c786..c2eb1c7 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -1,9 +1,6 @@ package com.jackss.ag.macroboard.network; -import android.os.AsyncTask; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; +import android.os.*; import android.util.Log; import java.io.*; @@ -18,20 +15,47 @@ public class TcpConnection { private static final String TAG = "TcpConnection"; - private static final int WHAT_DATA = 200; - private static final int WHAT_ERROR = 400; - private Socket clientSocket; + // Used in handler messages what field + private static final int MSG_WHAT_DATA = 200; + private static final int MSG_WHAT_ERROR = 400; - private OnTcpListener listener; + // TCP connection socket + private Socket clientSocket; + + // AsyncTask used to produce a connected socket private ConnectionTask connectionTask; + // Thread listening for input_stream data private Thread inputThread; + // Printer used to send data to the output_stream private PrintWriter outputPrinter; + // Port used for the tcp connection + private int port; + + // Listener used to listen for connection changes + private OnTcpListener listener; + + + + // + // ========== CONSTRUCTOR =========== + // + + public TcpConnection(int port) + { + this.port = port; + } + + + // + // ========== INNER CLASSES =========== + // + public interface OnTcpListener { void onData(String data); @@ -39,7 +63,7 @@ public interface OnTcpListener void onConnectionState(int state); } - class ConnectionTask extends AsyncTask + private class ConnectionTask extends AsyncTask { @Override protected Socket doInBackground(Integer... portArgs) @@ -83,17 +107,15 @@ private void createMainHandler() @Override public void handleMessage(Message msg) { - // MAIN THREAD HERE + // RUNNING ON MAIN THREAD switch(msg.what) { - case WHAT_DATA: - String data = (String) msg.obj; - Log.v(TAG, "On main thread data: " + data); + case MSG_WHAT_DATA: + onDataReceived((String) msg.obj); break; - case WHAT_ERROR: - Log.e(TAG, "Tcp connection error"); - Log.v(TAG, String.valueOf(clientSocket.isConnected())); + case MSG_WHAT_ERROR: + onError(); break; } } @@ -108,21 +130,21 @@ public void run() try { BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - Log.v(TAG, "Started input thread"); + Log.i(TAG, "Started input thread"); while(true) { if(Thread.interrupted()) break; - String readData = br.readLine(); + if(Thread.interrupted()) break; + if(readData != null) { - Log.v(TAG, "Read line: " + readData); - mainHandler.obtainMessage(0, readData).sendToTarget(); + mainHandler.obtainMessage(MSG_WHAT_DATA, readData).sendToTarget(); } else { - mainHandler.sendEmptyMessage(WHAT_ERROR); + mainHandler.sendEmptyMessage(MSG_WHAT_ERROR); } } } @@ -132,13 +154,20 @@ public void run() } finally { - Log.v(TAG, String.valueOf(clientSocket.isClosed())); - mainHandler.sendEmptyMessage(WHAT_ERROR); + if(!Thread.interrupted()) + mainHandler.sendEmptyMessage(MSG_WHAT_ERROR); + else + Log.i(TAG, "Skipping MGS_WHAT_ERROR since input_thread has been interrupted"); } } } + + // + // ========== METHODS =========== + // + private void onConnectionResult(Socket socket) { clientSocket = socket; @@ -148,12 +177,12 @@ private void onConnectionResult(Socket socket) { onConnected(); } - else Log.e(TAG, "Connection failed"); + else Log.e(TAG, "Connection result: failed"); } private void onConnected() { - Log.v(TAG, "Connected to: " + clientSocket.getInetAddress().getHostAddress()); + Log.i(TAG, "Connected to: " + clientSocket.getInetAddress().getHostAddress()); try { @@ -171,9 +200,14 @@ private void onConnected() } } - private boolean isConnected() + private void onError() { - return clientSocket != null && clientSocket.isConnected(); + Log.e(TAG, "Connection error"); + } + + private void onDataReceived(String data) + { + Log.v(TAG, "Tcp data: " + data); } private boolean isConnecting() @@ -183,24 +217,60 @@ private boolean isConnecting() && !connectionTask.isCancelled(); // task not cancelled } + private boolean isConnected() + { + return clientSocket != null && clientSocket.isConnected(); + } + public void setTcpListener(OnTcpListener listener) { this.listener = listener; } - public void accept(int port) + public void accept() { if(!isConnecting()) { connectionTask = new ConnectionTask(); connectionTask.execute(port); - Log.v(TAG, "Task started"); + Log.i(TAG, "Connecting..."); } } - public void disconnect() + public void reset() { + Log.v(TAG, "Connection reset"); + + // connection task + if(connectionTask != null) + { + connectionTask.cancel(true); + connectionTask = null; + } + + // input thread + if(inputThread != null) + { + inputThread.interrupt(); + inputThread = null; + } + // output printer + outputPrinter = null; + + // client socket + if(clientSocket != null) try + { + clientSocket.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + finally + { + clientSocket = null; + } } public void sendData(String data) @@ -216,43 +286,3 @@ public void sendData(String data) } } - - - - - - - - - -// class OutputHandler implements Runnable -// { -// final Socket socket; -// -// Handler handler; -// -// OutputHandler(Socket socket) -// { -// this.socket = socket; -// } -// -// @Override -// public void run() -// { -// Looper.prepare(); -// -// handler = new Handler() -// { -// @Override -// public void handleMessage(Message msg) -// { -// -// } -// }; -// -// -// -// -// Looper.loop(); -// } -// } diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index bc1f0f6..b492a2c 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -46,8 +46,8 @@ protected void onCreate(Bundle savedInstanceState) e.printStackTrace(); } - final TcpConnection connection = new TcpConnection(); - connection.accept(4545); + final TcpConnection connection = new TcpConnection(4545); + connection.accept(); Button start = (Button) findViewById(R.id.btn_media_prev); start.setOnClickListener(new View.OnClickListener() From 6acc9e4660b4c20737bcccab13903f05ae83d133 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Tue, 18 Apr 2017 02:06:29 +0200 Subject: [PATCH 05/48] Polished TcpConnection --- .../ag/macroboard/network/TcpConnection.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index c2eb1c7..10e8641 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -63,6 +63,9 @@ public interface OnTcpListener void onConnectionState(int state); } + /** + * AsyncTask used to produce a connected TCP socket + */ private class ConnectionTask extends AsyncTask { @Override @@ -89,7 +92,11 @@ protected void onPostExecute(Socket socket) if(!isCancelled()) onConnectionResult(socket); } } - + + /** + * Runnable running on a separate thread listening for TCP input stream data. + * Data is sent to main_thread via Handler(main_looper) + */ private class InputHandler implements Runnable { private Handler mainHandler; @@ -222,11 +229,6 @@ private boolean isConnected() return clientSocket != null && clientSocket.isConnected(); } - public void setTcpListener(OnTcpListener listener) - { - this.listener = listener; - } - public void accept() { if(!isConnecting()) @@ -284,5 +286,10 @@ public void sendData(String data) } else Log.e(TAG, "socket is not connected"); } + + public void setTcpListener(OnTcpListener listener) + { + this.listener = listener; + } } From 8bed38af261132f473451dd4432e2ba4d8ca592d Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 00:07:47 +0200 Subject: [PATCH 06/48] Improved connection functionalities - Created NetBridge class - Created NetBridge implementation WifiBridge - Added state determination to TcpConnection --- .../ag/macroboard/network/NetBridge.java | 85 +++++++++ .../ag/macroboard/network/TcpConnection.java | 162 +++++++++++++----- .../ag/macroboard/network/WifiBridge.java | 108 ++++++++++++ .../ui/activities/MainActivity.java | 30 +--- 4 files changed, 320 insertions(+), 65 deletions(-) create mode 100644 app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java create mode 100644 app/src/main/java/com/jackss/ag/macroboard/network/WifiBridge.java diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java b/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java new file mode 100644 index 0000000..67f7b4f --- /dev/null +++ b/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java @@ -0,0 +1,85 @@ +package com.jackss.ag.macroboard.network; + +import android.content.Context; +import android.util.Log; + +/** + * + */ +abstract public class NetBridge +{ + public enum DataReliability + { + RELIABLE, + UNRELIABLE + } + + public enum ConnectionState + { + IDLE, + CONNECTING, + CONNECTED, + ERROR + } + + interface OnConnectionStateListener + { + void onConnectionStateChanged(ConnectionState newState); + } + + private Context context; + + private OnConnectionStateListener connectionStateListener; + + private ConnectionState connectionState; + + + public NetBridge(Context context) + { + this.context = context; + } + + + // interface + abstract public boolean canStartConnection(); + + abstract public void startConnection(); + + abstract public void stopConnection(); + + abstract public boolean isConnected(); + + abstract public boolean sendData(String data, DataReliability reliability); + + public boolean sendData(String data) + { + return sendData(data, DataReliability.RELIABLE); + } + + // final + public void setConnectionStateListener(OnConnectionStateListener connectionStateListener) + { + this.connectionStateListener = connectionStateListener; + } + + protected void setConnectionState(ConnectionState state) + { + if(this.connectionState != state) + { + this.connectionState = state; + if(connectionStateListener != null) connectionStateListener.onConnectionStateChanged(this.connectionState); + } + + Log.v("NetBridge", "Moving to state: " + state.name()); + } + + public ConnectionState getConnectionState() + { + return connectionState; + } + + public Context getContext() + { + return context; + } +} diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index 10e8641..139d4de 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -4,9 +4,11 @@ import android.util.Log; import java.io.*; +import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; + /** * Manages a TCP connection * @@ -21,24 +23,20 @@ public class TcpConnection private static final int MSG_WHAT_ERROR = 400; - // TCP connection socket private Socket clientSocket; - // AsyncTask used to produce a connected socket - private ConnectionTask connectionTask; + private ConnectionTask connectionTask; // AsyncTask used to produce a connected socket + + private Thread inputThread; // Thread listening for input_stream data - // Thread listening for input_stream data - private Thread inputThread; + private PrintWriter outputPrinter; // Printer used to send data to the output_stream - // Printer used to send data to the output_stream - private PrintWriter outputPrinter; + private TcpState tcpState = TcpState.IDLE; - // Port used for the tcp connection private int port; - // Listener used to listen for connection changes - private OnTcpListener listener; + private OnTcpListener tcpListener; @@ -56,13 +54,22 @@ public TcpConnection(int port) // ========== INNER CLASSES =========== // + public enum TcpState + { + IDLE, + CONNECTING, + CONNECTED, + ERROR + } + public interface OnTcpListener { void onData(String data); - void onConnectionState(int state); + void onConnectionStateChanged(TcpState newState); } + /** * AsyncTask used to produce a connected TCP socket */ @@ -93,12 +100,15 @@ protected void onPostExecute(Socket socket) } } + /** * Runnable running on a separate thread listening for TCP input stream data. * Data is sent to main_thread via Handler(main_looper) */ private class InputHandler implements Runnable { + private static final String TAG = "InputHandler"; + private Handler mainHandler; private final Socket clientSocket; @@ -122,49 +132,45 @@ public void handleMessage(Message msg) break; case MSG_WHAT_ERROR: - onError(); + onInputThreadError(); break; } } }; } + private void sendErrorMessage() + { + mainHandler.sendEmptyMessage(MSG_WHAT_ERROR); + } + @Override public void run() { + Log.i(TAG, "Started input_thread"); + createMainHandler(); try { BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); - Log.i(TAG, "Started input thread"); + if(Thread.interrupted()) return; while(true) { - if(Thread.interrupted()) break; String readData = br.readLine(); if(Thread.interrupted()) break; if(readData != null) - { mainHandler.obtainMessage(MSG_WHAT_DATA, readData).sendToTarget(); - } - else - { - mainHandler.sendEmptyMessage(MSG_WHAT_ERROR); - } + else + sendErrorMessage(); } } catch (Exception e) { e.printStackTrace(); - } - finally - { - if(!Thread.interrupted()) - mainHandler.sendEmptyMessage(MSG_WHAT_ERROR); - else - Log.i(TAG, "Skipping MGS_WHAT_ERROR since input_thread has been interrupted"); + sendErrorMessage(); } } } @@ -175,6 +181,42 @@ public void run() // ========== METHODS =========== // + // Internal set tcp state. Call the listener if a change occurred + private void setTcpState(TcpState newState) + { + if(getTcpState() != newState) + { + this.tcpState = newState; + if(tcpListener != null) tcpListener.onConnectionStateChanged(getTcpState()); + + Log.v(TAG, "Moving to state: " + newState.name()); + } + } + + /** Get the state of this TCP connection */ + public TcpState getTcpState() + { + return tcpState; + } + + /** Set the listener notified of data receiving and connection state change */ + public void setTcpListener(OnTcpListener tcpListener) + { + this.tcpListener = tcpListener; + } + + /** If isConnected() returns true return the socket address, return null otherwise */ + public InetAddress getConnectedAddress() + { + return isConnected() ? clientSocket.getInetAddress() : null; + } + + public int getPort() + { + return port; + } + + // Called from ConnectionTask.onPostExecute(socket) when connection is finished private void onConnectionResult(Socket socket) { clientSocket = socket; @@ -184,9 +226,15 @@ private void onConnectionResult(Socket socket) { onConnected(); } - else Log.e(TAG, "Connection result: failed"); + else + { + Log.e(TAG, "Connection result failed"); + onError(); + } + } + // Called if a connected socket is found private void onConnected() { Log.i(TAG, "Connected to: " + clientSocket.getInetAddress().getHostAddress()); @@ -195,28 +243,43 @@ private void onConnected() { clientSocket.setKeepAlive(true); - outputPrinter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true); - + outputPrinter = + new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true); + if(inputThread != null) inputThread.interrupt(); inputThread = new Thread(new InputHandler(clientSocket)); inputThread.start(); + + setTcpState(TcpState.CONNECTED); } catch (IOException e) { e.printStackTrace(); + onError(); } } - private void onError() + // Called from input_thread if an error occurs using the main_handler (i.e. running on main_thread) + private void onInputThreadError() { - Log.e(TAG, "Connection error"); + // "throw" an error only if the socket wasn't intentionally closed using Socket.close() + // since it means it is not an unexpected event + if(isConnected()) onError(); } + // Called internally when an error occurs + private void onError() //TODO: maybe use error types + { + setTcpState(TcpState.ERROR); + } + + // Running on main thread. Called by input thread when data is read from the input buffer private void onDataReceived(String data) { - Log.v(TAG, "Tcp data: " + data); + if(tcpListener != null) tcpListener.onData(data); } + /** Return true if is currently try to connect, false otherwise */ private boolean isConnecting() { return connectionTask != null // valid ref @@ -224,24 +287,34 @@ private boolean isConnecting() && !connectionTask.isCancelled(); // task not cancelled } - private boolean isConnected() + /** + * Return true if is the socket is connected, false otherwise + * + * NOTE: The socket is considered connected even if is actually disconnected from the network. + * Only writing or reading from its streams determine if a socket is actually connected or not. + * TcpListener.onConnectionStateChange(TcpState.ERROR) is called (on the main thread) when such operations fail. + */ + private boolean isConnected() //TODO: get rid off this function { return clientSocket != null && clientSocket.isConnected(); } - public void accept() + public void startConnection() { if(!isConnecting()) { + Log.i(TAG, "Connection in progress"); + connectionTask = new ConnectionTask(); + setTcpState(TcpState.CONNECTING); connectionTask.execute(port); - Log.i(TAG, "Connecting..."); } } + /** Free every resource and reset */ public void reset() { - Log.v(TAG, "Connection reset"); + Log.i(TAG, "Connection reset"); // connection task if(connectionTask != null) @@ -273,23 +346,24 @@ public void reset() { clientSocket = null; } + + setTcpState(TcpState.IDLE); } public void sendData(String data) { - if(isConnected()) + if(isConnected()) //TODO: should use getState()? { if(outputPrinter != null) outputPrinter.println(data); else throw new AssertionError("outputPrinter is null while the socket is connected!"); } - else Log.e(TAG, "socket is not connected"); - } - - public void setTcpListener(OnTcpListener listener) - { - this.listener = listener; + else + { + Log.e(TAG, "SendData() called when not connected"); + onError(); + } } } diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/WifiBridge.java b/app/src/main/java/com/jackss/ag/macroboard/network/WifiBridge.java new file mode 100644 index 0000000..ce760ba --- /dev/null +++ b/app/src/main/java/com/jackss/ag/macroboard/network/WifiBridge.java @@ -0,0 +1,108 @@ +package com.jackss.ag.macroboard.network; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; +import android.support.annotation.NonNull; +import android.util.Log; + + +/** + * + */ +public class WifiBridge extends NetBridge +{ + private static final String TAG = "WifiBridge"; + + private TcpConnection tcpConnection; + + private UdpSender udpSender; + + private TcpConnection.OnTcpListener tcpListener= new TcpConnection.OnTcpListener() + { + @Override + public void onData(String data) + { + Log.v(TAG, "Data received: " + data); + } + + @Override + public void onConnectionStateChanged(TcpConnection.TcpState newState) + { + setConnectionState(ConnectionState.values()[newState.ordinal()]); //TODO: non-safe enum transposition + } + }; + + + public WifiBridge(Context context) + { + super(context); + + tcpConnection = new TcpConnection(4545); + tcpConnection.setTcpListener(tcpListener); + udpSender = new UdpSender(); + } + + @Override + public boolean canStartConnection() + { + return isWifiConnected(getContext()); + } + + @Override + public void startConnection() + { + if(canStartConnection()) + tcpConnection.startConnection(); + } + + @Override + public void stopConnection() + { + tcpConnection.reset(); + } + + @Override + public boolean isConnected() + { + return tcpConnection.getTcpState() == TcpConnection.TcpState.CONNECTED; + } + + @Override + public boolean sendData(String data, DataReliability reliability) + { + if(data == null) throw new AssertionError("sending null data string"); + + if(!isConnected()) + { + Log.v(TAG, "sending data from non-connected wifi_bridge"); + return false; + } + + if(reliability == DataReliability.RELIABLE) + { + tcpConnection.sendData(data); + } + else + { + udpSender.sendData(tcpConnection.getConnectedAddress(), tcpConnection.getPort(), data); + } + + return true; + } + + public static boolean isWifiConnected(@NonNull Context context) + { + ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + Network networks[] = manager.getAllNetworks(); + + for(Network net : networks) + { + NetworkInfo info = manager.getNetworkInfo(net); + if(info.getType() == ConnectivityManager.TYPE_WIFI) return info.isConnected(); + } + + return false; + } +} diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index b492a2c..3b524c2 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -10,9 +10,7 @@ import android.view.View; import android.widget.Button; import com.jackss.ag.macroboard.R; -import com.jackss.ag.macroboard.network.Beacon; -import com.jackss.ag.macroboard.network.TcpConnection; -import com.jackss.ag.macroboard.network.UdpSender; +import com.jackss.ag.macroboard.network.*; import java.net.InetAddress; import java.net.UnknownHostException; @@ -22,9 +20,8 @@ public class MainActivity extends AppCompatActivity Toolbar toolbar; InetAddress address; - UdpSender sender; - + NetBridge netBridge; @Override protected void onCreate(Bundle savedInstanceState) @@ -35,48 +32,39 @@ protected void onCreate(Bundle savedInstanceState) toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitle("Dumb Title"); + netBridge = new WifiBridge(getApplicationContext()); - sender = new UdpSender(); - try - { - address = InetAddress.getByName("192.168.1.5"); - } - catch (UnknownHostException e) - { - e.printStackTrace(); - } - - final TcpConnection connection = new TcpConnection(4545); - connection.accept(); Button start = (Button) findViewById(R.id.btn_media_prev); + start.setText("start"); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + netBridge.startConnection(); } }); Button stop = (Button) findViewById(R.id.btn_media_next); + stop.setText("stop"); stop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - + netBridge.stopConnection(); } }); final Button send = (Button) findViewById(R.id.btn_media_play); + send.setText("send"); send.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - sender.sendData(address, 4545,"Hey dummy"); - connection.sendData("Hello"); + netBridge.sendData("Hello"); } }); } From a4e1e8fb7a590061b958dc7417768f60fd943a72 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 00:08:13 +0200 Subject: [PATCH 07/48] Polished UdpSender --- .../jackss/ag/macroboard/network/UdpSender.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java index 010423e..38439e5 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java @@ -1,15 +1,12 @@ package com.jackss.ag.macroboard.network; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import java.net.*; +import android.support.annotation.NonNull; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.concurrent.Future; /** * Send udp packets to a specific address and port @@ -21,7 +18,7 @@ public class UdpSender private ExecutorService executorService; - /** Runnable used to send strings to udp host, port */ + /** Runnable used to send strings to udp using: host, port */ private class SendingTask implements Runnable { private final int port; @@ -53,7 +50,7 @@ public UdpSender() executorService = Executors.newSingleThreadExecutor(); } - public void sendData(InetAddress address, int port, String data) + public void sendData(@NonNull InetAddress address, int port, String data) { executorService.execute(new SendingTask(address, port, data)); } From cea8d17aaf65308bc66ac5fdfd596c892beb43bc Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 00:13:06 +0200 Subject: [PATCH 08/48] Added TODO to TcpConnection mainHandler leaks --- .../java/com/jackss/ag/macroboard/network/TcpConnection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index 139d4de..c28f268 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -119,7 +119,7 @@ private class InputHandler implements Runnable private void createMainHandler() { - mainHandler = new Handler(Looper.getMainLooper()) + mainHandler = new Handler(Looper.getMainLooper()) //TODO: this may cause leaks? { @Override public void handleMessage(Message msg) From 970b58c5fda316a476d4737e3edc7bdcf46aec20 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 00:24:50 +0200 Subject: [PATCH 09/48] Added canStartConnection() to TcpConnection + Polished javadoc --- .../ag/macroboard/network/TcpConnection.java | 41 +++++++++++++------ .../ag/macroboard/network/UdpSender.java | 4 +- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index c28f268..7517a2e 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -10,7 +10,7 @@ /** - * Manages a TCP connection + * Manages a TCP connection. * */ public class TcpConnection @@ -71,7 +71,7 @@ public interface OnTcpListener /** - * AsyncTask used to produce a connected TCP socket + * AsyncTask used to produce a connected TCP socket. */ private class ConnectionTask extends AsyncTask { @@ -103,7 +103,7 @@ protected void onPostExecute(Socket socket) /** * Runnable running on a separate thread listening for TCP input stream data. - * Data is sent to main_thread via Handler(main_looper) + * Data is sent to main_thread via Handler(main_looper). */ private class InputHandler implements Runnable { @@ -193,24 +193,25 @@ private void setTcpState(TcpState newState) } } - /** Get the state of this TCP connection */ + /** Get the state of this TCP connection. */ public TcpState getTcpState() { return tcpState; } - /** Set the listener notified of data receiving and connection state change */ + /** Set the listener notified of data receiving and connection state change. */ public void setTcpListener(OnTcpListener tcpListener) { this.tcpListener = tcpListener; } - /** If isConnected() returns true return the socket address, return null otherwise */ + /** If isConnected() returns true return the socket address, return null otherwise. */ public InetAddress getConnectedAddress() { return isConnected() ? clientSocket.getInetAddress() : null; } + /** Get the port used by this connection. */ public int getPort() { return port; @@ -279,7 +280,7 @@ private void onDataReceived(String data) if(tcpListener != null) tcpListener.onData(data); } - /** Return true if is currently try to connect, false otherwise */ + /** Return true if is currently try to connect, false otherwise. */ private boolean isConnecting() { return connectionTask != null // valid ref @@ -288,7 +289,7 @@ private boolean isConnecting() } /** - * Return true if is the socket is connected, false otherwise + * Return true if is the socket is connected, false otherwise. * * NOTE: The socket is considered connected even if is actually disconnected from the network. * Only writing or reading from its streams determine if a socket is actually connected or not. @@ -299,19 +300,34 @@ private boolean isConnected() //TODO: get rid off this function return clientSocket != null && clientSocket.isConnected(); } - public void startConnection() + /** Check whenever calling startConnection will actually start a connection */ + public boolean canStartConnection() //TODO: improve this { - if(!isConnecting()) + return !isConnecting(); + } + + /** + * Try to produce a connected Socket. State is moved to TcpState.CONNECTING. + * + * @return return true if the connection is successfully started + */ + public boolean startConnection() + { + if(canStartConnection()) { Log.i(TAG, "Connection in progress"); connectionTask = new ConnectionTask(); setTcpState(TcpState.CONNECTING); connectionTask.execute(port); + + return true; } + + return false; } - /** Free every resource and reset */ + /** Free every resource allowing to start a new connection. */ public void reset() { Log.i(TAG, "Connection reset"); @@ -350,6 +366,7 @@ public void reset() setTcpState(TcpState.IDLE); } + /** If the connection is open send a data string, do nothing otherwise. */ public void sendData(String data) { if(isConnected()) //TODO: should use getState()? @@ -361,7 +378,7 @@ public void sendData(String data) } else { - Log.e(TAG, "SendData() called when not connected"); + Log.e(TAG, "SendData() called when Socket is not connected"); onError(); } } diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java index 38439e5..8cc0096 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/UdpSender.java @@ -9,7 +9,7 @@ import java.util.concurrent.Executors; /** - * Send udp packets to a specific address and port + * Send udp packets to a specific address and port. */ public class UdpSender { @@ -18,7 +18,7 @@ public class UdpSender private ExecutorService executorService; - /** Runnable used to send strings to udp using: host, port */ + // Runnable used to send strings to udp using: host, port private class SendingTask implements Runnable { private final int port; From 3a35db26c442e566d1aef915aa0976ad181472b6 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 00:35:01 +0200 Subject: [PATCH 10/48] Added Charset to PrintWriter in TcpConnection --- .../com/jackss/ag/macroboard/network/TcpConnection.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java index 7517a2e..6c391d3 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/TcpConnection.java @@ -7,6 +7,7 @@ import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; +import java.nio.charset.StandardCharsets; /** @@ -245,7 +246,7 @@ private void onConnected() clientSocket.setKeepAlive(true); outputPrinter = - new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())), true); + new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8)), true); if(inputThread != null) inputThread.interrupt(); inputThread = new Thread(new InputHandler(clientSocket)); @@ -366,7 +367,11 @@ public void reset() setTcpState(TcpState.IDLE); } - /** If the connection is open send a data string, do nothing otherwise. */ + /** + * If the connection is open send a data string, do nothing otherwise. + * + * @param data Data string to send + */ public void sendData(String data) { if(isConnected()) //TODO: should use getState()? From bc97d5c091ba56ba19ca949716ab2e79ae0889cc Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 16:34:06 +0200 Subject: [PATCH 11/48] Added sandbox debug only flavour Added also NetworkTests activity --- app/build.gradle | 16 +++++++++++++++- app/src/sandbox/AndroidManifest.xml | 13 +++++++++++++ .../ag/macroboard/sandbox/NetworkTests.java | 16 ++++++++++++++++ .../res/layout/activity_network_tests.xml | 16 ++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 app/src/sandbox/AndroidManifest.xml create mode 100644 app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java create mode 100644 app/src/sandbox/res/layout/activity_network_tests.xml diff --git a/app/build.gradle b/app/build.gradle index 7aff108..5297ffe 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,11 +16,25 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } + + } + productFlavors { + sandbox { + applicationIdSuffix ".sandbox" + versionNameSuffix "-SANDBOX" + } + full { } + } + + variantFilter { variant -> + // Ignore sandboxDebug since it makes no sense + if(variant.name == 'sandboxRelease') + setIgnore true } } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) diff --git a/app/src/sandbox/AndroidManifest.xml b/app/src/sandbox/AndroidManifest.xml new file mode 100644 index 0000000..8daa801 --- /dev/null +++ b/app/src/sandbox/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java new file mode 100644 index 0000000..310d95e --- /dev/null +++ b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java @@ -0,0 +1,16 @@ +package com.jackss.ag.macroboard.sandbox; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import com.jackss.ag.macroboard.R; + +public class NetworkTests extends AppCompatActivity +{ + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_network_tests); + } +} diff --git a/app/src/sandbox/res/layout/activity_network_tests.xml b/app/src/sandbox/res/layout/activity_network_tests.xml new file mode 100644 index 0000000..ebaf724 --- /dev/null +++ b/app/src/sandbox/res/layout/activity_network_tests.xml @@ -0,0 +1,16 @@ + + + + + From c6317ee74655b7bc8f283ca1abaf9e940b115bba Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 16:58:23 +0200 Subject: [PATCH 12/48] Removed changes from MainActivity to 7a75442a --- .../ui/activities/MainActivity.java | 62 ------------------- 1 file changed, 62 deletions(-) diff --git a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java index 3b524c2..5dbc14c 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java +++ b/app/src/main/java/com/jackss/ag/macroboard/ui/activities/MainActivity.java @@ -1,27 +1,13 @@ package com.jackss.ag.macroboard.ui.activities; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; -import android.util.Log; -import android.view.View; -import android.widget.Button; import com.jackss.ag.macroboard.R; -import com.jackss.ag.macroboard.network.*; - -import java.net.InetAddress; -import java.net.UnknownHostException; public class MainActivity extends AppCompatActivity { Toolbar toolbar; - InetAddress address; - - - NetBridge netBridge; @Override protected void onCreate(Bundle savedInstanceState) @@ -31,53 +17,5 @@ protected void onCreate(Bundle savedInstanceState) toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitle("Dumb Title"); - - netBridge = new WifiBridge(getApplicationContext()); - - - Button start = (Button) findViewById(R.id.btn_media_prev); - start.setText("start"); - start.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View v) - { - netBridge.startConnection(); - } - }); - - Button stop = (Button) findViewById(R.id.btn_media_next); - stop.setText("stop"); - stop.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View v) - { - netBridge.stopConnection(); - } - }); - - final Button send = (Button) findViewById(R.id.btn_media_play); - send.setText("send"); - send.setOnClickListener(new View.OnClickListener() - { - @Override - public void onClick(View v) - { - netBridge.sendData("Hello"); - } - }); - } - - @Override - protected void onStart() - { - super.onStart(); - } - - @Override - protected void onStop() - { - super.onStop(); } } From d5d2086a254b4cef98d26ef16a710a15ac4cf6a0 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 17:16:48 +0200 Subject: [PATCH 13/48] Deleted NetworkTests xml layout --- app/build.gradle | 2 +- .../ag/macroboard/sandbox/NetworkTests.java | 3 +-- .../res/layout/activity_network_tests.xml | 16 ---------------- 3 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 app/src/sandbox/res/layout/activity_network_tests.xml diff --git a/app/build.gradle b/app/build.gradle index 5297ffe..e4c3ec9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,7 +27,7 @@ android { } variantFilter { variant -> - // Ignore sandboxDebug since it makes no sense + // Ignore sandboxRelease since it makes no sense if(variant.name == 'sandboxRelease') setIgnore true } diff --git a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java index 310d95e..59b2764 100644 --- a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java +++ b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java @@ -6,11 +6,10 @@ public class NetworkTests extends AppCompatActivity { - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_network_tests); + } } diff --git a/app/src/sandbox/res/layout/activity_network_tests.xml b/app/src/sandbox/res/layout/activity_network_tests.xml deleted file mode 100644 index ebaf724..0000000 --- a/app/src/sandbox/res/layout/activity_network_tests.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - From 51ba799de7703001c033d88d6c197bbfdc0fe6b0 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 17:35:48 +0200 Subject: [PATCH 14/48] Renamed NetworkTests to NetworkTestsActivity --- app/src/sandbox/AndroidManifest.xml | 2 +- .../sandbox/{NetworkTests.java => NetworkTestsActivity.java} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/{NetworkTests.java => NetworkTestsActivity.java} (82%) diff --git a/app/src/sandbox/AndroidManifest.xml b/app/src/sandbox/AndroidManifest.xml index 8daa801..ffabb85 100644 --- a/app/src/sandbox/AndroidManifest.xml +++ b/app/src/sandbox/AndroidManifest.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java similarity index 82% rename from app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java rename to app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java index 59b2764..616b25d 100644 --- a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTests.java +++ b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java @@ -4,7 +4,7 @@ import android.os.Bundle; import com.jackss.ag.macroboard.R; -public class NetworkTests extends AppCompatActivity +public class NetworkTestsActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) From 50b281f1ed0e8408dafb428cb1e5436180481a13 Mon Sep 17 00:00:00 2001 From: jackss011 Date: Thu, 20 Apr 2017 18:06:12 +0200 Subject: [PATCH 15/48] Implemented NetworkTestsActivivity Connection now works --- .../ag/macroboard/network/NetBridge.java | 2 +- .../sandbox/NetworkTestsActivity.java | 48 ++++++++++++++++++- .../res/layout/activity_network_tests.xml | 46 ++++++++++++++++++ 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 app/src/sandbox/res/layout/activity_network_tests.xml diff --git a/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java b/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java index 67f7b4f..d18c7e5 100644 --- a/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java +++ b/app/src/main/java/com/jackss/ag/macroboard/network/NetBridge.java @@ -22,7 +22,7 @@ public enum ConnectionState ERROR } - interface OnConnectionStateListener + public interface OnConnectionStateListener { void onConnectionStateChanged(ConnectionState newState); } diff --git a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java index 616b25d..e6338c5 100644 --- a/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java +++ b/app/src/sandbox/java/com/jackss/ag/macroboard/sandbox/NetworkTestsActivity.java @@ -2,14 +2,60 @@ import android.support.v7.app.AppCompatActivity; import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; import com.jackss.ag.macroboard.R; +import com.jackss.ag.macroboard.network.NetBridge; +import com.jackss.ag.macroboard.network.WifiBridge; -public class NetworkTestsActivity extends AppCompatActivity +public class NetworkTestsActivity extends AppCompatActivity implements NetBridge.OnConnectionStateListener { + private static final String TAG = "NetworkTestsActivity"; + private Button start; + private Button stop; + private Button send; + private TextView result; + + private WifiBridge wifiBridge; + + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + setContentView(R.layout.activity_network_tests); + + start = (Button) findViewById(R.id.sandbox_start); + stop = (Button) findViewById(R.id.sandbox_stop); + send = (Button) findViewById(R.id.sandbox_send); + result = (TextView) findViewById(R.id.sandbox_result); + + wifiBridge = new WifiBridge(this); + wifiBridge.setConnectionStateListener(this); + } + public void onClick(View view) + { + if(view.equals(start)) + { + Log.v(TAG, "Test "); + wifiBridge.startConnection(); + } + else if(view.equals(stop)) + { + wifiBridge.stopConnection(); + } + else if(view.equals(send)) + { + wifiBridge.sendData("Hello"); + } + } + + @Override + public void onConnectionStateChanged(NetBridge.ConnectionState newState) + { + result.setText(newState.name()); } } diff --git a/app/src/sandbox/res/layout/activity_network_tests.xml b/app/src/sandbox/res/layout/activity_network_tests.xml new file mode 100644 index 0000000..0a6c4b7 --- /dev/null +++ b/app/src/sandbox/res/layout/activity_network_tests.xml @@ -0,0 +1,46 @@ + + + +