I'm implementing retrofit in my app. I use code below to getString and write to file from server.
Callback callback = new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.i(TAG, "onResponse");
File file = new File(fileDirectory);
file.mkdirs();
File outputFile = new File(file,
XXX);
try {
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream(outputFile));
osw.write(new String(response.body().string()));
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.i(TAG,"onFailure, getTermAndPoliciesDocument()");
t.printStackTrace();
}
};
PortalService portalService = ServiceGeneratorDemo.createService(PortalService.class);
Call<ResponseBody> call = portalService.getStringFromFile(AppSetting.Default.TERM_AND_POLICIES_DOC_NAME);
call.enqueue(callback);
Now i want show information about download of that file. Like 1 - 100% to complete progress like below image. . Anyone know how to callback time remain ?
Now i want show information about download of that file. Like 1 - 100% to complete progress
Your image shows time remaining, but once you know the percentage complete, you can calcuate the time yourself. Here's how I found to get the percent progress update using Retrofit 2:
First, create a progress listener:
final ProgressResponseBody.ProgressListener progressListener = new ProgressResponseBody.ProgressListener() {
#Override public void update(long bytesRead, long contentLength, boolean done) {
int percent = (int)((100 * bytesRead) / contentLength);
//Do something with the progress (I sent the event through EventBus)
}
};
Next, create a client as shown here, which will call the listener:
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), progressListener))
.build();
}
})
.build();
Finally, specify the client when building Reftrofit:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build()
It took me a while to get this figured out and I wish I could find the link that provided the final information, but this is the code I'm using. (I thought it was on Future Studio but I don't see it.)
Related
I send request but there is no response and no error. It passes callAsync.enqueue(new Callback<GetCheapestResponseType>() method without entering into it.
This is my Service.class:
public class Service {
String urlGetCheapest = "https://services-api.ryanair.com/farfnd/3/";
public void getCheapestFromToSpain() {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(urlGetCheapest)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
httpClient.connectTimeout(5, TimeUnit.MINUTES) // connect timeout
.writeTimeout(5, TimeUnit.MINUTES) // write timeout
.readTimeout(5, TimeUnit.MINUTES); // read timeout
String outboundDepartureDateToString = "2021-12-31";
Date outboundDepartureDateFrom = new Date(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String outboundDepartureDateFromString = sdf.format(outboundDepartureDateFrom);
Controller controller = retrofit.create(Controller.class);
Call<GetCheapestResponseType> callAsync = controller.getCheapest("SXF", outboundDepartureDateFromString, outboundDepartureDateToString);
callAsync.enqueue(new Callback<GetCheapestResponseType>() {
#Override
public void onResponse(Call<GetCheapestResponseType> call, Response<GetCheapestResponseType> response) {
if (response.isSuccessful()) {
GetCheapestResponseType apiResponse = response.body();
//API response
System.out.println(apiResponse);
} else {
System.out.println("Request Error : " + response.errorBody());
}
}
#Override
public void onFailure(Call<GetCheapestResponseType> call, Throwable throwable) {
System.out.println(throwable);
}
});
}
}
This is my Controller interface:
public interface Controller {
#GET("/oneWayFares")
public Call<GetCheapestResponseType> getCheapest(
#Query("departureAirportIataCode") String departureAirportIataCode,
#Query("outboundDepartureDateFrom") String outboundDepartureDateFrom,
#Query("outboundDepartureDateTo") String outboundDepartureDateTo);
}
I've came across this problem in the past, This problem usually comes when your retrofit client can't parse your response into your Java class. I suggest you to double check your output with your java class field.
I'm putting the answer here so it's more visible.
The issue was that in the #GET had beginning "/" while the baseUrl had a trailing "/".
I had same problem, and checked my return type of Callback and response, then edited. So it worked for me.
This question basically wants to know how to use stored cookies for subsequent request. The long text below is just for example. Basic question is how to use the same cookie for all requests on a particular website.
Basically I am trying to reach the login page of a website within the android app. The website works the following way.
There are 3 urls to consider.
1 -> "http://www.example.com/timeoutPage"
2 -> "http://www.example.com/mainPage"
3 -> "http://www.example.com/loginPage"
The two main points to consider are
(1) If we directly go to the 3rd url (loginPage), it redirects to the 1st url(timeoutPage). The timeoutPage has a button to go to the mainPage.
(2) If we go to the 2nd url (mainPage), it gives us a cookie. Now, after getting the cookie, when we visit the 3rd url (loginPage), we are able to access it. The loginPage has a captcha so it's essential to visit it(loginPage) in order to login.
Without the cookie, which is given at visiting 2nd url(mainPage), we cannot directly access 3rd url(loginPage).
so what i am doing is to make a ClearableCookieJar and attach it to OkHttpClient.
OkHttpClient client;
ClearableCookieJar cookieJar;
CookieManager cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(this));
client = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
Request request = new Request.Builder()
.url("http://www.example.com/mainPage")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(myResponse);
}
});
}
}
});
Everthing is fine till here as i am able to print the html of mainPage in my textview.
Problem starts here when i make another request for the loginPage.
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
textView.setText("Failed to get response");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
final String myResponse2 = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
textView.setText(myResponse2);
}
});
}
}
});
Here i again make a request to the loginPage but i reach the timeoutPage. How should i make the request for the loginPage url so that my request sends the cookie which i stored in the cookieJar while making a request to mainPage. One way i thought of was
request = new Request.Builder()
.url("http://www.example.com/loginPage")
.addHeader("Cookie", cookieStringGivenAtMainPage)
.build();
But i don't know how to access that cookieStringGivenAtMainPage. How should i reach that loginPage?
I print the html of the response to see if i reached the correct page.
It seems the answer you want to know is the singleton pattern.
Please refer to below sample code. I got it from kakao developer site about 3 years ago.
public class NetworkManager {
private static NetworkManager instance;
private OkHttpClient client;
/**
* By using Singleton Pattern we can share cookie, client values.
**/
private NetworkManager() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
Context context = GlobalApplication.getGlobalApplicationContext();
ClearableCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(context));
builder.cookieJar(cookieJar);
builder.followRedirects(true);
builder.addInterceptor(new RedirectInterceptor());
File cacheDir = new File(context.getCacheDir(), "network");
if (!cacheDir.exists()) {
cacheDir.mkdir();
}
Cache cache = new Cache(cacheDir, 10 * 1024 * 1024);
builder.cache(cache);
builder.connectTimeout(30, TimeUnit.SECONDS);
builder.readTimeout(10, TimeUnit.SECONDS);
builder.writeTimeout(10, TimeUnit.SECONDS);
client = builder.build();
}
public static NetworkManager getInstance() {
if (instance == null) {
instance = new NetworkManager();
}
return instance;
}
public OkHttpClient getClient() {
return client;
}
}
In addition below is sample usage.
OkHttpClient client = NetworkManager.getInstance().getClient();
RequestBody formBody = new FormBody.Builder()
.add("userId", getTargetUserId())
.build();
Request request = new Request.Builder()
.url("www.test.com/insert.php")
.post(formBody)
.build();
client.newCall(request).enqueue(callback);
I'm trying to Post JSON object in my application's login page. I searched for many examples and tried for them. But only my android 4.3 devices is running well and the other upper api level devices is not even response coming back. My code like below:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.LoginBtn:
loading.show();
try {
login();
} catch (JSONException e) {
e.printStackTrace();
}
break;
}
}
public void login(){
okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.build();
final JSONObject JObje = new JSONObject();
try {
JObje.put("Username", String.valueOf(Username.getText()));
JObje.put("Password", String.valueOf(Password.getText()));
} catch (JSONException e) {
e.printStackTrace();
}
okhttp3.Request request = null;
okhttp3.RequestBody body = null;
body = new FormBody.Builder()
.addEncoded("JSONVALUE", String.valueOf(JObje))
.build();
request = new okhttp3.Request.Builder()
.url(context.getString(R.string.rutKontrolServis))
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.post(body)
.build();
client.newCall(request).enqueue(new okhttp3.Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
Log.d("TAG","responded");
}
});
}
the R.string.rutKontrolServis url is like this: https://ourwebsite.com/folder/package_name.mywebservice
In my gradle file I added dependency this:
compile 'com.squareup.okhttp3:okhttp:3.11.0'
Is there any different request syntax or any constraint about tls or ssl certificates with newer api level devices? Can someone show a point
Did you try to increase the connection timeout and read timeout? I think 10 seconds is too short:
okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.readTimeout(10,TimeUnit.SECONDS)
.build();
Increase to 30 seconds and try again.
Sometimes OkHTTP just suddenly stops responding - no onFailure results, no onResponse results, even after increasing timeout. Nothing.
Switching your wifi / network provider to another provider worked for me.
I need to get the XML file from the site. I'm learning to use Retrofit.
I need to make a request and attach my API key via the "X-AppId" header. It should look like this:
X-AppId: my key.
If I do this from the browser, I get the answer.
Through the retrofit I get the access
error 403 Forbidden code = 403, message = Forbidden, url = https: //
Tell me how it is implemented properly to receive an answer from the server code = 200
Here is my implementation:
public interface myAPIinterface {
#GET("/api/ru/index/route/?from=Minsk&to=Warsaw")
Call<Routes> getProducts();
}
This is the activity where I output to the log:
private void getProducts(){
final ProgressDialog loading = ProgressDialog.show(this,"Fetching Data","Please wait...",false,false);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Log.d(TAG, "getProducts");
httpClient.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.addHeader("X-AppId:", "97377f7b702d7198e47a2bf12eec74")
.build();
return chain.proceed(request);
}
});
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
myAPIinterface api = retrofit.create(myAPIinterface.class);
Call<Routes> call = api.getProducts();
call.enqueue(new Callback<Routes>() {
#Override
public void onResponse(#NonNull Call<Routes> call, #NonNull Response<Routes> response) {
Log.d(TAG, "onResponse");
Log.d(TAG, String.valueOf(kk));
Log.d(TAG, String.valueOf(response));
loading.dismiss();}
#Override
public void onFailure(Call<Routes> call, Throwable throwable) {
loading.dismiss();
Log.d(TAG, "onFailure" + throwable);
}
});
this is a log:
Response{protocol=http/1.1, code=403, message=Forbidden,
url=https://rasp.rw.by/api/ru/index/route/?from=Minsk&to=Warsaw}
if I take third-party sites where there are no headers, I get a response of 200 without problems. What am I doing wrong in this case? Thank you.
Oh, man, what are you doing. You can use annotations like #Query, #Header, etc.
public interface myAPIinterface {
#GET("/api/ru/index/route")
Call<Routes> getProducts(#Header("X-AppId:") String YOUR_APP_ID,
#Query("from") String from,
#Query("to") String to)
}
Then you can create request like this:
Retrofit retrofit = new Retrofit.Builder().
.baseUrl("https://rasp.rw.by")
.addConverterFactory(SimpleXmlConverterFactory.create())
.build();
retrofit.create(myAPIinterface.class).getProducts(myId, "Minsk", "Warsaw").enqueue ...
How It can help? You forgot to add header at second retrofit and then you have 403 error. So, You must add annotations, and this will be the last mistake when you forgot to put value to header/query/etc.
I'm trying to do a POST, but its returning me a error :
com.google.gson.stream.MalformedJsonException: Use
JsonReader.setLenient(true) to accept malformed JSON at line 1 column
1 path $
My Call:
#POST("BuscaPontos")
Call<PontuacaoModel> postPontuacao(#Body PontuacaoModel model);
And my Webservice consum:
try
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL_BUSCAR_CIDADE)
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
PontuacaoModel model = new PontuacaoModel();
model.setNome("Juina");
model.setEstado("Mato Grosso");
CallService.Pontuacao callService = retrofit.create(CallService.Pontuacao.class);
Call<PontuacaoModel> requestService = callService.postPontuacao(model);
requestService.enqueue(new Callback<PontuacaoModel>() {
#Override
public void onResponse(Call<PontuacaoModel> call, Response<PontuacaoModel> response) {
if(response.isSuccessful())
{
String i = response.message().toString();
}
}
#Override
public void onFailure(Call<PontuacaoModel> call, Throwable t) {
String i = t.toString();
}
});
}
catch (Exception ex)
{
}
Whats is wrong ?
I don't see a line in your code where you add client during initializing retrofit:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL_BUSCAR_CIDADE)
.client() // add a client instance here, e.g. OkHttpClient
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.build();
This is the issue with your response from server, that may not be correct format. Please install a tool called postman form here.
Use this tool to check whether the response is correct before do some coding.