Home > Software engineering >  android - OkHttp3: unable to connect to websocket in android
android - OkHttp3: unable to connect to websocket in android

Time:12-15

I have a websocket hosted on a server which has been tested and works. I cant identify any error messages in the logs.

The connect to the servers websocket fails with no error

Btw I am new with android.

Here is the code from android. The WebListener class in empty.

package kean.pathfinder;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.widget.Button;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Polyline;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;

import kean.pathfinder.websocket.WebListener;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, LocationListener {

    private MapView map;

    private final Path path = new Path();
    private GoogleMap googleMap;
    private LocationManager locationManager;
    private WebSocket ws;
    private OkHttpClient client;

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

        map = findViewById(R.id.map);
        Button start = findViewById(R.id.start);
        Button undo = findViewById(R.id.undo);
        Button clear = findViewById(R.id.clear);

        client = new OkHttpClient();

        Request request = new Request.Builder().url("ws://myServer.ip").build();
        WebListener listener = new WebListener();
        ws = client.newWebSocket(request,listener);

        ws.send("Hi from android");

        ws.close(1000,"Session end");

        start.setOnClickListener(l -> {
            try {
                JSONObject object = new JSONObject();
                JSONArray array = new JSONArray();
                for (LatLng latLng : path.getPoints()){
                    JSONObject point = new JSONObject();
                    point.put("lat",latLng.latitude);
                    point.put("lng",latLng.longitude);
                    array.put(point);
                }
                object.put("points",array);
                ws.send(object.toString());
            } catch (JSONException e){
                e.printStackTrace();
            }
        });
        undo.setOnClickListener(l -> {
            path.undo();
            updatePoly();
        });
        clear.setOnClickListener(l -> {
            path.clear();
            updatePoly();
        });


        map.getMapAsync(this);
        map.onCreate(savedInstanceState);

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        requestLocation();
    }

    public void onMapReady(@NonNull GoogleMap googleMap) {
        googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
        this.googleMap = googleMap;

        googleMap.setOnMapClickListener(l -> {
            path.add(l);
            updatePoly();
        });
    }

    private final AtomicReference<Polyline> polyline = new AtomicReference<>();
    private void updatePoly(){
        Polyline p = polyline.get();
        if (p != null) p.remove();
        polyline.set(googleMap.addPolyline(path.getPoly()));
    }

    public void onLocationChanged(@NonNull Location location) {
        LatLng latLng = new LatLng(location.getLatitude(),location.getLongitude());
        googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,50));
        locationManager.removeUpdates(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 1){
            requestLocation();
        }
    }

    private void requestLocation()
    {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},1);
            return;
        }
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 400L, 1000f, this);
    }

    @Override
    protected void onStart() {
        super.onStart();
        map.onStart();
    }

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

    @Override
    protected void onPause() {
        super.onPause();
        map.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
        map.onStop();
        ws.close(1000,"Session ended");
        client.dispatcher().executorService().shutdown();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        map.onDestroy();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        map.onSaveInstanceState(outState);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        map.onLowMemory();
    }
}

Here is the manifest file

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.PathFinder"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="token" />

    </application>

</manifest>

I have also tested the code in a normal java project and it worked. Here is the code

package org.example;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.WebSocket;

public class Main {
    public static void main(String[] args) {
        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder().url("ws://myServer.ip").build();
        // Empty class
        WebListener listener = new WebListener();
        WebSocket ws = client.newWebSocket(request,listener);

        ws.send("Hello World");

        ws.close(1000,"End");

        client.dispatcher().executorService().shutdown();
    }
}

CodePudding user response:

Verify you manifest has Internet permission

<uses-permission android:name="android.permission.INTERNET"/>

Verify that you have clear traffic for unsecure ws connection

<application
    android:usesCleartextTraffic="true">

</application>

Implement the WebSocketListener and override onFailure to see errors.

@Override
public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
    Log.v(LOG_TAG, "OnFailure: "   response   ", "   t);
    super.onFailure(webSocket, t, response);
}
  • Related