如何使用Retrofit调用Traccar API?调用失败求助
Hey there, let's walk through the common pitfalls that might be causing your Retrofit Basic Auth request to fail, especially with your login flow in onCreate:
1. Double-check your Basic Auth implementation
First, make sure you're adding the Authorization header correctly. There are two reliable ways to do this with Retrofit:
Option 1: Use the @BasicAuth annotation
This is the cleanest approach—Retrofit handles encoding your credentials automatically:
public interface AuthApi { @POST("auth/login") Call<LoginResponse> attemptLogin( @BasicAuth Credentials userCredentials, @Body LoginPayload loginData ); } // Credentials class (simple POJO) public class Credentials { private String username; private String password; // Constructor, getters, setters }
Option 2: Manually encode the Authorization header
If you prefer to handle encoding yourself, ensure you use the correct Base64 format (no line breaks):
public interface AuthApi { @POST("auth/login") Call<LoginResponse> attemptLogin( @Header("Authorization") String authHeader, @Body LoginPayload loginData ); } // Generate the header in your Activity String rawCredentials = username + ":" + password; String authHeader = "Basic " + Base64.encodeToString(rawCredentials.getBytes(), Base64.NO_WRAP);
Note: Avoid using Base64.DEFAULT here—it adds line breaks which will break the auth header.
2. Fix your onCreate network call
You can't run network requests on the main thread! If you're using call.execute() directly in onCreate, you'll get a NetworkOnMainThreadException. Always use asynchronous callbacks with enqueue():
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); // Initialize your Retrofit service AuthApi authApi = RetrofitClient.getService(); String authHeader = "Basic " + Base64.encodeToString(("testUser:testPass").getBytes(), Base64.NO_WRAP); // Run the login request asynchronously authApi.attemptLogin(authHeader, new LoginPayload()) .enqueue(new Callback<LoginResponse>() { @Override public void onResponse(Call<LoginResponse> call, Response<LoginResponse> response) { if (response.isSuccessful()) { // Check if user is registered LoginResponse responseBody = response.body(); if (responseBody != null && responseBody.isRegistered()) { // Navigate to main screen startActivity(new Intent(LoginActivity.this, MainActivity.class)); } else { // Prompt user to complete registration Toast.makeText(LoginActivity.this, "Please finish registering", Toast.LENGTH_SHORT).show(); } } else { // Handle error responses (e.g., 401 Unauthorized) String errorMsg = "Login failed: " + response.code() + " - " + response.message(); Toast.makeText(LoginActivity.this, errorMsg, Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<LoginResponse> call, Throwable t) { // Handle network errors (no internet, server down) Toast.makeText(LoginActivity.this, "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
3. Ensure Session persistence is set up
If your API uses sessions to maintain auth state after login, you need to configure OkHttp to store and send cookies automatically. Add a CookieJar to your OkHttpClient:
OkHttpClient client = new OkHttpClient.Builder() .cookieJar(new CookieJar() { private final Map<String, List<Cookie>> cookieStore = new HashMap<>(); @Override public void saveFromResponse(HttpUrl url, List<Cookie> cookies) { cookieStore.put(url.host(), cookies); } @Override public List<Cookie> loadForRequest(HttpUrl url) { List<Cookie> cookies = cookieStore.get(url.host()); return cookies != null ? cookies : new ArrayList<>(); } }) .build(); // Attach this client to your Retrofit instance Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://your-api-domain.com/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .build();
4. Debug with OkHttp Logging
To see exactly what's being sent/received, add the OkHttp logging interceptor. This will show you the full request headers, body, and response details in Logcat:
// Add the dependency first if you haven't: implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0' HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(loggingInterceptor) // Add other configs (CookieJar, etc.) .build();
Check if the Authorization header is present and correctly formatted, and look for response codes like 401 (invalid credentials) or 500 (server error) to narrow down the issue.
内容的提问来源于stack exchange,提问作者Alex Onofre

