Retrofit 2 - Dynamic URL
I think you are using it in wrong way. Here is an excerpt from the changelog:
New: @Url parameter annotation allows passing a complete URL for an endpoint.
So your interface should be like this:
public interface APIService {
@GET
Call<Users> getUsers(@Url String url);
}
Set dynamic base url using Retrofit 2.0 and Dagger 2
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);
Dynamic Url with @Post request retrofit + hilt
@Url is a parameter annotation allows passing a complete URL for an endpoint, so it's not a base url, but it's the full endpoint url, and you can't use it with dynamic path @POST("{id}")
, this must be like that @POST()
and also @Query
can't be used with @Url
, so you have two solutions:
- The first is by keeping
@Url
and generate the full url by yourself (generate a url will the query) and give it to getConfiguration(url) function:
code:
@POST()
suspend fun getConfiguration(
@Url url: String,
): Config
- The second which is not recommended but it's easier, which is creating a new retrofit instance with the other base url and other api interface provided by the new retrofit instance, and with you can keep using
Query
:
code:
@POST("{id}")
suspend fun getConfiguration(
@Body configRequest: ConfigRequest,
@Query("id") id: String
): Config
Retrofit 2 - Dynamic URL
I think you are using it in wrong way. Here is an excerpt from the changelog:
New: @Url parameter annotation allows passing a complete URL for an endpoint.
So your interface should be like this:
public interface APIService {
@GET
Call<Users> getUsers(@Url String url);
}
How i change the retrofit URL at runtime
you must have to add these lines in your code:
First Step:
Add the new CallAdapter RxJavaCallAdapterFactory.create() when building a Retrofit instance.
public static final String BASE_URL = "http://google.com/";
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
Next step:
Update the APIService for example:-> savePost(String title, String body, String userId) method to become an Observable.
public interface APIService {
@GET
Call<ResponseBody> list(@Url String url);
//or
@POST("/posts")
@FormUrlEncoded
Observable<Post> savePost(@Field("title") String title,
@Field("body") String body,
@Field("userId") long userId);
}
Final step:
When making the requests, our anonymous subscriber responds to the observable's stream which emits event.
public void sendPost(String title, String body) {
// RxJava
mAPIService.savePost(title, body, 1).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Post>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Post post) {
showResponse(post.toString());
}
});
}
this is way you build your dynamic urls: want to learn more details full description link: Sending Data With Retrofit 2 HTTP Client for Android
and See base URL for details of how the value will be resolved against a base URL to create the full endpoint URL.
if you are doing using kotlin: follow this link. dynamic urls at Runtime with Retrofit 2
Add dynamic value in url retrofit
The exception is self-explanatory, You need to use a query parameter for key
. Something like
@GET("storage/presigned-url?bucketName=files&httpVerb=2&contentType=image/jpeg")
suspend fun fileUploadPathCheque(@Query("key") name: String): Response<String>`
and then call it appending payment-receipt/
to your passing parameter:
Api.fileUploadPathCheque("payment-receipt/" + UUID.randomUUID().toString().plus(".jpg"))
This should work for you.
Related Topics
What Is the 'App' Android Xml Namespace
Set Selected Item of Spinner Programmatically
Android Emulator Doesn't Take Keyboard Input - Sdk Tools Rev 20
Android Asynctask Example and Explanation
Recyclerview Horizontal Scroll Snap in Center
How to Set a Reminder in Android
Broadcastreceiver Not Receiving Boot_Completed
Android 4.3 Menu Item Showasaction="Always" Ignored
Embed Zxing Library Without Using Barcode Scanner App
In Eclipse, Unable to Reference an Android Library Project in Another Android Project
Change the Circle Color of Radio Button
How to Know an Application Is Installed from Google Play or Side-Load
Foreground Service Being Killed by Android
How to Use Searchview in Toolbar Android