I'm using retrofit to get some data from the Flickr api. The method I'm making the call in looks like this:
public static List<String> getImageIds(int size) {
Call<PhotosList> call = flickrService.getPhotos(apiKey, format, "1");
Log.d("TEMP_TAG", "photo url: " + call.request().url().toString());
photoIds = new ArrayList<String>();
call.enqueue(new Callback<PhotosList>(){
#Override
public void onResponse(Call<PhotosList> call, Response<PhotosList> response) {
Log.d("TEMP_TAG", "it's getting here");
PhotosList photosList = response.body();
List<Photo> photos = photosList.getPhotos().getPhoto();
for(Photo photo : photos) {
Log.d("TEMP_TAG", "adding photo id to list: " + photo.getId());
photoIds.add(photo.getId());
}
}
#Override
public void onFailure(Call<PhotosList> call, Throwable t) {
// TODO: Clean up
Log.d("TEMP_TAG", "photoId: ");
}
});
Log.d("TEMP_TAG", "it's getting here too");
return photoIds;
}
However it is never getting into the onResponse() method. The first log statement within onResponse() never prints, neither does the log statement in onFailure(). When I try entering the URL that is returned by call.request().url().toString() in the browser it works fine, and I get the expected JSON. Why is my enqueue() method never firing?
Thanks for any help!
Use HttpLoggingInterceptor along with Retrofit.
If this helps, add this inside your build.gradle -
//Retrofit and OkHttp for Networking
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
//Logging Network Calls
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
Inside your APIClient class add this -
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
if(retrofit==null){
retrofit = new Retrofit.Builder()
.baseUrl(BuildConfig.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
}
return retrofit;
}
}
Kotlin Code
val interceptor : HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val client : OkHttpClient = OkHttpClient.Builder().apply {
addInterceptor(interceptor)
}.build()
fun getService(): Service {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(LiveDataCallAdapterFactory())
.client(client)
.build()
.create(Service::class.java)
}
And you will be able to log the Retrofit Network calls that you make.
Let me know if you need more information.
An OkHttp interceptor which logs HTTP request and response data.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Level.BASIC);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(logging)
.build();
You can change the log level at any time by calling setLevel.
There are 4 levels: NONE, BASIC, HEADERS, BODY
To log to a custom location, pass a Logger instance to the constructor.
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new
Logger() {
#Override public void log(String message) {
Log.d(TAG, "message: ");
}
});
From Gradle
compile 'com.squareup.okhttp3:logging-interceptor:(insert latest version)'
Follow this reference
EDITED: I also found this library which has a very nice structure and clean log. Try it!!
You can use the following class to log API calls
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
object HTTPLogger {
fun getLogger(): OkHttpClient {
/*
* OKHTTP interceptor to log all API calls
*/
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
return client
}
}
You can then call this class in your retrofit instance class like this
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClientInstance {
private var retrofit: Retrofit? = null
val retrofitInstance: Retrofit?
get() {
if (retrofit == null) {
retrofit = Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(HTTPLogger.getLogger())
.build()
}
return retrofit
}
}
The dependency required is
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.0'
Related
I am building an api client using retrofit with this method:
private fun createNewApiClient(authRefreshClient: AuthRefreshClient,
preferencesInteractor: PreferencesInteractor): ApiClient {
val loggingInterceptor = HttpLoggingInterceptor(PrettyLogger())
loggingInterceptor.level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
val okHttpClient = createHttpClientBuilder()
.addInterceptor(loggingInterceptor)
.build()
return Retrofit.Builder()
.client(okHttpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.baseUrl(Interactors.apiEndpoint)
.build()
.create(ApiClient::class.java)
}
Debug is set to true in my generated BuildConfig file:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
}
I can confirm that the call I am making with this client is being made because I put a lot statement in the throwable portion of RX's subscribe:
Interactors.api.apiClient.getUserByEmail(email).
.subscribe({
Log.d("Email exists")
//Success
}, {
Log.e("Call is failing")
}
})
But the body of the request is not showing up in my log statements. Nothing from okhttp is showing up. What is wrong with my implemention of okhttp?
Try to replace your PrettyLogger() with logger from HttpLoggingInterceptor
So replace yours:
val loggingInterceptor = HttpLoggingInterceptor(PrettyLogger())
in to:
val loggingInterceptor = HttpLoggingInterceptor()
I'm trying to implement auth via x-www-form-urlencoded with Retrofit 2 on Android but faced a problem, that Header Content-Type not set with #FormUrlEncoded annotation, as well as I'm trying to set it manually, but when I'm setting it with a typo like Cotent-Type it works correctly and I can see it in headers.
Retrofit version: 2.4.0
So my question: why #FormUrlEncoded not set a content type as well as #Header annotation or what can remove it from headers.
My request:
#FormUrlEncoded
#POST("account/login")
Single<LoginResponse> login(#Field("memberId") String memberId,
#Field("pin") String pin);
OkHTTP/Retrofit provider with interceptors:
#Singleton
#Provides
Retrofit provideRetrofit(final OkHttpClient client, final Moshi moshi) {
return new Retrofit.Builder()
.baseUrl(Configuration.BASE_URL)
.client(client)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
#Provides
OkHttpClient provideOkHttpClient(#AppContext final Context context) {
final OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(CONNECT_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.followRedirects(true)
.followSslRedirects(true)
.addInterceptor(createLanguageInterceptor(context));
if (BuildConfig.DEBUG) {
builder.addInterceptor(new LoggingInterceptor());
}
return builder.build();
}
Interceptor createLanguageInterceptor(#AppContext final Context context) {
Locale current = context.getResources().getConfiguration().locale;
return chain -> {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("Accept-Language", current.getLanguage());
Request request = builder.build();
Response response = chain.proceed(request);
return response;
};
}
As a workaround, I've implemented the following interceptor:
Interceptor createHeaderTransformationInterceptor() {
return chain -> {
final Request request = chain.request();
String dataType = request.header("Data-Type");
final Request resultRequest = dataType == null
? request
: chain.request().newBuilder()
.removeHeader("Data-Type")
.addHeader("Content-Type", dataType)
.build();
return chain.proceed(resultRequest);
};
}
and it works fine with the following annotation:
#Headers({"Data-Type: application/x-www-form-urlencoded"})
UPD: the reason that my interceptor didn't see that is in a place where the content type is stored. The right way to see that header in an interceptor:
if (requestBody.contentType() != null) {
logger.log("Content-Type: " + requestBody.contentType());
}
if (requestBody.contentLength() != -1) {
logger.log("Content-Length: " + requestBody.contentLength());
}
By this Request
#FormUrlEncoded
#POST("account/login")
Single<LoginResponse> login(#Field("memberId") String memberId,
#Field("pin") String pin);
method #POST and #FormUrlEncoded automatic add
Content-Type: application/x-www-form-urlencoded in header you can check in log by
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
it print all log in verbose mode
I have to use retrofit 2.0.2 with xml api response. But my custom xml converter is never called.
Playing around with this I found out:
if I use Volley to parse the same response, the same custom xml converter IS called;
if I apply GsonConverterFactory to my RestClient and parse json response, my custom JsonAdapter (#JsonAdapter(SomeAdapter.class)) IS called.
Anyone, how make my simple xml converter to be called? Am I doing something wrong, or retrofit 2.0.2 somehow doesn't support simple xml converter.
My java class where I parse response:
import org.simpleframework.xml.Element;
import org.simpleframework.xml.convert.Convert;
public class PassengerResponse {
#Element
#Convert(value = SomeConverter.class)
private String id;
}
Custom xml converter that is never called:
import org.simpleframework.xml.convert.Converter;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.OutputNode;
public class SomeConverter implements Converter<String> {
#Override
public String read(InputNode node) throws Exception {
return null;
}
#Override
public void write(OutputNode node, String value) throws Exception {
}
}
My retrofit RestClient:
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.simplexml.SimpleXmlConverterFactory;
public class RestClient2 {
private UserApiJSON userPassengerApi;
private static final int TIMEOUT = 120000;
private static RestClient2 INSTANCE;
public static RestClient2 getInstance() {
if (INSTANCE == null) {
INSTANCE = new RestClient2();
}
return INSTANCE;
}
private RestClient2() {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(SimpleXmlConverterFactory.create())
.client(okHttpClient.newBuilder().connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(loggingInterceptor)
.build())
.build();
userPassengerApi = retrofit.create(UserApiJSON.class);
}
public UserApiJSON getUserPassengerApi() {
return userPassengerApi;
}
}
Actually SimpleXmlConverterFactory has different method to create its instance.) If all you need is to make your custom Converer(s) work, do the next:
Strategy strategy = new AnnotationStrategy();
Serializer serializer = new Persister(strategy);
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(SimpleXmlConverterFactory.create(serializer))
.client(okHttpClient.newBuilder().connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(loggingInterceptor).build())
.build();
Note: if you add different converters, order does metter. Why? Watch Jake Wharton presentation.
To use your custom converter you have create custom Converter.Factory. And than add it to the retrofit using method addConverterFactory(). Below working example:
public class StringConverterFactory extends Converter.Factory {
public static StringConverterFactory create() {
return new StringConverterFactory();
}
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
if (String.class.equals(type)) {
return new Converter<ResponseBody, String>() {
#Override
public String convert(ResponseBody value) throws IOException {
return value.string();
}
};
}
return null;
}
}
And than add it retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addConverterFactory(StringConverterFactory.create())
.client(okHttpClient.newBuilder().connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
.addInterceptor(loggingInterceptor)
.build())
.build();
In Retrofit 2 allows multiple converters. There is video by Jake Wharton who talks about Retrofit 2 and it features like a multiple converters.
Inside Retrofit class there is a method nextRequestBodyConverter which returns converter for appropriate Type
public UsStatesApi providesApi(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Strategy strategy = new AnnotationStrategy();
Serializer serializer = new Persister(strategy);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(2, TimeUnit.MINUTES)
.writeTimeout(2, TimeUnit.MINUTES)
.readTimeout(2, TimeUnit.MINUTES)
.build();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(SimpleXmlConverterFactory.create(serializer))
.baseUrl("http://www.google.com")
.client(okHttpClient)
.build();
return retrofit.create( UsStatesApi.class);
}
I'm trying to perform a login action using Retrofit 2.0 using Dagger 2
Here's how I set up Retrofit dependency
#Provides
#Singleton
Retrofit provideRetrofit(Gson gson, OkHttpClient client) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(application.getUrl())
.build();
return retrofit;
}
Here's the API interface.
interface LoginAPI {
#GET(relative_path)
Call<Boolean> logMe();
}
I have three different base urls users can log into. So I can't set a static url while setting up Retrofit dependency. I created a setUrl() and getUrl() methods on Application class. Upon user login, I set the url onto Application before invoking the API call.
I use lazy injection for retrofit like this
Lazy<Retrofit> retrofit
That way, Dagger injects dependency only when I can call
retrofit.get()
This part works well. I got the url set to retrofit dependency. However, the problem arises when the user types in a wrong base url (say, mywifi.domain.com), understands it's the wrong one and changes it(say to mydata.domain.com). Since Dagger already created the dependency for retrofit, it won't do again.
So I have to reopen the app and type in the correct url.
I read different posts for setting up dynamic urls on Retrofit using Dagger. Nothing really worked out well in my case. Do I miss anything?
Support for this use-case was removed in Retrofit2. The recommendation is to use an OkHttp interceptor instead.
HostSelectionInterceptor made by swankjesse
import java.io.IOException;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
/** An interceptor that allows runtime changes to the URL hostname. */
public final class HostSelectionInterceptor implements Interceptor {
private volatile String host;
public void setHost(String host) {
this.host = host;
}
#Override public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String host = this.host;
if (host != null) {
//HttpUrl newUrl = request.url().newBuilder()
// .host(host)
// .build();
HttpUrl newUrl = HttpUrl.parse(host);
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
public static void main(String[] args) throws Exception {
HostSelectionInterceptor interceptor = new HostSelectionInterceptor();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Request request = new Request.Builder()
.url("http://www.coca-cola.com/robots.txt")
.build();
okhttp3.Call call1 = okHttpClient.newCall(request);
okhttp3.Response response1 = call1.execute();
System.out.println("RESPONSE FROM: " + response1.request().url());
System.out.println(response1.body().string());
interceptor.setHost("www.pepsi.com");
okhttp3.Call call2 = okHttpClient.newCall(request);
okhttp3.Response response2 = call2.execute();
System.out.println("RESPONSE FROM: " + response2.request().url());
System.out.println(response2.body().string());
}
}
Or you can either replace your Retrofit instance (and possibly store the instance in a RetrofitHolder in which you can modify the instance itself, and provide the holder through Dagger)...
public class RetrofitHolder {
Retrofit retrofit;
//getter, setter
}
Or re-use your current Retrofit instance and hack the new URL in with reflection, because screw the rules. Retrofit has a baseUrl parameter which is private final, therefore you can access it only with reflection.
Field field = Retrofit.class.getDeclaredField("baseUrl");
field.setAccessible(true);
okhttp3.HttpUrl newHttpUrl = HttpUrl.parse(newUrl);
field.set(retrofit, newHttpUrl);
Retrofit2 library comes with a #Url annotation. You can override baseUrl like this:
API interface:
public interface UserService {
#GET
public Call<ResponseBody> profilePicture(#Url String url);
}
And call the API like this:
Retrofit retrofit = Retrofit.Builder()
.baseUrl("https://your.api.url/");
.build();
UserService service = retrofit.create(UserService.class);
service.profilePicture("https://s3.amazon.com/profile-picture/path");
For more details refer to this link: https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests
This worked for me in Kotlin
class HostSelectionInterceptor: Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val host: String = SharedPreferencesManager.getServeIpAddress()
val newUrl = request.url().newBuilder()
.host(host)
.build()
request = request.newBuilder()
.url(newUrl)
.build()
return chain.proceed(request)
}
}
Add the interceptor to OkHttpClient builder
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HostSelectionInterceptor())
.cache(null)
.build()
This might be late but Retrofit allows you to use dynamic URLs while making the network call itself using #Url annotation.
I am also using Dagger2 to inject the Retrofit instance in my repositories and this solution is working fine for me.
This will use the base url
provided by you while creating the instance of Retrofit.
#GET("/product/123")
fun fetchDataFromNetwork(): Call<Product>
This ignore the base url
and use the url you will be providing this call at run time.
#GET()
fun fetchDataFromNetwork(#Url url : String): Call<Product> //
Thanks to #EpicPandaForce for help. If someone is facing IllegalArgumentException, this is my working code.
public class HostSelectionInterceptor implements Interceptor {
private volatile String host;
public void setHost(String host) {
this.host = HttpUrl.parse(host).host();
}
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String reqUrl = request.url().host();
String host = this.host;
if (host != null) {
HttpUrl newUrl = request.url().newBuilder()
.host(host)
.build();
request = request.newBuilder()
.url(newUrl)
.build();
}
return chain.proceed(request);
}
}
For latest Retrofit library, you can simply use singleton instance and change it with retrofitInstance.newBuilder().baseUrl(newUrl). No need to create another instance.
Dynamic url using Retrofit 2 and Dagger 2
You are able to instantiate new object using un-scoped provide method.
#Provides
LoginAPI provideAPI(Gson gson, OkHttpClient client, BaseUrlHolder baseUrlHolder) {
Retrofit retrofit = new Retrofit.Builder().addConverterFactory(GsonConverterFactory.create(gson)
.client(client)
.baseUrl(baseUrlHolder.get())
.build();
return retrofit.create(LoginAPI.class);
}
#AppScope
#Provides
BaseUrlHolder provideBaseUrlHolder() {
return new BaseUrlHolder("https://www.default.com")
}
public class BaseUrlHolder {
public String baseUrl;
public BaseUrlHolder(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
}
Now you can change base url via getting baseUrlHolder from the component
App.appComponent.getBaseUrlHolder().set("https://www.changed.com");
this.loginApi = App.appComponent.getLoginApi();
Please look into my workaround for Dagger dynamic URL.
Step1: Create an Interceptor
import android.util.Patterns;
import com.nfs.ascent.mdaas.repo.network.ApiConfig;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class DomainURLInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
String requestUrl = original.url().toString();
String PROTOCOL = "(?i:http|https|rtsp)://";
String newURL = requestUrl.replaceFirst(PROTOCOL, "")
.replaceFirst(Patterns.DOMAIN_NAME.toString(), "");
newURL = validateBackSlash(newURL) ? ApiConfig.BASE_URL.concat(newURL) : newURL.replaceFirst("/", ApiConfig.BASE_URL);
original = original.newBuilder()
.url(newURL)
.build();
return chain.proceed(original);
}
private boolean validateBackSlash(String str) {
if (!str.substring(str.length() - 1).equals("/")) {
return true;
}
return false;
}
}
Step 2:
add your newly created interceptor in your module
#Provides
#Singlton
DomainURLInterceptor getChangeURLInterceptor() {
return new DomainURLInterceptor();
}
step 3:
add interceptor into list of HttpClient interceptors
#Provides
#Singlton
OkHttpClient provideHttpClient() {
return new OkHttpClient.Builder()
.addInterceptor(getChangeURLInterceptor())
.readTimeout(ApiConfig.API_CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.connectTimeout(ApiConfig.API_CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.build();
}
step 4:
#Provides
#Singlton
Retrofit provideRetrofit() {
return new Retrofit.Builder()
.baseUrl(ApiConfig.BASE_URL) // this is default URl,
.addConverterFactory(provideConverterFactory())
.client(provideHttpClient())
.build();
}
Note: if the user has to change the Base URL from settings, remember to validate the newly created URL with below method:
public final static boolean isValidUrl(CharSequence target) {
if (target == null) {
return false;
} else {
return Patterns.WEB_URL.matcher(target).matches();
}
}
I am trying get specific data from Firebase. Using REST API and Retrofit 2 on client side.
Here is my JSON structure on Firebase:
{
"profiles" : {
"-KAG0XPBVNNF_RT55lwV" : {
"GCMTocken" : "rtdjhsrfjt546456",
"firstName" : "P",
"gender" : 1,
"lastName" : "Strongman",
"likes" : 0,
"nickname" : "drake1",
"uid" : "facebook:957484"
}
}
}
Request interface:
#GET("/profiles.json")
Observable<Profile> getProfile(#Query("orderBy") String key, #Query("equalTo") String uid);
On this request i always get:
java.lang.IllegalArgumentException: No Retrofit annotation found. (parameter #1)
for method FirebaseAPI.getProfile
EDIT
i need this request:
https://incandescent-torch-4.firebaseio.com/profiles.json?orderBy="uid"&equalTo="facebook:95748485767896"
My retrofit setup:
String BASE_FIREBASE_URL = "https://incandescent-torch-4.firebaseio.com";
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_FIREBASE_URL)
.client(okHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
restAPI = retrofit.create(FirebaseAPI.class);
Request from RxJava:
RestFirebaseClient.getInstance().getProfile(authData.getUid())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Profile>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(Profile profile) {
}
});
I observe in your code request #GET request just put "/" & make sure in you url you have to remove "/" at the end of url like -
like this -
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://incandescent-torch-4.firebaseio.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
#GET("/profiles.json")
Observable<Profile> getProfile(#Query("orderBy") String key, #Query("equalTo") String uid);
This is included in documentation of retrofit.
Add Retrofit 2 dependency to Gradle:
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
compile 'com.squareup.retrofit2:converter-jackson:2.0.0-beta3'
compile 'com.squareup.okhttp3:logging-interceptor:3.0.0-RC1'
Initialize Retrofit:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new HttpLoggingInterceptor()
.setLevel(HttpLoggingInterceptor.Level.BODY))
.addInterceptor(new TokenInterceptor())
.addInterceptor(new AuthenticationInterceptor())
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://your_url/")
.addConverterFactory(JacksonConverterFactory.create())
.client(client)
.build();
Create Retrofit services, such as:
import retrofit2.Call;
import retrofit2.http.GET;
public interface ProfileService {
#GET("profile")
Call<User> get();
}
I used #GET("profile") and finally url was: http://your_url/profile
You maybe try change Observable<Profile> to Call<Profile> and delete .json from #GET("profiles.json")