Search code examples
javaandroidclientokhttp

Android app client can't connect to my server


I created a client and a server to train my self with POST request. That was in java windows program, and I had no problem, it was fully functional. Now I m trying to create an android version to have a client in app, using java as language, and I managed to create a get request with okhttp library, but seems it doesn't reach my server at all.

I checked:

  • the ip is correct, already tested with the windows client, its a local server, so I m using Ipv4 addres in the form of "http://x.x.x.x:25565/home"
  • the port is correctly portforwarded
  • my phone, which is running the app, have access to internet. I also already tried on a browser to reach the same url, obtaining the data I m looking for
  • internet permission to app, is correctly inserted in the manifest xml
  • I used a thread to run the script on the main activity responsable for preparing and sending the get request because I ve seen it is sugguested

My server send some message in the console whenever it receives request, but in this case it return me nothing. It really look like my app doesn't really send the request or rather it doesn't reach the server. Here s the code and and manifest. Any suggestion/idea?

//CODE

package com.example.provaserver;

import android.os.Bundle;

import com.google.android.material.bottomnavigation.BottomNavigationView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;

import com.example.provaserver.databinding.ActivityMainBinding;
import okhttp3.*;
import android.net.Uri;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.net.URLEncoder;



public class MainActivity extends AppCompatActivity {

    private ActivityMainBinding binding;
    OkHttpClient client = new OkHttpClient();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());

        BottomNavigationView navView = findViewById(R.id.nav_view);
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications)
                .build();
        NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
        NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
        NavigationUI.setupWithNavController(binding.navView, navController);

        TextView textViewResponse = findViewById(R.id.textViewResponse);



        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Request request = new Request.Builder()
                            .url("http://x.x.x.x:25565/home")
                            .build();

                    Log.d("NetworkRequest", "Inizio richiesta GET");
                    Call call = client.newCall(request);
                    Response response = call.execute();
                    Log.d("MainActivity", "Richiesta inviata, in attesa della risposta...");
                    if (response.isSuccessful()) {
                        final String responseData = response.body().string();

                        // Aggiorna l'interfaccia utente sul thread principale
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                // Esempio: aggiorna un TextView con la risposta
                                textViewResponse.setText(responseData);
                            }
                        });
                    } else {
                        runOnUiThread(() -> {
                            textViewResponse.setText("Errore nella risposta");
                        });
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }
}

//MANIFEST

<?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" />

    <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.ProvaServer"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

Solution

  • It's because you are using the unencrypted HTTP protocol instead of HTTPS. Starting with Android 9 (API level 28), cleartext support is disabled by default. For more information, please check out here.

    You can also check Logcat in Android Studio for a stacktrace like this.

    java.net.UnknownServiceException: CLEARTEXT communication to x.x.x.x not permitted by network security policy

    Option 1

    If you want to allow all unencrypted HTTP protocol URLs, you can add android:usesCleartextTraffic="true" to application tag of AndroidManifest.xml file.

    <manifest ...>
        <application
            android:usesCleartextTraffic="true"
            ...
    

    Option 2

    If you want to add only specific domain or URL, you can use networkSecurityConfig.

    • Create file res/xml/network_security_config.xml.

      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
           <domain-config cleartextTrafficPermitted="true">
               <domain includeSubdomains="true">127.0.0.1</domain>
           </domain-config>
      </network-security-config>
      
    • Add networkSecurityConfig to application tag of AndroidManifest.xml file.

      <manifest ...>
           <application
               android:networkSecurityConfig="@xml/network_security_config"
               ...