Commit a0033ca4 authored by fpeterfalvi's avatar fpeterfalvi
Browse files

Server recyclerview handles client disconnect.

If the "disconnect" key is pressed on the client or the client is closed, the corresponding item is removed form the recyclerview at the server.
parent 958283aa
/KvizClient/.idea/vcs.xml
/KvizServer/.idea/vcs.xml
/KvizClient/.idea/misc.xml
......@@ -6,18 +6,11 @@ import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.BufferedWriter;
......@@ -30,7 +23,6 @@ import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import onlab.kvizclient.model.ServerInfo;
import onlab.kvizclient.model.ServerModel;
public class LobbyActivity extends AppCompatActivity implements ServerConnection {
......@@ -49,10 +41,6 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
private int hostPort;
private NsdManager mNsdManager;
private NsdServiceInfo mService;
//private TextView txtip;
//private TextView txtport;
//private TextView txthostname;
//private Button btnconnect;
Handler updateConversationHandler;
......@@ -65,9 +53,6 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lobby);
//txtip = findViewById(R.id.txtip);
//txtport = findViewById(R.id.txtport);
//txthostname = findViewById(R.id.txthostname);
servers = new ArrayList<ServerModel>();
......@@ -156,15 +141,14 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
// When the network service is no longer available.
// Internal bookkeeping code goes here.
Log.e(TAG, "service lost" + service);
//
for (ServerModel server: servers) {
if(server.getSocket().getInetAddress() == service.getHost())
{
if(server.getSocket().isClosed()) {
Log.d("fdsa", "bbbbbbbbbbbbbbbbbbb");
int position = servers.indexOf(server);
updateConversationHandler.post(new updateUIThread(Operation.REMOVE_SERVER, Integer.toString(position)));
servers.remove(server);
// TODO: 2018. 03. 16. //refresh list
}
}
}
......@@ -216,23 +200,17 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
hostPort = serviceInfo.getPort();
hostAddress = serviceInfo.getHost();
runOnUiThread(new Runnable() {
public void run() {
//txtip.setText(hostAddress.getHostAddress());
//txtport.setText(Integer.toString(hostPort));
//txthostname.setText(hostname);
//Log.d("MEGVAN", hostAddress.getHostAddress());
adapter.addItem(new ServerInfo(hostAddress.getHostAddress(), Integer.toString(hostPort), hostname));
}
});
//-----Socket-----//
try {
Socket s = new Socket(hostAddress,hostPort);
ServerModel serverModel = new ServerModel("Unknown", s);
ServerModel serverModel = new ServerModel(serviceInfo, s);
servers.add(serverModel);
runOnUiThread(new Runnable() {
public void run() {
adapter.addItem();
}
});
CommunicationThread commThread = new CommunicationThread(serverModel);
new Thread(commThread).start();
} catch (IOException e) {
......@@ -244,16 +222,16 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
//-----Socket----//
public void onClick(int serverNumber) {
public void onConnect(int serverNumber) {
try {
if(servers.size() >0) {
if(servers.size() > serverNumber) {
String str = "Connect##"+CLIENT_NAME;
Socket socket = servers.get(serverNumber).getSocket();
SocketHolder.setSocket(socket);
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(servers.get(serverNumber).getSocket().getOutputStream())), true);
new OutputStreamWriter(socket.getOutputStream())), true);
out.println(str);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
......@@ -263,11 +241,21 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
}
}
public void onDisconnect() {
try {
if (SocketHolder.getSocket() != null) {
String str = "Disconnect##"+CLIENT_NAME;
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(SocketHolder.getSocket().getOutputStream())), true);
out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
}
class CommunicationThread implements Runnable {
//private Socket serverSocket;
private ServerModel serverModel;
private BufferedReader input;
......@@ -290,8 +278,6 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(serverModel.getSocket().getOutputStream())),true);
out.println(str);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
......@@ -301,32 +287,41 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
}
while (!Thread.currentThread().isInterrupted()) {
try {
String read = input.readLine();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(serverModel.getSocket().getOutputStream())), true);
String params[] = read.split("##");
switch (params[0])
{
case "Hostname":
int serverIndex = servers.indexOf(serverModel);
updateConversationHandler.post(new updateUIThread(params[1], serverIndex));
break;
case "Connect":
if(params[1].equals("Ok!"))
{
//továbblépni
if (serverModel.getSocket().isConnected()) {
Log.d("LobbyActivity", "Connected");
String read = input.readLine();
Log.d("LobbyActivity", "Read");
if (read != null) {
String params[] = read.split("##");
switch (params[0]) {
case "Hostname":
int serverIndex = servers.indexOf(serverModel);
serverModel.setHostName(params[1]);
updateConversationHandler.post(new updateUIThread(Operation.UPDATE_SERVER, Integer.toString(serverIndex)));
break;
case "Connect":
if(params[1].equals("Ok!")) {
//továbblépni
} else {
//nem sikerült
}
break;
case "Disconnect":
//sikeres disconnect, vagy pedig a szerver csatlakozott le
break;
}
else
{
//nem sikerült
}
} else {
Log.d("LobbyActivity", "Not connected");
for (ServerModel server : servers) {
if (server.getSocket() == serverModel.getSocket()) {
int position = servers.indexOf(server);
updateConversationHandler.post(new updateUIThread(Operation.REMOVE_SERVER, Integer.toString(position)));
servers.remove(server);
break;
}
break;
case "Disconnect":
//sikeres disconnect, vagy pedig a szerver csatlakozott le
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
......@@ -336,23 +331,36 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
}
class updateUIThread implements Runnable {
private Operation op;
private String msg;
private int serverIndex;
public updateUIThread(String str, int serverIndex) {
public updateUIThread(Operation op, String str) {
this.op = op;
this.msg = str;
this.serverIndex = serverIndex;
}
@Override
public void run() {
//txthostname.setText(msg);
adapter.updateHostName(serverIndex, msg);
switch (op) {
case ADD_SERVER:
adapter.addItem();
break;
case REMOVE_SERVER:
adapter.removeItem(Integer.parseInt(msg));
break;
case UPDATE_SERVER:
adapter.updateItem(Integer.parseInt(msg));
default:
Log.d("updateUIThread", "Unknown operation");
break;
}
}
}
private void initRecyclerView() {
recyclerView = (RecyclerView) findViewById(R.id.MainRecyclerView);
adapter = new ServerListAdapter(this);
adapter = new ServerListAdapter(this, servers);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(adapter);
......@@ -360,3 +368,6 @@ public class LobbyActivity extends AppCompatActivity implements ServerConnection
}
enum Operation {
ADD_SERVER, REMOVE_SERVER, UPDATE_SERVER;
}
package onlab.kvizclient;
public interface ServerConnection {
public void onClick(int serverNumber);
public void onConnect(int serverNumber);
public void onDisconnect();
}
......@@ -4,21 +4,22 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import onlab.kvizclient.model.ServerInfo;
import onlab.kvizclient.model.ConnectionStatus;
import onlab.kvizclient.model.ServerModel;
public class ServerListAdapter extends RecyclerView.Adapter<ServerListAdapter.ServerViewHolder> {
private final List<ServerInfo> items = new ArrayList<>();
private final List<ServerModel> items;
private final ServerConnection serverConnection;
public ServerListAdapter(ServerConnection sc) {
public ServerListAdapter(ServerConnection sc, List<ServerModel> servers) {
items = servers;
serverConnection = sc;
}
......@@ -31,14 +32,42 @@ public class ServerListAdapter extends RecyclerView.Adapter<ServerListAdapter.Se
@Override
public void onBindViewHolder(final ServerViewHolder holder, final int position) {
final ServerInfo item = items.get(position);
holder.ipTextView.setText(item.getIp());
holder.portTextView.setText(item.getPort());
final ServerModel item = items.get(position);
holder.ipTextView.setText(item.getHostAddress());
holder.portTextView.setText(Integer.toString(item.getPort()));
holder.hostNameTextView.setText(item.getHostName());
switch (item.getConnectionStatus()) {
case CONNECTED:
holder.connectButton.setEnabled(false);
holder.disconnectButton.setEnabled(true);
break;
case NOT_CONNECTED:
holder.connectButton.setEnabled(true);
holder.disconnectButton.setEnabled(false);
break;
default:
holder.connectButton.setEnabled(false);
holder.disconnectButton.setEnabled(false);
}
holder.connectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
serverConnection.onClick(position);
serverConnection.onConnect(position);
for (ServerModel server : items) {
server.setConnectionStatus(ConnectionStatus.CONNECTED_TO_OTHER_SERVER);
}
item.setConnectionStatus(ConnectionStatus.CONNECTED);
notifyDataSetChanged();
}
});
holder.disconnectButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
serverConnection.onDisconnect();
for (ServerModel server : items) {
server.setConnectionStatus(ConnectionStatus.NOT_CONNECTED);
}
notifyDataSetChanged();
}
});
}
......@@ -53,35 +82,36 @@ public class ServerListAdapter extends RecyclerView.Adapter<ServerListAdapter.Se
TextView ipTextView;
TextView portTextView;
TextView hostNameTextView;
ImageButton connectButton;
Button connectButton;
Button disconnectButton;
public ServerViewHolder(View itemView) {
super(itemView);
ipTextView = (TextView) itemView.findViewById(R.id.ipTextView);
portTextView = (TextView) itemView.findViewById(R.id.portTextView);
hostNameTextView = (TextView) itemView.findViewById(R.id.hostNameTextView);
connectButton = (ImageButton) itemView.findViewById(R.id.connectButton);
connectButton = (Button) itemView.findViewById(R.id.connectButton);
disconnectButton = (Button) itemView.findViewById(R.id.disconnectButton);
}
}
public void addItem(ServerInfo item) {
items.add(item);
public void addItem() {
notifyItemInserted(items.size() - 1);
}
public void update(List<ServerInfo> serverInfos) {
items.clear();
items.addAll(serverInfos);
public void update() {
notifyDataSetChanged();
}
public void updateHostName(int index, String name) {
ServerInfo si = items.get(index);
si.setHostName(name);
public void updateItem(int index) {
notifyItemChanged(index);
}
public ServerInfo getItem(int position) {
public void removeItem(int position) {
notifyItemRemoved(position);
}
public ServerModel getItem(int position) {
return items.get(position);
}
......
package onlab.kvizclient;
import java.net.Socket;
public class SocketHolder {
private static Socket socket;
public static Socket getSocket() {
return socket;
}
public static void setSocket(Socket socket) {
SocketHolder.socket = socket;
}
}
package onlab.kvizclient.model;
public enum ConnectionStatus {
CONNECTED, NOT_CONNECTED, CONNECTED_TO_OTHER_SERVER
}
package onlab.kvizclient.model;
public class ServerInfo {
String ip;
String port;
String hostName;
public ServerInfo(String ip, String port, String hostName) {
this.ip = ip;
this.port = port;
this.hostName = hostName;
}
public String getIp() {
return ip;
}
public String getPort() {
return port;
}
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
}
package onlab.kvizclient.model;
import android.net.nsd.NsdServiceInfo;
import java.net.InetAddress;
import java.net.Socket;
......@@ -8,15 +10,16 @@ import java.net.Socket;
*/
public class ServerModel {
private String hostName;
private String hostName = "";
private Socket socket;
private boolean joinrequest = false;
private NsdServiceInfo serviceInfo;
private ConnectionStatus connectionStatus = ConnectionStatus.NOT_CONNECTED;
public ServerModel(String hname, Socket sock)
public ServerModel(NsdServiceInfo serviceInfo, Socket socket)
{
this.hostName = hname;
this.socket = sock;
this.serviceInfo = serviceInfo;
this.socket = socket;
}
public String getHostName() {
......@@ -42,4 +45,20 @@ public class ServerModel {
public void setJoinrequest(boolean joinrequest) {
this.joinrequest = joinrequest;
}
public int getPort() {
return serviceInfo.getPort();
}
public String getHostAddress() {
return serviceInfo.getHost().getHostAddress();
}
public ConnectionStatus getConnectionStatus() {
return connectionStatus;
}
public void setConnectionStatus(ConnectionStatus connectionStatus) {
this.connectionStatus = connectionStatus;
}
}
......@@ -19,7 +19,7 @@
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Unknown"
android:text="kli"
android:id="@+id/txtname"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
......
......@@ -39,14 +39,19 @@
</LinearLayout>
<ImageButton
<Button
android:id="@+id/connectButton"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/disconnectButton"
android:text="Connect"/>
<Button
android:id="@+id/disconnectButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:src="@drawable/ic_transfer_within_a_station_black_48dp"
android:scaleType="fitXY"
style="@style/Widget.AppCompat.Button.Borderless"
/>
android:text="Disconnect"
android:enabled="false"/>
</RelativeLayout>
\ No newline at end of file
......@@ -9,9 +9,17 @@ import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
import onlab.kvizserver.model.ClientModel;
public class ClientListAdapter extends RecyclerView.Adapter<ClientListAdapter.ServerViewHolder> {
private final List<String> items = new ArrayList<>();
//private final List<String> items = new ArrayList<>();
private final ArrayList<ClientModel> items;
public ClientListAdapter(ArrayList<ClientModel> items) {
this.items = items;
}
@Override
public ServerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
......@@ -22,8 +30,7 @@ public class ClientListAdapter extends RecyclerView.Adapter<ClientListAdapter.Se
@Override
public void onBindViewHolder(final ServerViewHolder holder, final int position) {
final String item = items.get(position);
holder.clientNameTextView.setText(item);
holder.clientNameTextView.setText(items.get(position).getName());
}
@Override
......@@ -41,18 +48,19 @@ public class ClientListAdapter extends RecyclerView.Adapter<ClientListAdapter.Se
}
}
public void addItem(String item) {
items.add(item);
public void addItem() {
notifyItemInserted(items.size() - 1);
}
public void update(List<String> clients) {
items.clear();
items.addAll(clients);
public void update() {
notifyDataSetChanged();
}