I am currently creating my first Android app with Java. I make two API calls to a Loxone Music Server (based on "/audio/X/volume/-Y" -> https://www.loxone.com/dede/kb/loxone-music-server/) to change the volume of the room. The calls are simple GET requests to different URLs. The call is made using two different buttons. Once on the URL "http://xx.xx.xx.xx:7091/audio/9/volume/+5" to increase the volume by 5% and with the URL "http://xx.xx.xx.xx:7091/audio/9/volume/-5" to decrease the volume by 5%. Both calls are executed cleanly. My problem is, depending on which button I click first, that executes the request. When I click the other button, the same request is received on the music server. That is, if I increase the volume first, when I click on the decrease volume button, the request is sent from the increase to the music server, even though the log output shows the correct URL.
Currently, I am stuck because I don't know what I am doing wrong. In the log, I see that different request URL are called. However, somehow via a cache mechanism or proxy, always the same request arrive at the music server. If I execute the two calls in the Postman, they work fine.
For the implementation, I have already tried different variants. However, with the same result. I have the same behavior with StringRequest in combination with and without queue (volley), or also with a simple variant with HttpURLConnection.
StringRequest
public void get(String url, String username, String pwd) {
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (null != response) {
Log.d(TAG, "GET");
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "ERROR");
}
}){
#Override
public Map<String, String> getHeaders() {
Map<String, String> params = new HashMap<String, String>();
params.put(
"Authorization",
String.format("Basic %s", Base64.encodeToString(
String.format("%s:%s", username, pwd).getBytes(), Base64.DEFAULT)));
return params;
}
};
queue.add( request );
}
Simple Variant
public void sendSimpleGET( String uri) {
try{
URL obj = new URL(uri);
HttpURLConnection con = (HttpURLConnection) obj.openConnection(Proxy.NO_PROXY);
con.setRequestMethod("GET");
con.setRequestProperty("User-Agent", "LoxoneSuiteApp");
int responseCode = con.getResponseCode();
System.out.println("GET Response Code :: " + responseCode);
// success
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(
con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// print result
System.out.println(response.toString());
} else {
System.out.println("GET request not worked");
}
} catch (IOException e) {
e.printStackTrace();
toastMessage("Error: " + e.getMessage());
}
}
Related
I had 2 pages: first one is login page and second is category page. In login API after entering the credentials, I am getting the response as sesssion id from response header.
The sesssion id will be saved and it will use for further API calls. I am trying to call second API (category page). In this page, as an input am passing the saved session id in the request header. Getting response as "session expired". Also tried to pass Set-Cookie: PHPSESSID=d9f9sdkfjs9 in the request header. but it didn't work.
Note :
I am experiencing this issue in production environment only (SSL included)
I am using volley library for handling APIs.
public void fnCallLoginAPI() {
try {
//DEMO URL
//final String URL="http://demo.io/api/api.php?m=login";
//LIVE URL
final String URL = "https://www.live.com/shop/api/api.php?m=login";
final String requestBody = "email=abc.b#xyz.com" + "&password=43443==" + "&strPlatform=i" + "&strDeviceToken=null";
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String strResponse = response;
System.out.println("THE RESPONSE IS in PROFILE IS" + response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Cookie", "PHPSESSID=" + sessionID);
return headers;
}
#Override
public byte[] getBody() throws AuthFailureError {
byte[] body = new byte[0];
try {
System.out.println("THE REQIEST BODY IS" + requestBody);
body = requestBody.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e("TAG", "Unable to gets bytes from JSON", e.fillInStackTrace());
}
return body;
}
};
AppApplication.getInstance().addToRequestQueue(stringRequest, "assignment");
} catch (Exception e) {
}
}
public void fnCallCateGoryAPI(){
try { final String URL ="https://www.live.com/shop/api/api.php?m=getcategories";
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
String strResponse = response;
System.out.println("THE RESPONSE IS in PROFILE IS" + response);
JSONObject jsonObj = null;
try {
jsonObj = new JSONObject(strResponse);
sessionID = jsonObj.optString("session_id");
System.out.print("sessionID" + sessionID);
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
})
{
};
AppApplication.getInstance().addToRequestQueue(stringRequest, "assignment");
} catch (Exception e) {}
}}
#fazil try after increasing the token expiration time from the backend
#fazil : I was facing something similar in my projects too and the reason i understood was actually due to multiple header values set under same key "Set-Cookie".
Please do check this in your logs.
Also, make sure that you have set the headers properly in your request(check the logs of request and response from your Server).
If everything implemented is correct and the issue is due to multiple values in the same header you need to check this implementation of volley : https://github.com/georgiecasey/android-volley-duplicateheadersfix
I am using basic authentic for http connection in app. App is working finr correctly on devices with higher versions. I have also searched for solution and It did not worked for me.
Here is my code for connection
public static String executeHttpPost(Activity activity, String url,
ArrayList<NameValuePair> postParameters) {
String value = "{\"status\":false,\"message\":\"Server Timeout, connection problem, Please try later\"}";
try {
final String basicAuth = "Basic " + Base64.encodeToString(
("abc" + ":" + "abcd").getBytes(), Base64.NO_WRAP);
networkConnection = new NetworkConnection();
if (networkConnection.isOnline(activity)) {
postParameters.add(new BasicNameValuePair("device_type","android"));
HttpClient client = getNewHttpClient();
HttpPost post = new HttpPost(url);
try {
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postParameters, "UTF-8");
post.setEntity(entity);
post.setHeader("Authorization",basicAuth);
post.setHeader("some-parameter","abc");
org.apache.http.HttpResponse result = client.execute(post);
value = EntityUtils.toString(result.getEntity());
}catch (Exception e){}
String s = "";
for (NameValuePair param : postParameters) {
s = s + param.getName() + " = " + param.getValue() + " ";
}
if (value != null) {
WebUrl.ShowLog("From " + url +" parameters "+s
+ " Response : " + value.trim());
return value.trim();
} else {
return value;
}
} else {
activity.startActivity(new Intent(activity, NoInternet.class));
activity.finish();
return "{\"status\":false,\"message\":\"\"}";
}
} catch (Exception e) {
e.printStackTrace();
return value;
}
}
This is the only link I found, but it didn't work for me
You should use Google Volley for the connections with the server. There are many ways to get connect, but using "Google Volley" in Android development is so simple, reliable and as it comes as a dependency it gets bundled with your package. So never worry about compatibility over many old and many current and upcoming Android versions.
I have used it 5 years ago and it was working on all major platforms. Very easy to program.
Have a look:
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);
How simple is it.
SOLVED:
I have gone ahead and used the recomendation of Retrofit library and it has reduced my code allot. Thank you for the help.
I have an android application, on the page I have code displayed below when someone clicks on a switch it will use PUT to send the data as a JSON to the server. However im not sure how I can reduce this code in a way that I can use it again. I dont want to have to keep copy and pasting the same code and changing the requestMethod or the type of bytes im writing.
This is the code in my oncreate, when the switch is turned on it will do what is in Figure B. I want to make it DELETE when the switch is off without having to copy the same code from figure B and changing it and then executing it.:
test.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean on = ((Switch) v).isChecked();
if(on)
{
//Do something when switch is on/checked
new RetrieveFeedTask().execute();
new newtask().execute();
}
else
{
//Do something when switch is off/unchecked
}
}
});
Figure B
class RetrieveFeedTask extends AsyncTask<String, String, String> {
private Exception exception;
protected String doInBackground(String... urls) {
URL url = null;
try {
String strUrl = "http://192.168.0.104:5053/TEST";
url = new URL(strUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset");
connection.setDoInput(true);
connection.setDoOutput(true);
OutputStream stream = connection.getOutputStream();
DataOutputStream writer = new DataOutputStream(stream);
connection.connect();
//Log.d("WARN", "TEST");
// The LogCat prints out data like:
// ID:test,Email:test#gmail.com,Pwd:test
String suuid = UUID.randomUUID().toString();
writer.writeBytes("{\"id\" : \""+suuid+ "\", \"sensorType\" : \"sound\", \"threshold\" : \"50\", \"operator\" : \">\", \"actuator\" : \"1\", \"actuatorAction\" : \"4\"}");
writer.flush();
writer.close();
InputStream response = connection.getInputStream();
StringBuilder sb = new StringBuilder();
BufferedReader bf = new BufferedReader(new InputStreamReader(response, "utf-8"));
String responseLine = bf.readLine();
while(responseLine != null) {
sb.append(responseLine);
responseLine = bf.readLine();
}
stream.close();
System.out.println("executed");
connection.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
return "fff";
}
protected String onPostExecute() {
// TODO: check this.exception
// TODO: do something with the feed
return "ASDASD";
}
}
If any more information is needed on making this clearer please let me know.
Use Android Asynchronous Http Client
Sample Code:
AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("key", "value");
params.put("more", "data");
client.post("https://www.google.com", params, new AsyncHttpResponseHandler() {
#Override
public void onStart() {
// called before request is started
}
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
// called when response HTTP status is "200 OK"
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
}
#Override
public void onRetry(int retryNo) {
// called when request is retried
}
});
Gradle:
dependencies {
compile 'com.loopj.android:android-async-http:1.4.9'
}
Android-Volley(deprecated):
https://github.com/mcxiaoke/android-volley
or
Retrofit:
Type-safe HTTP client
Retrofit is definitely the better alternative to volley in terms of ease of use, performance,Catching, extensibility, Multipart uploads and other things. It is a type-safe REST client
(http://square.github.io/retrofit)
You can use a very lightweight Ion library for this. Usage examples are on Github: https://github.com/koush/ion
First of all, i would recommend using a networking library (Retrofit, Volly, etc...) since dealing with the http connection directly is a bit more complicated and prone to errors which the libraries have probably addressed already.
But if you still wish to use an http connection directly, You could just make an httpConnection Task that extends async task and gets the necessary params on creation.
for example -
public class HttpConnection extends AsyncTask<String, String, String> {
private final String mBytes;
private final String mMethod;
public HttpConnection(String method, String bytes) {
mMethod = method;
mBytes = bytes;
}
#Override
protected String doInBackground(String... strings) {
// ... open connection
writer.writeBytes(mBytes);
return null;
}
Obviously, you can change this up to use whatever params you want/need
I'm using Volley to download text files from a website.
This is the content of a sample text file:
NEON Wönn 30€ Kostüm größter Spaß
TESTTESTTESTTEST★★★★TESTTEST:::TEST
I put that in Notepad and selected 'Encoding UTF-8' in the SaveFileDialog.
In Filezilla in the server manager I selected 'Force UTF-8' before I uploaded the file.
When I download it with Volley the response will look like this:
NEON Wönn 30⬠Kostüm gröÃter SpaÃ
TESTTESTTESTTESTââââTESTTEST:::TEST
Here is my method:
public static void getRequest(String url) {
RequestQueue queue = Volley.newRequestQueue(activity);
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//response is gibberish :/
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VolleyError", error.toString());
}
});
stringRequest.setShouldCache(false);
// Add the request to the RequestQueue.
queue.add(stringRequest);
}
Is there a way to fix that by forcing Volley to use UTF-8 Encoding?
I had to Override this method:
#Override
protected Response<String> parseNetworkResponse(
NetworkResponse response) {
String strUTF8 = null;
try {
strUTF8 = new String(response.data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Response.success(strUTF8,
HttpHeaderParser.parseCacheHeaders(response));
}
I'm working with a server (that I do not control) that sends back UTF-8 responses without setting charset in the content-type header. Volley currently defaults to ISO-8859-1 in this case.
I simply wanted to change the default charset without forcing every response to UTF-8. I ended up just using parseNetworkResponse() to intercept Volley's response processing and check to see if charset is missing from the response headers. If it is missing, I force it to look like the server said "charset=UTF-8" and then just let the normal processing continue.
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
// Volley's default charset is "ISO-8859-1". If no charset is specified, we want to default to UTF-8.
String charset = HttpHeaderParser.parseCharset(response.headers, null);
if (null == charset) {
String contentType = response.headers.get("Content-Type");
contentType = (null != contentType) ? (contentType + ";charset=UTF-8") : "charset=UTF-8";
response.headers.put("Content-Type", contentType);
}
return super.parseNetworkResponse(response);
}
I am trying to fire a DELETE request using HttpUrlConnection in android,I am setting the setRequestmethod as DELETE and getting a 200 as response code. The Item is not getting deleted. The async I am using is below.
private class DeleteTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String result = null;
URL url = null;
try {
url = new URL(urls[0]);
Log.i("URL to access :", urls[0]);
} catch (MalformedURLException exception) {
exception.printStackTrace();
}
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("DELETE");
httpURLConnection.setRequestProperty("charset", "utf-8");
httpURLConnection.setUseCaches(false);
System.out.println("ResponseCode: "+httpURLConnection.getResponseCode());
if(httpURLConnection.getResponseCode() == 204){
Log.d(TAG,"Deleted");
}
} catch (IOException exception) {
exception.printStackTrace();
} finally {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
return null;
}
}
}
It looks like the setRequestMethod() is not working and its taking the Request as a GET and giving me a 200 !!
I tested this in postman(a chrome extension) and it was working fine , If it was a backend issue then from postman also it should fail.
okHttp:
I was trying to make this work on okHttp also for that
Request request = new Request.Builder().url(url.toString()).patch(body).build();
How will I make up this for delete, because delete request dosent have a body
Volly:
I've tried out the google volly library too..
RequestQueue requestQueue = Volley.newRequestQueue(TimerSummary.this);
StringRequest request = new StringRequest(Request.Method.DELETE, uri, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG,"Response: "+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG,"Error: "+error);
}
});
requestQueue.add(request);
This also returns like GET request, I am getting the item as json which was supposed to be deleted.
any suggestions are appreciated.
Thanks in advance..
It was actually a typo!!! I am an idiot!Both of my methods work fine ,but I am Now using Google's volly library for network related things.
I was missing a "/" before the "?" before appending parameters with the URL