I am trying to call a RESTful API in my Android app using Volley. The API requires that for each request you pass in a special header (X-AUTH-TOKEN).
I found that I could do this for GET requests by overriding the getHeaders method from the Request class.
However when I try to do this with a POST request, I find that the header is not appended / received by the server.
This is the class I am using to create the request
public class AuthenticatedStringRequest extends StringRequest {
public AuthenticatedStringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) {
super(method, url, listener, errorListener);
}
#Override
public Map<String, String> getHeaders() {
Map<String, String> headers = new HashMap<>();
headers.put("X-AUTH-TOKEN", Constants.AUTH_TOKEN);
return headers;
}
}
Is there a different method of adding special headers with POST requests on Volley?
Related
//Code
private void searchQuery(String strQuery, String link){
Toast.makeText(getContext(), "You searched for "+strQuery, Toast.LENGTH_SHORT).show();
JsonArrayRequest request = new JsonArrayRequest(Request.Method.POST, link, new Response.Listener<JSONArray>(){
#Override
public void onResponse(JSONArray jresponse) {
//displayResultInList(jresponse);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("query", strQuery);
return parameters;
}
};
RequestQueue rQueue = Volley.newRequestQueue(getActivity());
rQueue.add(request);
}
This particular line: parameters.put("query", strQuery); is giving an error and the error message says:
Variable 'strQuery' is accessed from within inner class, needs to be declared final.
I did some research and read some tutorials on POST requests using Volley and the large chunk of them are not using variables but strings in that function.The problem with setting the variable as final is that the user is typing it in therefore that variable will only have a value after the query is submitted.
It's because you're using the parameter variable in a block of code inside the method.
The JAVA compiler demands that the variables from outside the scope of the Response.Listener block are declared as final to guarantee that the variable value keeps the same (when the block is declared) when running the code.
It assures that you cannot modify the value of the variable after declaring the block.
So, you DO NEED to put final before String strQuery in the function parameter, since you're using it inside the block.
I am using retrofit 2.0.2 for HTTP calls in which I have to send token in header for each API except login and signup. For this I have added this token into interceptors and contains information about the client but before login token is automatically added into interceptors. Is there any way to exclude token from interceptors for login and signup call
Check this link out, it contains a nice and clean way to handle this.
https://medium.com/kufar-tech/retrofit-tips-passing-custom-parameters-from-retrofits-request-to-okhttp-s-interceptor-989b8ceff07d
Briefly, you should create a custom annotation (for example named PublicAPI)
#Documented
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface PublicAPI { }
and add it to all services that won’t need authentication.
public interface LoginService {
#PublicAPI
#POST(value = "login")
#FormUrlEncoded
Call<Void> login(#Header("Authorization") final String credentials);
}
Retrofit’s RequestFactory creates an instance of Invocation object with service’s method and argumentList as parameters and sets it as Request tag. Therefore you can check whether your service annotated with PublicAPI or not within the interceptor and do wat you want based on it.
#Override
public #NonNull Response intercept(#NonNull final Chain chain) throws IOException {
Request request = chain.request();
Invocation invocation = request.tag(Invocation.class);
Annotation publicAPI = invocation.method().getAnnotation(PublicAPI.class);
if (publicAPI == null) {
//add access token
}
// rest
return response;
}
You can check the request path in the interceptor and do some stuff based on the request URL.
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if(originalRequest.url().encodedPath().equals("/some/login/path")){
// don't add token header
}else{
// add token header
}
}
or you may use the method provided at https://stackoverflow.com/a/41033670/1273657
I have some custom POJO:
class CustomClass {
int x;
String str;
SecondCustomClass obj; //indicate it's not class of simple types
//etc...
}
I want to send instance of him from Android (Volley library) client to web service running on Spring-boot java application. Currently I know how to send data with URL params and return to client custom object. But I want also to send custom object.
Code in Android (I know that I need to use 3'rd parameter which is now null but I'm struggling get it work):
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,
"BASE_URL?param1=param",
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
CustomClass result = new Gson().fromJson(response.toString(), CustomClass.class);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
);
volleyQueue.add(request);
Code in server:
EDIT: The solution to receive pojo is using #RequestBody
#RequestMapping("/webmethod")
public CustomClass webmethod(#RequestParam(value="obj_param") #RequestBody CustomClass obj) {
//work with obj
}
What do I need to put in Android side to get it work?
You have to use the JSON object inside the JSON object.Below is the sample. When you are request the Parameter with only one request.
This the Request JSON
{
"x":10,
"str":"MyName",
"SecondCustomClass":{
"id":10,
"title":"make it eassy"
}
}
This is the post parameter request from Android. Try this way.
For more details please use this link
I'm going to develop a small-sized system to raise my developing skills.
It consists of the three parts listed below:
1. Web DB
2. Web Page
3. Android App
The main feature is managing the members. (login, just showing the user information)
At this point, I'm wondering about the android app part.
Especially, the HTTP.
I found two libraries which are JSoup and Retrofit.
As far as I can tell, those libraries are a little bit different.
I think the retrofit is a better fit for me...
Up until now I couldn't find a good sample...
Can you give me a hint how to do this?
If you are trying to connect to a Web Database I would suggest using Volley which is really simple and straightforward and really powerful yet: https://developer.android.com/training/volley/index.html.
Here's an example on how you could set your query with volley from the android developer site:
final TextView mTextView = (TextView) findViewById(R.id.text);
...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
Retrofit example
Synchronous
Interface
public interface RestApi {
#POST("/Login")
String login(#Body User user);
}
Simple class which follows the singleton design pattern
public class RestClient {
private static RestApi API_INSTANCE;
private static final String ENDPOINT = "http://192.168.6.99:50500/Phone";
static {
setUpHttpClient();
}
private static void setUpHttpClient() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(ENDPOINT)
.setLogLevel(BuildConfig.DEBUG ?
RestAdapter.LogLevel.FULL :
RestAdapter.LogLevel.NONE)
.build();
API_INSTANCE = restAdapter.create(RestApi.class);
}
private RestClient() {}
public static RestApi getApiInstance() {
return API_INSTANCE;
}
}
Call it for example in an IntentService
String userToken = "";
try {
// post to http://192.168.6.99:50500/Phone/Login
userToken = RestClient.getApiInstance().login(new User(login, password));
} catch (RetrofitError error) {
//...
}
build.gradle
compile 'com.squareup.retrofit:retrofit:1.9.0'
Or Asynchronous
interface
public interface RestApi {
#POST("/Login")
void login(#Body User user, Callback<String> token);
}
and do the request with a callback..
I am required to pass cookie value in my next service after log in I am using volley library to call services. I have successfully saved cookie using this it successfully saves ids in preference.
i have use getHeader for next request
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return myApp.getSessionCookie();
}
but for my next request how to use this value?