Skip to content

How to fix the Issue with replacing AsyncTask to connect socket?

I’m trying to use This approach(Marked Answer) to replace my code with AsyncTask to make connection between user in android and server, And here’s what I’ve done :

Note: I’m not using any specific pattern, just trying to achieve this goal on a basic structure.

MainActivity :

public class MainActivity extends AppCompatActivity {
    private ClientConnection connection;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        connection = new ClientConnection(inputServerIp.getText().toString(), inputUserName.getText().toString(), Integer.parseInt(inputPort.getText().toString()));
    }
}

ClientConnection :

public class ClientConnection {
    private Socket serverSocket;
    private ConnectionTask taskRunner;

    public ClientConnection(String ipAddress, String userName, int dstPort) {
        this.ipAddress = ipAddress;
        this.userName = userName;
        this.dstPort = dstPort;
    }

    public void connect() {
        taskRunner.executeAsync(new ConnectionRunningTask(ipAddress, dstPort), (data) -> {
            serverSocket = data;
        });
    }

ConnectionTask :

public class ConnectionTask {

    private final Executor executor = Executors.newSingleThreadExecutor();
    private final Handler handler = new Handler(Looper.getMainLooper());

    public interface Callback<R> {
        void onComplete(R result);
    }

    public void executeAsync(Callable<R> callable, Callback<R> callback) {
        executor.execute(() -> {
            try {
                final R result = callable.call();
                handler.post(() -> {
                    callback.onComplete(result);
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

ConnectionRunningTask:

public class ConnectionRunningTask implements Callable<Socket> {
    private final String ipAddress;
    private final Integer dstPort;

    public ConnectionRunningTask(String ipAddress, Integer dstPort) {
        this.ipAddress = ipAddress;
        this.dstPort = dstPort;
    }

    @Override
    public Socket call() throws IOException {
        return new Socket(ipAddress, dstPort);
    }
}

So base on the above code I’ll try to explain what I’ve tried and what is the current problem :

Problem: base on the above code I’m getting the below error in connect() which it is telling me data is R and you can’t set it to serverSocket, and due to this error I can’t build the application.

Then I’ve tried to replace all R with Socket in the ConnectionTask class ( R in Callback and Callable), which in this case application was able to build and run.

public interface Callback<Socket> {
    void onComplete(Socket result);
}

public void executeAsync(Callable<Socket> callable, Callback<Socket> callback) {
    executor.execute(() -> {
        try {
            final Socket result = callable.call();
            handler.post(() -> {
                callback.onComplete(result);
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
}

But based on the above approach I’ll get an error when I hit connect button, and here’s what I’ve got :

2021-12-06 04:02:26.942 16417-16417/ir.atlaspio.atlasclientchat E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ir.atlaspio.atlasclientchat, PID: 16417
    java.lang.NullPointerException: Attempt to invoke virtual method 'void ir.atlaspio.atlasclientchat.networking.ConnectionTask.executeAsync(java.util.concurrent.Callable, ir.atlaspio.atlasclientchat.networking.ConnectionTask$Callback)' on a null object reference
        at ir.atlaspio.atlasclientchat.networking.ClientConnection.connect(ClientConnection.java:38)
        at ir.atlaspio.atlasclientchat.MainActivity$1.onClick(MainActivity.java:61)
        at android.view.View.performClick(View.java:4780)
        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
2021-12-06 04:07:27.221 16417-16417/ir.atlaspio.atlasclientchat I/Process: Sending signal. PID: 16417 SIG: 9

On the Server-Side I’ve also checked incoming connections, and nothing happened there…

Answer

You’re not instantiating taskRunner inside ClientConnection. Add this line to the constructor:

public ClientConnection(String ipAddress, String userName, int dstPort) {
    this.ipAddress = ipAddress;
    this.userName = userName;
    this.dstPort = dstPort;
    this.taskRunner = new ConnectionTask(); // <-- this line here
}