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
Related
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());
}
}
I am trying to parse data from URL. The URL that i test in mobile browser its working fine. I am trying to parse data by AsyncHttpClient .after exection its going to onFailure method.
in dependencies add
compile 'com.loopj.android:android-async-http:1.4.9'
and I import
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import cz.msebera.android.httpclient.Header;
..
AsyncHttpClient client = new AsyncHttpClient();
client.get(url, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
pg1.dismiss();
String jsonStr = new String(responseBody, "UTF-8");
Log.e("Tag ","jsonStr "+jsonStr);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
pg1.dismiss();
Log.e("Tag ","fetch feeds fail");
}
});
The URL is in GET method
can any one please help me to resolve this issue
Just print responseBody in onFailure() method. if it is timeoutexception; then you can set client.setTimeout(30000); before client.get().
OR
check your url; if it its giving response in browser or not and also check keys and values. that may be server is not giving you any response.
I am doing same thing using inner class extends AsncyTask.
private class JSONWeatherTask extends AsyncTask<String, Void, Weather> {
#Override
protected Weather doInBackground(String... params) {
Weather weather = new Weather();
data = ((new WeatherHttpClient()).getWeatherData(params[0], params[1]));
Log.d("DATA", data);
try {
weathers = JSONWeatherParser.getWeather(data);
// Let's retrieve the icon
weather.iconData = ((new WeatherHttpClient()).getImage(weather.currentCondition.getIcon()));
} catch (JSONException e) {
e.printStackTrace();
}
return weather;
}
inside WeatherHttpClient class I get data using URL with HttpUrlConnection.
I'd like to do some work in AsyncTask including some server requests for downloading small files. When download is done continue logic inside AsyncTask and when all stuff is done I get the result in activity. Everything is working good but my AsyncTask is not waiting for callback method:
public class AsyncOperation extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String linkUrl = params[0];
functionDoStuff(linkUrl);
return "Executed";
}
public void functionDoStuff(String urlLink) {
... code ...
String str = getFile(urlLink);
!!! is not waiting for result !!!
... use 'str' ...
}
private String getFile(String urlLink) {
String savedFileDestination = null;
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder()
.url(urlLink")
.build();
client.newCall(request).enqueue(new com.squareup.okhttp.Callback() {
#Override
public void onFailure(Request request, IOException e) {
//something goes wrong
}
#Override
public void onResponse(com.squareup.okhttp.Response response) throws IOException {
//get stream
InputStream inputStream = response.body().byteStream();
//this method save file and return file path
savedFileDestination = saveFileMethod(inputStream);
}
});
return savedFileDestination;
}
}
How can I wait for this callback to continue logic in functiobDoStuff() ?
put all the stuff inside onResponse method.Because onResponse method work asyncronusly
#Selvin is right, I have to make my request synchronous and my 'waiting problem' is gone!
The only change is into getFile() method, it should be smth like:
private void getFile(String urlLink) {
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder()
.url(urlLink)
.build();
try {
Response response = client.newCall(request).execute();
if (response!=null){
InputStream inputStream = response.body().byteStream();
saveFile(inputStream);
}
} catch (IOException e) {
e.printStackTrace();
}
}
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
I'm trying to use setUseSynchronousMode on loopj to wait for results of http call before continuing in one case. I tried:
AsyncHttpResponseHandler responseHandler = new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] response) {
Log.d("TEST", "Got results");
}
};
AsyncHttpClient client = new AsyncHttpClient();
responseHandler.setUseSynchronousMode(true);
client.get("http://www.google.com", responseHandler);
Log.d("TEST", "Don't want to get here until after getting results");
But the result is:
07-11 19:48:05.631 D/TEST﹕ Don't want to get here until after getting results
07-11 19:48:05.814 D/TEST﹕ Got results
Am I misunderstanding what setUseSynchronousMode should do?
You should have used SyncHttpClient instead of AsyncHttpClient. setUseSynchronousMode doesn't have the desired effect for AsyncHttpClient.
To have synchronous version of AsyncHttpClient with an ability to cancel it, I do everything on the main thread. Previously I was running it in AsyncTask and as soon as AsyncHttpClient.post() was called, the AsyncTask would finish and I was unable to keep track the AsyncHttpClient instance.
SyncHttpClient didn't allow me to cancel the uploading so I knew I had to use AsyncHttpClient and make appropriate changes.
Following is my class to upload a file which uses AsyncHttpClient and allows cancellation:
public class AsyncUploader {
private String mTitle;
private String mPath;
private Callback mCallback;
public void AsyncUploader(String title, String filePath, MyCallback callback) {
mTitle = title;
mPath = filePath;
mCallback = callback;
}
public void startTransfer() {
mClient = new AsyncHttpClient();
RequestParams params = new RequestParams();
File file = new File(mPath);
try {
params.put("title", mTitle);
params.put("video", file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
mClient.setTimeout(50000);
mClient.post(mContext, mUrl, params, new ResponseHandlerInterface() {
#Override
public void sendResponseMessage(HttpResponse response) throws IOException {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
// TODO convert instream to JSONObject and do whatever you need to
mCallback.uploadComplete();
}
}
#Override
public void sendProgressMessage(int bytesWritten, int bytesTotal) {
mCallback.progressUpdate(bytesWritten, bytesTotal);
}
#Override
public void sendFailureMessage(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
mCallback.failedWithError(error.getMessage());
}
});
}
/**
* Cancel upload by calling this method
*/
public void cancel() {
mClient.cancelAllRequests(true);
}
}
This is how you can run it:
AsyncUploader uploader = new AsyncUploader(myTitle, myFilePath, myCallback);
uploader.startTransfer();
/* Transfer started */
/* Upon completion, myCallback.uploadComplete() will be called */
To cancel the upload, just call cancel() like:
uploader.cancel();