Slim+Retrofit安卓App请求异常问题求助
Hey there, let's dig into why your Retrofit requests are failing on your laptop setup while working fine on your desktop. I’ve looked over your code and the issue details, here are practical troubleshooting steps and fixes to try:
Before diving into code, make sure the basics are working:
- Test your API directly in the browser: On your laptop, open a browser and paste your
BASE_URL_PC(e.g.,http://192.168.43.71/CharmAppAPI/public/). If you can’t access it, your Slim API isn’t running properly on your laptop, or your network is blocking it. - Check firewall settings: Windows Firewall on your laptop might be blocking incoming requests to your API port. Try temporarily disabling it to test, or add an exception for your web server (Apache/Nginx/PHP built-in server) to allow local and LAN access.
- Fix emulator network mismatch: Android Studio’s emulator sometimes uses a separate network that doesn’t align with your laptop’s WiFi. Try:
- Using
adb reverseto forward requests: Runadb reverse tcp:80 tcp:80(replace 80 with your API port if different) in your terminal, then set Retrofit’s base URL tohttp://localhost/CharmAppAPI/public/—this routes emulator requests directly to your laptop’s local API. - Switching the emulator’s network mode to "Bridge" (if using Genymotion) to match your laptop’s network segment.
- Using
Your RetrofitClient uses a singleton pattern, but once it’s initialized, it won’t pick up changes to BASE_URL_PC—this means even if you update the IP, your app is still using the old base URL from the first initialization!
Here’s how to fix it:
Option 1: Add a reset method for the singleton
public class RetrofitClient { private static final String BASE_URL = "http://147.96.127.212/CharmAppAPI/public/"; private static final String BASE_URL_PC = "http://192.168.43.71/CharmAppAPI/public/"; private static RetrofitClient instance; private Retrofit retrofit; private RetrofitClient(){ retrofit = new Retrofit.Builder() .baseUrl(BASE_URL_PC) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static synchronized RetrofitClient getInstance(){ if(instance == null){ instance = new RetrofitClient(); } return instance; } // Add this method to reset the singleton when changing IPs public static void resetInstance() { instance = null; } public APICalls getAPI(){ return retrofit.create(APICalls.class); } }
Call RetrofitClient.resetInstance() right after you update the BASE_URL_PC value, then re-fetch the instance to use the new IP.
Option 2: Pass the base URL to the singleton
Make the singleton dynamic so it uses the current URL every time:
public class RetrofitClient { private static RetrofitClient instance; private Retrofit retrofit; private RetrofitClient(String baseUrl){ retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static synchronized RetrofitClient getInstance(String baseUrl){ if(instance == null){ instance = new RetrofitClient(baseUrl); } // Refresh the instance if the base URL changed else if(!instance.retrofit.baseUrl().toString().equals(baseUrl)) { instance = new RetrofitClient(baseUrl); } return instance; } public APICalls getAPI(){ return retrofit.create(APICalls.class); } }
Now call RetrofitClient.getInstance(BASE_URL_PC) to ensure you’re always using the latest IP.
You can’t debug what you can’t see. Add Retrofit’s logging interceptor to view full request/response details in Logcat:
- Add this dependency to your module-level
build.gradle:
implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
- Update your
RetrofitClientto include the interceptor:
private RetrofitClient(String baseUrl){ // Enable full request/response logging HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(logging) .build(); retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .client(client) // Attach the logging client .addConverterFactory(GsonConverterFactory.create()) .build(); }
Now check Logcat for the OkHttp tag—you’ll see exactly if the request was sent, what URL was used, response status codes (like 404, 500, or connection timeouts), and error messages.
Starting with Android 9 (API 28), apps block plain HTTP requests by default. If your API uses HTTP (not HTTPS), you need to allow it:
- Add this to your
AndroidManifest.xmlinside the<application>tag:
android:usesCleartextTraffic="true"
Or for a more secure setup, create a network security config file (res/xml/network_security_config.xml):
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">192.168.43.71</domain> <!-- Laptop IP --> <domain includeSubdomains="true">147.96.127.212</domain> <!-- Desktop IP --> </domain-config> </network-security-config>
Then reference it in AndroidManifest.xml:
android:networkSecurityConfig="@xml/network_security_config"
Start with the network checks first—most of the time, it’s a firewall or emulator network issue. If that doesn’t work, enable logging to get concrete error details to narrow it down.
内容的提问来源于stack exchange,提问作者Kougami

