How does one use Basic Authentication with Volley on Android? - android

I'm looking through examples and code but I don't see anything implemented. Is this possible at this stage?

For those who don't want to use Spring for Android just for that, here's how to do it.
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s","USERNAME","PASSWORD");
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT);
params.put("Authorization", auth);
return params;
}
Note that you may have to use Base64.NO_WRAP instead of Base64.DEFAULT for this to work. As pointed in the comments.
API 8+

Yes it's possible. You need to override Request.getHeaders(). I'm lazy and I used HttpHeaders and HttpAuthentication from Spring for Android but you can just build the auth header and return it from the method. From getHeaders() you can return the auth header for basic auth. This is a sample request with basic auth.
public class GetUser extends Request<User> {
private static final String TAG = GetUser.class.getName();
private Response.Listener<User> mListener;
private ObjectMapper mMapper = new ObjectMapper();
public GetUser(Response.ErrorListener errorListener, Response.Listener<User> listener){
super(Method.GET, PoisUtils.BASE_URL + "/users", errorListener);
mListener = listener;
}
#Override
protected Response<User> parseNetworkResponse(NetworkResponse response) {
String jsonString = new String(response.data);
try {
User result = mMapper.readValue(jsonString, User.class);
return Response.success(result, getCacheEntry());
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
return null;
}
#Override
protected void deliverResponse(User response) {
mListener.onResponse(response);
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return AuthUtils.buildAuthHeaders().toSingleValueMap();
}
}
And here is how I build the auth headers
public static HttpHeaders buildAuthHeaders(){
if(UserUtils.isUserLogged()){
HttpHeaders requestHeaders = new HttpHeaders();
User user = PoisApplication.get().getUser();
HttpAuthentication auth = new HttpBasicAuthentication(
user.getUsername(), user.getPassword());
requestHeaders.setAuthorization(auth);
return requestHeaders;
}
return null;
}

For a proxy authorization (like squid) use this header :
String credentials = proxyUsername + ":" + proxyPassword;
String auth = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Proxy-Authorization", auth);

Related

How to post audio and image as multipart/formdata in native android?

I want to post Form Data like this,
where,
ApiKey, userid, albumid, music_name, singer_name are the keys whose corresponding values are all text type.
music_cover and music_file are the keys for image file and audio file as their value.
All the values are non nullable. That is, must pass all values to the
server to get a success response.
So, all in all, I have a bunch of texts and an audio and an image to upload to server using web service from android.
I am picking the image and audio using picker, so I have their file path.
Please guide me through the process of uploading audio and image using multipart from android.
It has kept me up all night and yet no reprieve.
Here I created an example using Volley
So first of all we have to build a RestApiMultiPartRequests.class so here i created it like this
private class RestApiMultiPartRequests extends Request {
private final Map<String, String> mStringParts;
private final Map<String, File> mFileParts;
private MultipartEntityBuilder mBuilder;
private final Response.Listener<T> mListener;
public RestApiMultiPartRequests(String url,
Map<String, String> stringParts,
Map<String, File> fileParts,
Response.Listener<T> listener,
Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
mListener = listener;
mStringParts = stringParts;
mFileParts = fileParts;
buildMultipartEntity();
}
private void buildMultipartEntity() {
if (mBuilder != null) {
mBuilder = null;
}
mBuilder = MultipartEntityBuilder.create();
mBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
mBuilder.setBoundary("_____" + Long.toString(System.currentTimeMillis()) + "_____");
mBuilder.setCharset(Consts.UTF_8);
if (mStringParts != null) {
for (Map.Entry<String, String> entry : mStringParts.entrySet()) {
mBuilder.addTextBody(entry.getKey(), entry.getValue(), ContentType.create("text/plain", Charset.forName("UTF-8")));
}
}
Log.e("Size", "Size: " + mFileParts.size());
for (Map.Entry<String, File> entry : mFileParts.entrySet()) {
ContentType imageContentType = ContentType.create("image/*");//MULTIPART_FORM_DATA;
Log.d("", "Key " + entry.getKey());
Log.d("", "Value " + entry.getValue());
Log.d("", "Name " + entry.getValue().getName());
//"userfile"
mBuilder.addBinaryBody(entry.getKey(), entry.getValue(), imageContentType, entry.getValue().getName());
}
}
#Override
public String getBodyContentType() {
return mBuilder.build().getContentType().getValue();
}
#Override
public byte[] getBody() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
mBuilder.build().writeTo(bos);
} catch (IOException e) {
e.printStackTrace();
}
return bos.toByteArray();
}
public HttpEntity getEntity() {
return mBuilder.build();
}
#SuppressWarnings("unchecked")
#Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return (Response<T>) Response.success(jsonString, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(T response) {
mListener.onResponse(response);
}
}
Using this class we can build a request like this
private void UploadImage() {
ServiceCall.RestApiMultiPartRequests<String> restApiMultiPartRequest =
new ServiceCall.RestApiMultiPartRequests<String>(url/*YOUR SERVICE URL*/, hashMap /* HASHMAP OF STRING */, fileparts /*HASH MAP OF FILE AND STRING */, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
/* HANDEL YOUR SUCCESS RESPONSE **/
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Handle your error types accordingly.For Timeout & No
// connection error, you can show 'retry' button.
// For AuthFailure, you can re login with user
// credentials.
// For ClientError, 400 & 401, Errors happening on
// client side when sending api request.
// In this case you can check how client is forming the
// api and debug accordingly.
// For ServerError 5xx, you can do retry or handle
// accordingly.
/** HANDLE YOUR ERRORS */
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization","YOUR AUTHANTICATION TOKEN IF REQUIRED");
return params;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
return params;
}
};
restApiMultiPartRequest.setRetryPolicy(new DefaultRetryPolicy(0, 1, 2));//10000
VOLLEY_INSTANCE.addToRequestQueue(restApiMultiPartRequest);
}
Here hashmap is HashMap<String, String> hashMap
and fileparts is HashMap<String, File> fileparts;
so the parameters with String key and String value add in to hashmap
and parameters with String key and File Value add into fileparts

Send Raw Data in android using Volley

I am trying to send an http post request with raw data .
may be its a duplicate question.. nut i've tried a lot but didn't get any exact solution..
May be there is some minor mistake that i'm not able to understand..
The raw data format is described below
{result_data: [project,circuit]}
what I'm doing:
public void MakeStrRawRequest(final String Tag, String url, final String appData, final ResponseListener responseListener) {
//String uri = String.format(Locale.US, URL);
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "String Success :" + response);
}
},
new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "String Error In Request :" + error.toString());
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
String res = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Now you can use any deserializer to make sense of data
//JSONObject obj = new JSONObject(res);
Logger.e(res);
} catch (UnsupportedEncodingException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
}
}
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
return super.parseNetworkResponse(response);
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("result_data", "[project,circuit]");
// {result_data: [project,circuit]}
return hashMap;
}
#Override
public byte[] getBody() throws AuthFailureError {
return appData.getBytes();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
String AuthToken = "auto_token_value";
headers.put(ApiConstant.TOKEN_KEY, AuthToken);
return headers;
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(15000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
ApplicationData.getInstance().getRequestQueue().add(stringRequest);
}
Here is the response that i'm getting..
BasicNetwork.performRequest: Unexpected response code 400
I've tried both method to send data
1.in getParam() and
2. in getBody()
1. #Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("result_data", "[project,circuit]");
// {result_data: [project,circuit]}
return hashMap;
}
2.
#Override
public byte[] getBody() throws AuthFailureError {
return appData.getBytes();
}
getBody and getParams both are use to send parameters .So, You should call only one method at a time .If you want to send an arbitary string then use getBody() method and on the otherside if you want to send normal parameters then you should use getBody() method.For more detail you may see here

400 Error when calling Sinch REST API

I am using Sinch to create an app in android and some of the functionalities that I need can only be implemented by calling their REST API. I want to mute a particular user, for that I have written the code like this
String userName = call.getCallId();
final String muteURL = URL+CallingUsersName+"/"+userName;
final String muteParticipant = "{ \"command\" : \"mute\" }";
JSONObject muteJSON;
try{
muteJSON = new JSONObject(muteParticipant);
Toast.makeText(getActivity(),muteJSON.toString(),Toast.LENGTH_SHORT).show();
}catch (JSONException e ) {
muteJSON = null;
Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_SHORT).show();
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PATCH, muteURL, muteJSON, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
mConferenceParticipants.setText(response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
mConferenceParticipants.setText(error.toString());
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s",AppKey,AppSecretKey);
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
params.put("Authorization", auth);
params.put("Content-Type", "application/json");
// params.put("X-HTTP-Method-Override", "PATCH");
return params;
// return super.getHeaders();
}
};
// jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(8000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rq.add(jsonObjectRequest);
When I call this request the meeting is actually going on but I am getting this error
BasicNetwork.performRequest: Unexpected response code 400 for https://callingapi.sinch.com/v1/conferences/id/Meeting/a291ba94-e430-454f-80a9-73013cd43451
I believe that 400 means Conference not found but the conference is established and in the same activity I am also calling the REST API that will tell me the no. of participants in the meeting and that is working correctly.
Any idea what is wrong in this?
I tried to solve this problem for a long time and finally got it working. Here is the code:
public void MuteTheParticipants(){
String userName = call.getCallId();
final String muteURL = URL+CallingUsersName+"/"+userName;
StringRequest sr = new StringRequest(Request.Method.PATCH, muteURL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if(flag)
muteButton.setBackgroundResource(R.drawable.microphone);
else
muteButton.setBackgroundResource(R.drawable.microphone_off
);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getActivity(),error.toString(),Toast.LENGTH_SHORT).show();
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
String creds = String.format("%s:%s",AppKey,AppSecretKey);
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
params.put("Authorization", auth);
return params;
// return super.getHeaders();
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
if(!flag) {
params.put("command", "mute");
flag = true;
}else {
params.put("command", "unmute");
flag = false;
}
return params;
}
};
sr.setRetryPolicy(new DefaultRetryPolicy(8000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rq.add(sr);
}
your variable says username, it should be callid you mute not username

Android : Sending form-data as body Google Volley

In my Android application, I am using google's volley for network operations. There is a case where I need to make a request but send body as form-data.
I have tried everything else, but I am not able to make the request as form-data.
Here is a curl
curl -X POST -H "Content-Type: multipart/form-data" -F "mobile_number=<XXXX>" "<server_url>"
How can I achieve that -F part in volley? The Server is throwing bad request.
This is what I have done :
final JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST, URLFactory.OTP_URL,
null, listener, errorListener){
#Override
public byte[] getBody() {
final JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("mobile_number", mobileNumber);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
return jsonObject.toString().getBytes();
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
final HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "multipart/form-data");
return headers;
}
};
Please help me in this.
This can be done in volley by creating the postBody yourself. Please refer the below code.
Code for creating the body:
private String createPostBody(Map<String, String> params) {
StringBuilder sbPost = new StringBuilder();
for (String key : params.keySet()) {
if (params.get(key) != null) {
sbPost.append("\r\n" + "--" + BOUNDARY + "\r\n");
sbPost.append("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n\r\n");
sbPost.append(params.get(key));
}
}
return sbPost.toString();
}
Modifed getBody() code :
#Override
public byte[] getBody() {
Map<String,String> params = new HashMap<>();
params.add("mobile_number", mobileNumber);
String postBody = createPostBody(params);
return postBody.getBytes();
}
You will need to modify getHeaders as well to tell the server what you boundary is :
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
final HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY;);
return headers;
}

Getting Twitter auth token with Volley POST request

I'm trying to produce a proper request for Twitter Application-only authorization token using a Volley POST request, but I keep getting a Http 400 response (Bad Request).
This is what I tried :
URL
private static final String TWITTER_API_AUTH_URL = "https://api.twitter.com/oauth2/token";
Encoding the consumer key and the consumer secret
try {
byte[] data = (URLEncoder.encode(TWITTER_CONSUMER_KEY, "UTF-8") + ":" + URLEncoder.encode(TWITTER_CONSUMER_SECRET, "UTF-8")).getBytes("UTF-8");
mEncodedKeyAndSecret = Base64.encodeToString(data, Base64.DEFAULT);
} catch (UnsupportedEncodingException e) {
//handleError
}
Custom Volley StringRequest
private class TokenRequestWithAuthHeader extends StringRequest{
public TokenRequestWithAuthHeader (int method, String url, Response.Listener listener, Response.ErrorListener errorListener)
{
super(method, url, listener, errorListener);
}
#Override
public Map getHeaders() throws AuthFailureError {
Map headers = new HashMap();
headers.put("Content-Length", String.valueOf(getBody().length));
headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
headers.put("Authorization", "Basic " + mEncodedKeyAndSecret);
return headers;
}
#Override
public byte[] getBody() {
return ("grant_type=client_credentials").getBytes();
}
}
Sending Request
tokenRequest = new TokenRequestWithAuthHeader
(Request.Method.POST, TWITTER_API_AUTH_URL, mCallback.getTokenResponseListener(), mCallback);
requestQueue.add(tokenRequest);
Documentation about Application-Only authentication at dev.twitter.com
I also tried extending JsonObjectRequest and JsonRequest instead of StringRequest, same result.
Can someone help identify what is the problem with the request ?
I have just tested with the credential you've provided in comments. It's working with the following logcat output (I truncated real access token's content)
I/onResponse: {"access_token":"AAAAAAAAAAAAAAAAAAAAAIwbjgAAAAAAGVMKCDU9taD0ke3sStAyA2WKszs%3DA4nfnpLTF31YuE.............JFtKjrTQC1K","token_type":"bearer"}
My code:
final RequestQueue queue = Volley.newRequestQueue(this);
final String url = "https://api.twitter.com/oauth2/token";
final String requestBody = "grant_type=client_credentials";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url, requestBody, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("onResponse", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("onErrorResponse", error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// Basic Authentication
//String auth = "Basic " + Base64.encodeToString(CONSUMER_KEY_AND_SECRET.getBytes(), Base64.NO_WRAP);
String auth = "Basic cjMzZXVWeG5ZSDN3NjJ1RUdhV1NtcDAzYzpDa0h5Q3N1ZXF5ZXVobTExWURnTmpKMUZWRFN6OEk5TDFXWXJVUTFQWTNPZTcxcWlGdQ==";
headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
headers.put("Authorization", auth);
return headers;
}
};
queue.add(jsonObjectRequest);
private void fetchAccessTokens() {
final String requestBody = "grant_type=client_credentials";
JsonObjectRequest req1 = new JsonObjectRequest(Request.Method.POST,
TwitterTokenURL,
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("Response: ", response.toString());
fetchTweets(response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
// URL encode the consumer key and secret
String urlApiKey = null;
String urlApiSecret = null;
try {
urlApiKey = URLEncoder.encode(CONSUMER_KEY, "UTF-8");
urlApiSecret = URLEncoder.encode(CONSUMER_SECRET, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Concatenate the encoded consumer key, a colon character, and the
// encoded consumer secret
String credentials = urlApiKey + ":" + urlApiSecret;
String auth = "Basic "
+ Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
headers.put("Authorization", auth);
return headers;
}
#Override
public byte[] getBody() {
return requestBody.getBytes();
}
};
AppController.getInstance().addToRequestQueue(req1, tag_json_arry);
}

Categories

Resources