Hi I am working on an android app which relies on being able to fetch images among other data from our server, i.e., the image is contained in a tag as part of the response. The communication with the server is based on WCF and SOAP.
Up until the point where we need to fetch images it has worked fine. But when we need to fetch an image from the server the app takes a substantial amount of time and consumes a lot of memory when parsing the response from the server containing the image. The images we are working with are typically of the size of 1500 x 1000 pixels. The image itself is transmitted as a base64 encoded byte array.
Currently we are parsing the response using a DOM xml parser, which I know to be prone to huge memory consumption but insofar has not given any problems(aside from parsing images). Furthermore some minor tests using XMLPull, which seems to be the recommended XML parser on the android platform, has resolved in pretty much the same issue, huge memory and time consumption.
I suspect that the issue stems from the image being converted to a string or byte array both of which should consume quite a bit of memory considering the size of the image.
Bellow is an example of the code we currently are using to parse the response:
public static Document parseResponse(InputStream response)
{
Document parsedResponse = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
parsedResponse = builder.parse(response);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return parsedResponse;
}
And the response is fetched using an Async-Task using the following code:
protected Document doInBackground(ServerRequest... requests) {
ServerRequest request = requests[0];
HttpPost postRequest = request.postMethod;
HttpParams httpParams = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParams, 10000);
HttpConnectionParams.setSoTimeout(httpParams, 10000);
DefaultHttpClient client = new DefaultHttpClient(httpParams);
HttpResponse response = null;
try {
response = client.execute(postRequest);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Document parsedResponse = null;
try {
InputStream stream = response.getEntity().getContent();
parsedResponse = ServerRequest.parseResponse(stream);
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return parsedResponse;
}
Currently it is not possible to fetch the image itself using a URL, i.e., it comes as part of the XML from the server, otherwise something like Android Hive - Custom ListView with Image and Text would probably be the way to go.
Before delving into something like kSOAP2 I would like to find out if there was a simple fix to the above approach or if I've missed something simple.
I have searched lot of on internet for your alternate solution. But it seems that memory constraints is always in middle of the way for phone.
Really 1500 * 1000 px image is too huge for android mobile to eat. I was also faced the same problem in one of my projects.
Only way is you can parse that string on server side, store it temporarily and pass the image path in response. This is the best approach i am feeling right now. I am still searching for solution. If found, i will let you know.
Your above approach will slow down the mobile and also kill the useful apps services running in background. :(
Related
I have an android app that loads images and text files into Dropbox. I've figured out the authentication and upload process.
Now, using the same authenticated session, I want to read one of the uploaded text files (to look for changes). I've found a download example, but that would mean writing it to local SD, then reading for there ... not efficient at all (in part because of the additional android permission required).
I've examined Dropbox's v2 documentation and there do seem to be a bunch of read calls but I can't, for the life of me, figure out how to use them. The helpful Android-Dropbox examples also don't seem to tackle my specific problem. I couldn't find any v2 examples on stackoverflow either.
Surely, somebody can point me to a simple example that provides a nice InputStream.
You can use the Dropbox Java SDK download method to get file contents directly. There's an example of using that in the example app here. That example writes directly to a FileOutputStream.
It sounds like you just want an InputStream though, which would look like this:
DbxClientV2 client = new DbxClientV2(config, ACCESS_TOKEN);
String remotePath = "/test.txt"; // the path to the file you want to download
InputStream fileInputStream = null;
try {
fileInputStream = client.files().download(remotePath).getInputStream();
// use `fileInputStream` as desired
} catch (DbxException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
After much tooling around, here's something that works
String my_link = null;
URL my_url = null;
URLConnection conn = null;
BufferedReader reader = null;
try {
my_link = my_DbxClient.files().getTemporaryLink("/" + my_File).getLink();
my_url = new URL (my_link);
conn = my_url.openConnection();
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} catch (DbxException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I'm currently sending an image to my server by encoding it into a base64 string like this: https://gist.github.com/fabdarice/a4006a97171cc415892e
However, when I'm looking at the HTTP POST request, I'm seeing something like this :
{"login"=>"Jerem", "mobile_upload_file"=>"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\nAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB\nAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAQ4BDgDASIA\nAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA\nAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3\nODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm\np6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA\nAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3....................................}
This goes on for a while, (around 1 millions characters) and it seems to make my server laggy.
I was wondering if this is a normal behavior to see that amount of characters sent? If not, how am I supposed to implement the process of sending an image to a server?
Thanks for your help
You can send image in FileBody by Multipart entity like this...
public String sendMultipartRequestToServer(BusinessDataObject dataObject,String url) {
String responseString=null;
HttpResponse response;
HttpClient client=new DefaultHttpClient();
HttpPost post=new HttpPost(url);
HttpConnectionParams.setConnectionTimeout(client.getParams(),50000);
MultipartEntity multipartEntity=new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
try {
multipartEntity.addPart(KEY_EMAIL,new StringBody(dataObject.getEmail()));
multipartEntity.addPart(KEY_PASSWORD, new StringBody(dataObject.getPassword()));
multipartEntity.addPart(KEY_IMAGE,new FileBody(new File(Here your image path on your memory)));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//Setting parameter to post method
post.setEntity(multipartEntity);
try {
response=client.execute(post);
InputStream inputStream=response.getEntity().getContent();
responseString=convertStreamToString(inputStream);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return responseString;
}
If you will not find the class MultipartEntity .Then you have to add HttpMime.jar in your project .It is the best way to send images so far i know here no need to convert image in Base64.You can just pass the url of selected image to FileBody.
I have 3 tabs in my app, each having its own Fragment. I need to populate each tab's Fragment with data that needs to be retrieved from my website's REST API.
To my understanding, the onCreate/onCreateView method in the Fragment class is where I should request the JSON data (how do I request it?).
Then I would loop through the data and insert it into separate lists or cards (how do I do this?).
Sorry for the beginner questions, but I'm not sure where to begin.
There are two ways to do this
1) through native android
private void makeGetRequest() {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://www.example.com");
// replace with your url
HttpResponse response;
try {
response = client.execute(request);
Log.d("Response of GET request", response.toString());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) use third party libraries.Please refer this url https://github.com/square/retrofit
Example
https://github.com/square/retrofit/blob/master/samples/src/main/java/com/example/retrofit/SimpleService.java
This library will do all the things like GET,POST,Sync,Async and Error Handling.
you have to use AsyncTask When youre requesting anything from server, Asynctask runs in backgrouns so your UI thread will no be blocked by it.
Otherwise you can try using Volly library dosen't need an AsyncTask to work. It will work in background thread anyway '
It also provides you with sucess failure handlers(if youre into ajax and all it'll easier for you)
take a look at Volly Library
I am creating a networking website's Application in android.I want to know how can I perform syncing ie I want to store all user contacts on websites to my android phone.
user's details will come in XML format.
Please Guide me ..
For that you have to make a web service call either by using HttpClient or by using other third-party libraries like kSoap2. But i would prefer native class instead of third-party library.
Here is a best example: http://lukencode.com/2010/04/27/calling-web-services-in-android-using-httpclient/
After making a call, you will receive a XML, after that you can parse the received XML response either by using SAX parser, Pull Parser or DOM Parser.
This is the scenario to fetch data from web to your local database.
For your info: To get response from Web:
public static InputStream getInputStreamFromWeb(String url) {
InputStream content = null;
try {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(new HttpGet(url));
content = response.getEntity().getContent();
} catch (Exception e) {
Log.("GET", "Network exception", e);
}
return content;
}
I am making an app for Android. I like to make the rest calls as quick as possible. When I get my results as XML it takes 5 seconds (!) to get a simple xml like this:
<souvenirs>
<souvenir>
<id>1</id>
<name>Example 1</name>
<rating>3.4</rating>
<photourl>/images/example.jpg</photourl>
<price>3.50</price>
</souvenir>
<souvenir>
<id>2</id>
<name>Example 2</name>
<rating>2.4</rating>
<photourl>/images/example.jpg</photourl>
<price>8.50</price>
</souvenir>
</souvenirs>
So I tried it with JSON. But that takes also about 5 seconds to retrieve.
I load the XML in android with the following code:
URL url = new URL("http://example.nu?method=getAllSouvenirs");
URLConnection conn = url.openConnection();
long t=System.currentTimeMillis();
InputStream ins = conn.getInputStream();
Log.d("info", String.valueOf((System.currentTimeMillis()-t)));
The log says it takes about 5000 ms to get the inputstream.. Is there any way to speed this up? does anybody knows which technique the Android Market uses? This loads way faster than my app..
Thanks in advance! :)
When you try to get the data "manually" - via browser or via other means (wget, curl) how long does it take there.
On Android you also should take the mobile network into consideration that is usually significantly slower than for a desktop computer. Also latencies are bigger.
To me this sounds a lot like issues in the backend (e.g. trying to resolve the IP of the client and thus taking lots of time).
use Apache HttpClient instead of URLConnection:
Apache http client or URLConnection
EDIT(2012-02-07): no longer true on newer android platform please read: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
Maybe that is how it is implemented and you can't do nothing. That is my guess.
My opinion is to do all connection based stuff on your own thread (to put in in background) and in foreground (main UI thread) entertain user. :)
I have played a little bit around this and it works fast enough for me... Here is my code:
private static HttpResponse doPost(String url, JSONStringer json) {
try {
HttpPost request = new HttpPost(url);
StringEntity entity;
entity = new StringEntity(json.toString());
entity.setContentType("application/json;charset=UTF-8");
entity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json;charset=UTF-8"));
request.setEntity(entity);
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
return response;
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
And somewhere else I call that method like:
HttpResponse httpResponse = doPost(url, json);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"));
It works fine for me...