Http GET调用失败排查:Web测试正常但代码调用持续失败
Hey there, let's dig into why your Retrofit call is failing even though the API works in a web test. I've gone through your code and spotted several key issues that could be causing this:
1. Missing Internet Permission (Critical for Android)
On Android, your app can’t make any network requests unless you explicitly grant it permission. If this line is missing from your AndroidManifest.xml, all HTTP calls will fail silently and trigger the onFailure callback.
Fix:
Add this permission inside the <manifest> tag (not nested under <application>):
<uses-permission android:name="android.permission.INTERNET" />
2. Static Fields in Rate Class Break Gson Parsing
Your Rate class uses static fields for all currency rates, but Gson (the converter you’re using with Retrofit) ignores static fields by default. This means when Retrofit tries to map the API’s response into your Response and Rate objects, it can’t populate those static rate values. In many cases, this parsing failure will cause the entire request to be marked as failed.
Fix:
Remove the static modifier from all fields in the Rate class:
public class Rate { public float ILS; public float EUR; public float USD; public float AUD; public float CAD; public float GBP; public float JPY; public float RUB; // Keep your getConversionRate method as-is (note: you might want to update the map keys to match the API's response keys instead of symbols like "€") }
3. Mismatched Field Name in Response Class
Looking at Fixer.io’s API structure, the date field in the response is named "date", but your Response class uses dateString. Gson relies on exact field name matches (unless you use annotations), so this mismatch will cause parsing errors that can break the entire request.
Fix:
Either rename the field to date, or add the @SerializedName annotation to map it correctly:
public class Response { public boolean success; public int timestamp; public String base; @SerializedName("date") // Maps the JSON "date" field to this Java field public String dateString; public Rate rates; }
4. Missing Query Parameters in FixerApi Interface
You didn’t share your FixerApi interface code, but your getResponse() method must include the access_key and symbols parameters that made your web test work. If these are missing from the Retrofit request, the API will return an error response, which can trigger onFailure or a non-successful onResponse.
Fix:
Define your interface to include the required parameters (dynamic values are better for maintainability):
public interface FixerApi { @GET("api/latest") Call<Response> getResponse( @Query("access_key") String accessKey, @Query("symbols") String symbols ); }
Then update your call to pass the values:
Call<Response> call = fixerApi.getResponse( "d4fa53a5bb8f9eccdedcd42d647de093", "ILS,EUR,USD,AUD,CAD,GBP,JPY,RUB" );
5. Plaintext HTTP Blocked (Android 9+)
Starting with Android 9 (API level 28), apps are blocked from making plaintext HTTP requests by default. If you’re using http://data.fixer.io/, this is almost certainly causing your request to fail.
Fix:
Switch to the HTTPS version of the API (the most secure and recommended solution):
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://data.fixer.io/") // Use HTTPS instead of HTTP .addConverterFactory(GsonConverterFactory.create()) .build();
6. Debug the Exact Failure Reason
To get clearer insight into what’s going wrong, update your onFailure callback to log the full error details:
@Override public void onFailure(Call<Response> call, Throwable t) { String errorDetails = "Request failed: " + t.getMessage(); Log.e("RetrofitError", errorDetails, t); Toast.makeText(getApplicationContext(), errorDetails, Toast.LENGTH_LONG).show(); }
This will tell you if the issue is related to network access, parsing, or something else entirely.
内容的提问来源于stack exchange,提问作者Harel Yacovian

