How to get the request url in retrofit 2.0 with rxjava?
Asked Answered
O

4

31

I'm trying to upgrade to Retrofit 2.0 and add RxJava in my android project. I'm making an api call and want to retrieve the url and it with the response data in sqlite as a cache

Observable<MyResponseObject> apiCall(@Body body);

And in the RxJava call:

myRetrofitObject.apiCall(body).subscribe(new Subscriber<MyResponseObject>() {
    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {

    }

    @Override
    public void onNext(MyResponseObject myResponseObject) {

    }
});

In Retrofit 1.9, we could get the url in the success callback:

        @Override
        public void success(MyResponseObject object, Response response) {
            String url=response.getUrl();
            //save object data and url to sqlite
        }

How do you do this with Retrofit 2.0 using RxJava?

Openhearted answered 18/8, 2016 at 10:40 Comment(1)
Any success on this? I also am searching for thisAndrosterone
S
48

Update:

After reading the question again:

If you want access to the raw response you need to define your API interface as:

Observable<Response<MyResponseObject>> apiCall(@Body body);

instead of:

Observable<MyResponseObject> apiCall(@Body body);

You can get the Url using:

response.raw().request().url()

here:
response is the response from Retrofit
raw is the response from OkHttp
request is the Request from OkHttp which contains the Url as HttpUrl.

Soke answered 18/8, 2016 at 10:54 Comment(2)
it is useful in retrofit1.9, but in retrofit2.0 and rxjava I can not retrieve response from retrofitSyndesmosis
@LordRaydenMK, Can we print requested url before get the response ? as we can print it without using Rxjava eg- https://mcmap.net/q/471237/-retrofit-2-check-call-urlUrticaria
L
1

Get response from API using rxjava use following code

Create class name API

public class Api {

private static final String BASE_URL="https://your_url";

private static Api instance;
private final IApiCall iApiCallInterface;

private Api() {
    Gson gson = new GsonBuilder().setLenient().create();
    final OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .connectTimeout(60, TimeUnit.SECONDS)
            .writeTimeout(60, TimeUnit.SECONDS)
            .readTimeout(60, TimeUnit.SECONDS)
            .build();
    Retrofit retrofit = new Retrofit.Builder().client(okHttpClient).baseUrl(BASE_URL)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create(gson)).build();

    iApiCallInterface = retrofit.create(IApiCall.class);
}

public static Api start() {
    return instance = instance == null ? new Api() : instance;
}

public Observable<Example> getSendMoneyCountries() {
    return iApiCallInterface.getCategoryList();
}
}

Crete Interface name IApiCall here you can make your all othe API requests

public interface IApiCall {
  //response in in json array
  @Headers("Content-Type: application/json")
  @GET("/json")
   Observable<Example> getCategoryList();
}

Write below code in your MainActivity.java

    private static Api api;
    api = Api.start();
    api.getSendMoneyCountries()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeWith(new DisposableObserver<Example>() {
                @Override
                public void onNext(Example response) {
                    //Handle logic
                    try {
                        populateCountryList(response);
                    }catch (Exception e)
                    {
                        finish();
                        Toast.makeText(MainActivity.this,"Unable to send money",Toast.LENGTH_SHORT).show();
                        //MainActivity.showTimeoutDialog();
                        e.printStackTrace();
                    }
                }

                @Override
                public void onError(Throwable e) {
                    //Handle error
                    Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onComplete() {
                }
            });
Legality answered 13/6, 2019 at 12:54 Comment(0)
M
0

Well, I will show you how I did, Handling API with retrofit & rxJava.

First create a ApiClient.class

     public class ApiClient {

            private static final String BASE_URL = "https://travellingbook.app/api/v2/";

        public static final String IMAGE_BASE_URL = "";

        private static File httpCacheDirectory = new File(UpasargaApplication.getAppContext().getCacheDir(), "new_responses");

        private static int cacheSize = 10 * 1024 * 1024; // 10 MiB

        private static Cache cache = new Cache(httpCacheDirectory, cacheSize);

        private static Retrofit retrofit = null;

        public static Retrofit getClient() {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();

            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            if (BuildConfig.DEBUG) {
                interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            } else {
                interceptor.setLevel(HttpLoggingInterceptor.Level.NONE);
            }

            builder.interceptors().add(interceptor);
            builder.authenticator(new ApiTokenAuthenticator());
            OkHttpClient httpClient = builder
                    .readTimeout(15, TimeUnit.SECONDS)
                    .connectTimeout(15, TimeUnit.SECONDS)
                    .writeTimeout(15, TimeUnit.SECONDS)
                    .addInterceptor(new ApiInterceptor())
                    .build();


            Gson gson = new GsonBuilder()
                    .setLenient()
                    .create();

            RxJava2CallAdapterFactory rxJava2CallAdapterFactory = RxJava2CallAdapterFactory.createWithScheduler(Schedulers.computation());


            if (retrofit == null) {
                retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                        .addConverterFactory(GsonConverterFactory.create(gson))
                        .addCallAdapterFactory(rxJava2CallAdapterFactory)
                        .client(httpClient)
                        .build();
            }
            return retrofit;
        }

Now, Add Interceptor.class and TokenAuthenticator.class (Based upon your rest API architecture. Here's a sample case.)

public class ApiInterceptor implements Interceptor {

    @NonNull
    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request originalRequest = chain.request();
        if (Utilities.getLoginResponse() == null || TextUtils.isEmpty(Utilities.getLoginUserToken())) {
            return chain.proceed(originalRequest);
        }


        Request request = originalRequest.newBuilder()
                .addHeader("Authorization", Utilities.getLoginUserToken())
                .addHeader("Accept", "Accept: application/x.school.v1+json")
                .header("Cache-Control", String.format("max-age=%d", 50000))
                .build();
        return chain.proceed(request);
    }
}

Now Create a LoginApiService.java interface.

public interface LoginApiService {

    @POST("login")
    @FormUrlEncoded
    Observable<Login> login(
            @Field("email") String email,
            @Field("password") String password
    );


    @POST("forgot_password")
    @FormUrlEncoded
    Observable<ServerResponse> forgotPassword(
            @Field("email") String email
    );


}

Now Implementing LoginPresenter.java Handles Logic.

public class LoginPresenter {

    private static final String TAG = LoginPresenter.class.getSimpleName();

    private WeakReference<View> view;

    CompositeDisposable compositeDisposable;

    public LoginPresenter(View view) {
        this.view = new WeakReference<>(view);
        this.compositeDisposable = new CompositeDisposable();

    }

    private View getView() throws NullPointerException {
        if (view != null)
            return view.get();
        else
            throw new NullPointerException("View is unavailable");
    }


    public void userLogin(String email, String password) {


        Observable<Login> loginObservable = ApiClient.getClient().create(LoginApiService.class)
                .login(email, password)
                .subscribeOn(Schedulers.io())
                .retry(AppConstants.API_RETRY_COUNT)
                .observeOn(AndroidSchedulers.mainThread());


        DisposableObserver<Login> loginDisposableObserver = new DisposableObserver<Login>() {

            @Override
            public void onNext(Login login) {

                if (getView() != null && login != null) {
                    getView().onUserLoginSuccess(login);
                }

            }

            @Override
            public void onError(Throwable e) {

                try {

                    getView().onFailure(UtilitiesFunctions.handleApiError(e));

                } catch (Exception ignored) {

                }

            }

            @Override
            public void onComplete() {

            }
        };

        compositeDisposable.add(loginObservable.subscribeWith(loginDisposableObserver));

    }


    public void forgotPassword(String email) {

        Observable<ServerResponse> loginObservable = ApiClient.getClient().create(LoginApiService.class)
                .forgotPassword(email)
                .subscribeOn(Schedulers.io())
                .retry(AppConstants.API_RETRY_COUNT)
                .observeOn(AndroidSchedulers.mainThread());

        DisposableObserver<ServerResponse> loginDisposableObserver = new DisposableObserver<ServerResponse>() {

            @Override
            public void onNext(ServerResponse serverResponse) {

                Log.e("onNext: ", new GsonBuilder().create().toJson(serverResponse));

                if (getView() != null && serverResponse != null) {
                    getView().onForgotPasswordSuccess(serverResponse);
                }

            }

            @Override
            public void onError(Throwable e) {

                ServerResponse serverResponse = new GsonBuilder().create().fromJson(e.getMessage(), ServerResponse.class);

                if (serverResponse != null) {

                    getView().onFailure(serverResponse.getMessage());
                } else {
                    try {

                        getView().onFailure(UtilitiesFunctions.handleApiError(e));

                    } catch (Exception ignored) {

                    }
                }


            }

            @Override
            public void onComplete() {

            }
        };

        compositeDisposable.add(loginObservable.subscribeWith(loginDisposableObserver));

    }


    public void onActivityStop() {

        if (getView() != null) {
            compositeDisposable.clear();

        }
    }


    public interface View {

        void onUserLoginSuccess(Login login);

        void onForgotPasswordSuccess(ServerResponse serverResponse);

        void onFailure(String message);

    }

Finally, we can access LoginPresenter.class from Activity/Fragment

public class LoginActivity extends AppActivity implements LoginPresenter.View {

private Button btnLogin;
    private LoginPresenter loginPresenter;

 @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    enter code here
        loginPresenter = new LoginPresenter(this);

    }
 @Override
    public void onUserLoginSuccess(Login login) {
        if (login != null) {
            Utilities.saveLoginResponse(login);
            Utilities.saveLoginResponse(login);
            hideProgressBarWork();
            if (login.getStatus()) {
                Utilities.setUserLoginCompleted();
            } else {
                ShowToastWithMessage("Your account has been disabled.");
            }
        }
    }

    @Override
    public void onForgotPasswordSuccess(ServerResponse serverResponse) {

    }

    @Override
    public void onFailure(String message) {
        hideProgressBarWork();
        ShowToastWithMessage(message);
    }

}

Queries & Suggestions are welcome.

Munoz answered 31/1, 2020 at 11:15 Comment(1)
Kindly take a look on my question related to this, #67635781Dalessandro
D
0

Simply call this method

@Override
public void onFailure(Call<List<loginModel>> call, Throwable t) {
        Log.v("rese",call.request().url().toString());
    }
});
Doorjamb answered 22/6, 2020 at 5:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.