I'm using Retrofit on my app to download a video file from the server, in the request i need to do a Post request,
on the interface I have added the parameters needed it....and on the java function I'm passing the parameters too, but
when I try to run the code i get an error:
java.lang.RuntimeException: An error occurred while executing
doInBackground()
#Headers("Content-Type: application/json; charset=UTF-8")
#Streaming
#POST
Call<ResponseBody> downloadFileStream(#Url String url, #QueryMap Map<String, Object> postdata);
private void downloadFile(String url) {
FileDownloadClient fileDownloadClient = retrofit.create(FileDownloadClient.class);
Call<ResponseBody> call = fileDownloadClient.downloadFileStream(url,postdata);
postdata.put("user", "test#test.com");
postdata.put("test", "test");
Call<ResponseBody> call = fileDownloadClient.downloadFileStream(url, postdata);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
boolean success = writeResponseBodyToDisk(response.body());
return null;
}
}.execute();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity.this, "Mal", Toast.LENGTH_LONG).show();
}
});
}
I was having the same problm, try this...this worked for me
Your interface:
public interface FileDownloadClient {
#Streaming
#POST("yourAPI")
Call<ResponseBody> downloadFileStream(#Body Map<String, Object> postdata);
}
Change this on your downloadFile:
private void downloadFile() {
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("yourwebsite/api/")
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.build();
FileDownloadClient fileDownloadClient = retrofit.create(FileDownloadClient.class);
Map<String, Object> postdata = new HashMap<>();
postdata.put("user", "test#test.com");
postdata.put("test", "test");
Call<ResponseBody> call = fileDownloadClient.downloadFileStream(postdata);
}
Grandle:
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.google.code.gson:gson:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.5.0'
Related
I am creating android application which uses retrofit. I have used spring as rest api. I have used authentication with JWT. I have use two interceptor here RequestInterceptor and ResponseInterceptor. The scenario of calling BASE_URL/hello api with expire JWT is as below
client call /hello with expired accesstoken in header using RequestInterceptor
server check token and response with code 401/403
client check response code and call /refresh using ResponseInterceptor with refreshtoken in header
Server check refreshtoken and response with new accesstoken
now the problem is how to call again /hello. I want this for each request. How can i predict which request has been made last.
Here is the code:
part of the code where /hello is called
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Call<HelloResponse> call= RetrofitFactoryWithJwt.getRetrofitInstance(getApplicationContext()).helloUser();
call.enqueue(new Callback<HelloResponse>() {
#Override
public void onResponse(Call<HelloResponse> call, Response<HelloResponse> response) {
Log.d(TAG,"after call in enque");
if(response.code()==200)
{
Log.d(TAG,response.body().getSuccess());
}
else
{
Log.d(TAG,"problem in response:"+response.code());
}
}
#Override
public void onFailure(Call<HelloResponse> call, Throwable t) {
Log.d(TAG,"onfailure"+t.getMessage());
}
});
Intent intent = new Intent( getApplicationContext(), MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
});
RequestInterceptor.java
public class RequestInterceptor implements Interceptor {
Context context;
String TAG="heyrequest";
public RequestInterceptor(Context context)
{
this.context=context;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
//if url is /refresh add refresh token in header instead of accesstoken
if(originalRequest.url().encodedPath().equalsIgnoreCase("/refresh"))
{
SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
String refreshvalue=preferences.getString("refreshtoken","");
// rewrite the request
Request newRequest=originalRequest.newBuilder()
.addHeader("Authorization","Bearer "+refreshvalue)
.build();
return chain.proceed(newRequest);
}
//for context we have use requestinterceptor context construction
SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
String tokenvalue=preferences.getString("accesstoken","");
// rewrite the request
Request newRequest=originalRequest.newBuilder()
.addHeader("Authorization","Bearer "+tokenvalue)
.build();
return chain.proceed(newRequest);
}
}
ResponseInterceptor.java
public class ResponseInterceptor implements Interceptor {
Context context;
String TAG="heyresponse";
String accesstoken=null;
Response response=null;
public ResponseInterceptor(Context context)
{
this.context=context;
}
#Override
public Response intercept(final Chain chain) throws IOException {
final Request request=chain.request();
response = chain.proceed(request);
if(response.code()==401 || response.code()==403)
{
accesstoken=getNewToken();
}
return chain.proceed(request);
}
public String getNewToken()
{
Call<RefreshResponse> call= RetrofitFactoryWithJwt.getRetrofitInstance(context).refreshToken();
call.enqueue(new Callback<RefreshResponse>() {
#Override
public void onResponse(Call<RefreshResponse> call, retrofit2.Response<RefreshResponse> response1) {
Log.d(TAG,"in refreshtoken call");
if(response1.code()==200)
{
accesstoken=response1.body().getAccesstoken();
Log.d(TAG,accesstoken);
SharedPreferences preferences = context.getSharedPreferences("tokens", MODE_PRIVATE);
preferences.edit().putString("accesstoken", accesstoken).apply();
}
else
{
Log.d(TAG,"problem in response:"+response1.code());
}
}
#Override
public void onFailure(Call<RefreshResponse> call, Throwable t) {
Log.d(TAG,"onfailure:"+t.getMessage());
}
});
return accesstoken;
}
}
I solved this problem by using authenticator for handle the response and interceptor for adding header in request
All the thing working fine but how to call the the user{first_name,last_name,email}
You have to call a retrofit method in this way,
#FormUrlEncoded
#POST("employer/login")
Call<ResponseModelEmplyrLogin> loginEmployer(
#Field("data") String data);
public void loginEmployer(String data, final MyApiCallbackEmplyrLogin<EmployrDataBean> callback) {
ApiInterface apiService = ApiClient.createService();
Call<ResponseModelEmplyrLogin> call = apiService.loginEmployer(data);
call.enqueue(new Callback<ResponseModelEmplyrLogin>() {
#Override
public void onResponse(Call<ResponseModelEmplyrLogin> call, Response<ResponseModelEmplyrLogin> response) {
//Write your code
}
#Override
public void onFailure(Call<ResponseModelEmplyrLogin> call, Throwable t) {
//Write your code
}
});
}
Check out this link https://www.androidtutorialpoint.com/networking/retrofit-android-tutorial/ ...I think this will be helpful
i'm having issues getting Retrofit 2.0 to send POST requests to Python-Django.
Here's my Retrofit method.
public void sendNetworkRequest(User user) {
//Cria instância retrofit
final Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://127.0.0.1:8000/")
.addConverterFactory(GsonConverterFactory.create())
.build();
UserService services = retrofit.create(UserService.class);
Call<User> call = services.createAccount(user);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Toast.makeText(CadastrarActivity.this, "Você foi cadastrado com sucesso!", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<User> call, Throwable t) {
CheckConnection checkConnection = new CheckConnection();
if (checkConnection.equals(null)){
Toast.makeText(CadastrarActivity.this, "Conecte-se a internet!", Toast.LENGTH_SHORT).show();
}
else {
Log.e("heurys", t.getMessage());
System.out.println(t.getStackTrace());
Toast.makeText(CadastrarActivity.this, "Algo deu errado!", Toast.LENGTH_SHORT).show();
}
}
});
}
Here's my interface method used in the Rest call:
public interface UserService {
#POST("rest/cadastro")
Call<User> createAccount(#Body User user);
}
And here's my traceback error:
04-03 12:58:43.726 18692-18692/com.example.ccyrobuosi.estudos E/heurys: Failed to connect to /127.0.0.1:8000
In advance, my Python code works just fine, i used Postman to test it, and its getting the requests properly.
I'm getting started working with Android Studio, and I'd like to make a simple application to grab raw HTML from a URL. I've set up Volley to do this using the basic example at http://developer.android.com/training/volley/simple.html, which works fine for public URLs.
The URL I want to access requires specific headers and cookies, which I have the static values of on hand. How can I assign these values to my request?
public void grabHTML(View view) {
RequestQueue queue = Volley.newRequestQueue(this);
String url = getString(R.string.urlpath);
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
mTextView.setText(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
});
queue.add(stringRequest);
}
EDIT:
I was able to apply the solution from How are cookies passed in the HTTP protocol? to manually set my request headers.
Use the solution How are cookies passed in the HTTP protocol? here to manually set headers to your request. My code ended up looking like this:
package com.pesonal.webrequestexample;
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.StringRequest;
import java.util.HashMap;
import java.util.Map;
public class StringRequestWithCookies extends StringRequest {
private Map<String, String> cookies;
public StringRequestWithCookies(String url, Map<String, String> cookies, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(Request.Method.GET, url, listener, errorListener);
this.cookies = cookies;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("header1","value");
headers.put("header2","value");
return headers;
}
}
and in the relevant activity...
public void grabHTML(View view) {
String url = getString(R.string.urlpath);
RequestQueue queue = Volley.newRequestQueue(this);
StringRequestWithCookies stringRequest = new StringRequestWithCookies(
url,getCookies(),
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
mTextView.setText(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
});
queue.add(stringRequest);
}
I'm working with retrofit and I want to know which is the generated url.
I've tried with setRequestInterceptor and setProfiler.
The last one gives me the url but not query params... so It's not the complete one.
Thanks
This works for me:
service.yourRequest(params...).enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG, call.request().url().toString()); // here
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
For those who want to know
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.BASIC)
.setEndpoint(Metadata.CURRENT_SERVER)
.setRequestInterceptor(requestInterceptor)
.build();
call.request().url(), where call is an instance of retrofit2.Call