Мне нужно изменить базовый URL-адрес во время выполнения. У меня есть кнопка входа в систему, и когда время нажатия кнопки входа в систему, я называюсь своим api входа как показано ниже:
логин api = http://192.168.0.61/api/authenticate
API_BASE_URL = http://192.168.0.61/api/
когда я получаю успешный ответ от первого API, я получаю URL-адрес клиентского сервера для изменения baseUrl.
CompanyUrlConfigEntity companyUrlConfigEntity = response.body (); как показано ниже:
Строка clientUrl = companyUrlConfigEntity. getBaseUrl ();
clientUrl = http://192.168.0.238/api/
В этом проекте в основном для клиентов или компаний, поэтому у них есть свой сервер. Каждая компания использует более 20 API. Поэтому мне нужно изменить базовый URL.
Я также проверяю ссылку ниже для изменения базового URL:
https://futurestud.io/tutorials/retrofit-2-how-to-change-api-base-url-at-runtime-2
и изменил такой код
public static void changeApiBaseUrl(String newApiBaseUrl) {
API_BASE_URL = newApiBaseUrl;
builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(new NullOnEmptyConverterFactory())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(new Gson()));
}
когда я отлаживал и проверял свой baseUrl, он отображается правильно, как показано ниже:
API_BASE_URL = http://192.168.0.238/api/
But when i call my customer api it shows the my first base url calling,
the url not changed.
expected customer api : http://192.168.0.238/api/customers
reality customer api : http://192.168.0.61/api/customers
I am also checked below link :
https://futurestud.io/tutorials/retrofit-2-how-to-use-dynamic-urls-for-requests
thats working , But each api need to pass fullPath url with each api like below:
@GET
public Call<ResponseBody> profilePicture(@Url String url);
But using this method , each api calling place i need to attach full path of url.
There is any other options? Please help me.
ServiceGenerator.class
public class ServiceGenerator {
public static String API_BASE_URL = "http://192.168.0.61/api/";
private static Retrofit retrofit;
private static OkHttpClient.Builder httpClient = new
OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(new NullOnEmptyConverterFactory())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(new
Gson()));
private ServiceGenerator() {
}
public static void changeApiBaseUrl(String newApiBaseUrl) {
API_BASE_URL = newApiBaseUrl;
builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(new NullOnEmptyConverterFactory())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(new Gson()));
}
public static Retrofit retrofit() {
return retrofit;
}
public static <S> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(Class<S> serviceClass,
final String authToken,
final ProgressListener progressListener) {
if (authToken != null) {
httpClient.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
final String headerValue = AUTHORIZATION_TYPE + authToken;
Request request = original.newBuilder()
.header(AUTHORIZATION_HEADER_KEY, headerValue)
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
}
addResponseProgressListener(progressListener);
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor httpLoggingInterceptor = new
HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(httpLoggingInterceptor);
}
if (authToken != null) {
if (picasso == null) {
setUpPicasso(authToken);
}
}
OkHttpClient client = httpClient.build();
httpClient.connectTimeout(15, TimeUnit.SECONDS);
httpClient.readTimeout(2, TimeUnit.MINUTES);
httpClient.writeTimeout(2, TimeUnit.MINUTES);
retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
}
@OnClick(R.id.bt_login)
void onLogin() {
checkValidityOfUser();
}
private void checkValidityOfUser() {
final Login login = getLoginCredentials();
Call<CompanyUrlConfigEntity> callCheckValidity = dataProcessController.
getApiClient().
checkValidityOfUsers(login.getUsername());
callCheckValidity.enqueue(new Callback<CompanyUrlConfigEntity>() {
@Override
public void onResponse(Call<CompanyUrlConfigEntity> call,
Response<CompanyUrlConfigEntity> response) {
if (response.code() == 200) {
CompanyUrlConfigEntity companyUrlConfigEntity = response.body();
boolean status = companyUrlConfigEntity.isValidUser();
if (status) {
String baseUrls = companyUrlConfigEntity.
getBaseUrl();
baseUrls = baseUrls + "/api/";
ServiceGenerator.changeApiBaseUrl(baseUrls);
logins();
} else {
ToastHelper.show("please contact admin");
}
} else {
ToastHelper.show("" + response.code() + response.message());
}
}
@Override
public void onFailure(Call<CompanyUrlConfigEntity> call, Throwable t) {
ToastHelper.show("please contact admin");
}
});
}
private void logins() {
login = getLoginCredentials();
Call<Void> callLogin = dataProcessController.
getApiClient().
login(login);
callLogin.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.code() == 200) {
} else if (response.code() == 401) {
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
}
});
}
@ZaidMirza, я обновил свой вопрос, добавив свой класс ServiceGenerator, пожалуйста, посмотрите его.
Когда вы вызываете метод changeApiBaseUrl? А когда вы звоните с измененным API?
@Macmist, привет, я только что обновил свой вопрос, добавив функцию вызова changeApiBaseUrl () и вызов новой функции api с измененным baseUrl (LoginFragment.java). Пожалуйста, загляните в него. Жду вашего ответа.
Может быть, вам нужно два клиента для модернизации?
@jestopaul спасибо за обновление. судя по всему, то, как вы это делаете, кажется правильным. Один вопрос, у вас в двух звонках dataProcessController.getApiClient(), как он работает? Вы регенерируете апиклиент в этой функции?
@Macmist, спасибо за ответ. ApiClient не восстанавливается. ApiClient.java -------------- общедоступный интерфейс ApiClient {@POST ("аутентифицировать") Вызов <Void> login (логин @Body Login); }} DataProcessController.java -------------------------- открытый класс DataProcessController {частный ApiClient apiClient = null; частный DataProcessController () {apiClient = ServiceGenerator.createService (ApiClient.class); }}
и BaseFragment выглядит следующим образом: BaseFragment.java ----------------- открытый абстрактный класс BaseFragment расширяет фрагмент {protected DataProcessController dataProcessController = DataProcessController .getDataProcessController (); }




Основываясь на ваших комментариях, я бы сказал, что вы правильно меняете URL-адрес API в своем конструкторе, но ваш второй вызов по-прежнему использует экземпляр службы, URL-адрес которого не изменился.
Чтобы объяснить немного больше, из того, что я понимаю, все выполняется следующим образом:
dataProcessController.getApiClient() в вашем первом вызове вы получаете службу, которая указывает на первый URL-адрес, а затем выполняете вызов.ServiceGenerator этим новым URL-адресом. Затем вы выполняете метод logins().dataProcessController.getApiClient() и выполняете с ним второй вызов. Однако, поскольку вы никогда не переделывали apiClient = ServiceGenerator.createService(ApiClient.class);, полученный вами экземпляр apiClient по-прежнему указывает на первый URL-адрес, потому что он не был уведомлен об изменении URL-адреса.Я бы попробовал здесь изменить метод getApiClient() в вашем классе DataProcessController на что-то вроде этого:
public ApiClient getApiClient() {
apiClient = ServiceGenerator.createService(ApiClient.class);
return apiClient;
}
и посмотрите, работает ли это лучше.
Или, если вы не хотите регенерировать службу внутри этой функции, вы также можете сделать что-то вроде этого:
public class DataProcessController {
private ApiClient apiClient = null;
private DataProcessController() {
regenerateClient();
}
public ApiClient getApiClient() { return apiClient; }
// add this to regenerate the client whenever url changes
public void regenerateClient() {
apiClient = ServiceGenerator.createService(ApiClient.class);
}
}
затем каждый раз, когда вы меняете URL-адрес, делайте следующее:
ServiceGenerator.changeApiBaseUrl(baseUrls);
dataProcessController.regenerateClient();
и вы должны получить клиента, который указывает на правильный URL-адрес каждый раз, когда вы делаете dataProcessController.getApiClient()
спасибо, человек работает. ServiceGenerator.changeApiBaseUrl (baseUrls); dataProcessController.regenerateClient (); у меня это сработало.
https://segunfamisa.com/posts/firebase-remote-config
Вы должны следовать концепции удаленной конфигурации firebase. Здесь вам не нужно хранить базовый URL-адрес в исходном коде, он будет извлечен из значений конфигурации firebase, которые хранятся на сервере firebase.
// fetch
mRemoteConfig.fetch(3000)
.addOnCompleteListener(this, new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
if (task.isSuccessful()) {
// update your base url here.
} else {
//task failed
}
}
});
Проголосовали против, потому что это не имеет ничего общего с вопросом OP. Речь идет совсем не о Firebase, а о модернизации.
возможно, вы реализовали одноэлементный шаблон и получили старый объект построителя. пожалуйста, покажите больше кода, где вы получаете объект построителя