I'm trying to set a connection between 2 devices. As a matter of fact, I'm writing a game application, and I want to run it on 2 devices. One of these devices is a virtual one, and the other one is my phone, a physical device. I need to run the application on both devices, and after finding each other, and connecting to each other, both will be redirected to the final activity in which the game algorithm will be implemented, between these 2. The following are my classes. Can anyone tell me where I'm wrong? I don't think the connection is even established.
package com.example.soccergamedevelopmentproject;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.net.PortUnreachableException;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.PublicKey;
import java.util.concurrent.CountDownLatch;
public class AcceptThread extends Thread{
private ServerSocket ServerDeviceSocket;
protected Socket ClientDeviceSocket;
protected CountDownLatch latch;
private int port ;
private boolean isAcceptThreadConnected = false;
public AcceptThread(CountDownLatch latch, int port){
this.latch = latch;
this.port = port;
}
@Override
public void run() {
InitializeServerSocket();
AcceptConnection();
CountDownLatchNotificationForClient();
AwaitForClient();
} // RUN
public void InitializeServerSocket(){
try {
ServerDeviceSocket = new ServerSocket(port); // Port is the characteristic of the Client.
isAcceptThreadConnected = true;
} catch (IOException e) {
e.printStackTrace();
}
// CONNECT
} // InitializeSocket
public void AcceptConnection(){
this.setName("Accept Thread Class");
try {
ClientDeviceSocket = ServerDeviceSocket.accept();
if(ClientDeviceSocket != null && ServerDeviceSocket != null){
CloseConnectionOnBothSides();
Log.i(FindingMatchActivity.class.getSimpleName(), "Both Socket are closed");
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} // AcceptConnection
public void CloseConnectionOnBothSides(){
try {
ClientDeviceSocket.close();
ServerDeviceSocket.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
} // Close SocketConnection
public void CountDownLatchNotificationForClient(){
this.latch.countDown();
} // LatchCountDown
public void AwaitForClient(){
try {
this.latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} // wait for the client
public boolean GetIsAcceptThreadConnected(){
return this.isAcceptThreadConnected;
}
} // AcceptThread
The ConnectThread
is also as follows:
package com.example.soccergamedevelopmentproject;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
public class ConnectThread extends Thread{
public final int MaxConnectionRetries = 2;
protected int ConnectionRetries = 0; // Initial
protected Socket DeviceSocket;
private String ipAddress; // For Socket Device
protected int port; // For Socket Device
public CountDownLatch clientLatch;
protected Handler handler;
protected boolean isConnectThreadConnected = false;
public ConnectThread(String ipAddress,
int port,
CountDownLatch clientLatch,
Handler handler){
this.ipAddress = ipAddress;
this.port = port;
this.clientLatch = clientLatch;
this.handler = handler;
}
@Override
public void run() {
setName(" Connect Thread Class");
InitializeDeviceSocket();
ConnectToTheServer();
} // RUN
public void InitializeDeviceSocket(){
try {
DeviceSocket = new Socket(this.ipAddress, this.port);
isConnectThreadConnected = true;
if(DeviceSocket != null){
CloseSocketConnection();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} // Initialize DeviceSocket
public void WaitForTheServer() {
try {
clientLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void HandleConnectionFailure(){
if(ConnectionRetries <= MaxConnectionRetries) {
ConnectionRetries += 1;
retryConnection();
} else{
Message handlerMessage = handler.obtainMessage();
handlerMessage.obj = "Connection Failed. Please Try again...";
handler.sendMessage(handlerMessage);
}
} // HandleConnection Failure
public void CloseSocketConnection(){
try {
DeviceSocket.close();
} catch (IOException e) {
e.printStackTrace();
HandleConnectionFailure();
}
} // Close Socket Connection
public void ConnectToTheServer(){
InetSocketAddress inetSocketAddress = new InetSocketAddress(this.ipAddress, this.port);
try {
clientLatch.countDown();
WaitForTheServer();
DeviceSocket.connect(inetSocketAddress);
} catch (IOException e) {
e.printStackTrace();
} finally {
CloseSocketConnection();
}
// CONNECT
} //ConnectTOtHEsERVER
public void retryConnection(){
try {
Thread.sleep(2000);
ConnectToTheServer();
} catch (InterruptedException e) {
e.printStackTrace();
}
} // Retry Connection
public void setIpAddress(String ipAddress){
this.ipAddress = ipAddress;
}
public boolean GetIsConnectThreadConnected(){
return this.isConnectThreadConnected;
}
} // ConnectThread
And finally, my FindingActivity
class is as follows:
package com.example.soccergamedevelopmentproject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.net.nsd.NsdServiceInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.format.Formatter;
import android.util.Log;
import android.widget.Toast;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
public class FindingMatchActivity extends AppCompatActivity {
private static final String TAG = "FindingMatch Activity";
public CountDownLatch latch;
private AcceptThread acceptThread;
private ConnectThread connectThread;
public final int port = 48720;
private String ipAddress;
public int IntegerIp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_finding_match);
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
IntegerIp = wifiInfo.getIpAddress();
ipAddress = Formatter.formatIpAddress(IntegerIp);
latch = new CountDownLatch(2);
acceptThread = new AcceptThread( latch, port);
StartThreads();
} // On Create
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "Connection lost");
}
public void StartThreads(){
connectThread = new ConnectThread(ipAddress, port, latch, new MyHandler(FindingMatchActivity.this));
connectThread.setIpAddress(ipAddress);
if(connectThread != null) {
acceptThread.start();
connectThread.start();
Log.i(TAG, "\n"+"Accept Thread Connection: "+acceptThread.GetIsAcceptThreadConnected() +
"\n" +
"Connect Thread Connection: " + connectThread.GetIsConnectThreadConnected());
if (acceptThread.GetIsAcceptThreadConnected() && connectThread.GetIsConnectThreadConnected()) {
NavigateToTheFinalActivity(this);
}
}
} // Start Threads
private static class MyHandler extends Handler{
protected WeakReference<FindingMatchActivity> activityRef;
public MyHandler(FindingMatchActivity activity){
activityRef = new WeakReference<>(activity);
}
@Override
public void handleMessage(@NonNull Message msg) {
FindingMatchActivity activity = activityRef.get();
if (activity != null) {
String messageFromConnectedThread = (String) msg.obj;
Toast.makeText(activity, messageFromConnectedThread, Toast.LENGTH_LONG).show();
}
}
} // MyHandler Class
public void NavigateToTheFinalActivity(Context context){
Intent GoTheFinalActivity = new Intent(context, FinalActivity.class);
context.startActivity(GoTheFinalActivity);
} // NavigateTotHEfINALaCtivity
} // Finding Match Activity