HTTP-Download loads tons of questionmarks - android

I created a Async-Download-Class to download JSON-Code from an interface-website. It does actually work, but sometimes it breaks and in the download log I can see question marks that should be a string. I had this problem before and solved it by just increasing the buffer size but this affects the speed of the app.
As you can imagine the JSON-Reader searches for a timestamp but he cannot find one. So the error I get is a formatexception but I think this is not relevant. (Sometimes undetermined object, too)
10-17 18:38:11.443: D/debug(13532): {"ident":"50572","ts":"24.05.2011 07:40","content":"<inmydays> Bin ich der einzige der dachte, beim Film 1+1=10 geht es um Nerds und nicht darum, dass 2 Schauspieler die 10 Hauptrollen spielen?","rating":"2044"},
10-17 18:38:11.443: D/debug(13532): {"ident":"28685","ts":"20.12.2009 08:40","content":"<Frau> ich wohne jetzt hier fast 10 monate und habe heute endlich mal meinen nachbarn von nebenan kennengelernt[newline]<Alex> Glückwunsch [newline]<Frau> in der videothek... Hat sich 7 pornos ausgeliehen[newline]<Alex> lol","rating":"4787"},
10-17 18:38:11.443: D/debug(13532): {"ident":"12820�������������������������������������������������������������������������������������������������������������������������������������������������������������
*I deleted most of the questionmarks to keep it clear.
#Override
protected String doInBackground(String... params) {
String urlStr = params[0];
InputStream is = null;
try {
URL url = new URL(urlStr);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setReadTimeout(100 * 1000);
connection.setConnectTimeout(100 * 1000);
connection.setRequestMethod("GET");
connection.setDoInput(true);
connection.connect();
int response = connection.getResponseCode();
Log.d("debug", "The response is: " + response);
is = connection.getInputStream();
// read string
// buffersize:
// ~max 1024 - 5
//
SharedPreferences sharedPref = PreferenceManager
.getDefaultSharedPreferences(activity);
String displayed_items = sharedPref.getString(
"pref_key_numberofitems", "10");
int items = Integer.parseInt(displayed_items);
if (items > 10) {
final int bufferSize = 40960 * 2;
byte[] buffer = new byte[40960 * 2];
ByteArrayOutputStream os = new ByteArrayOutputStream();
while (true) {
int count = is.read(buffer, 0, bufferSize);
if (count == -1) {
break;
}
os.write(buffer);
}
os.close();
result = new String(os.toByteArray(), "iso-8859-1");
Log.d("debug", result);
} else {
final int bufferSize = 2048 * 7;
byte[] buffer = new byte[2048 * 7];
ByteArrayOutputStream os = new ByteArrayOutputStream();
while (true) {
int count = is.read(buffer, 0, bufferSize);
if (count == -1) {
break;
}
os.write(buffer);
}
os.close();
result = new String(os.toByteArray(), "iso-8859-1");
Log.d("debug", result);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
Edit: Is there another method to download data from an interface webiste? Maybe this would help me.

This solved my problem:
String result = "";
#Override
protected String doInBackground(String... params) {
String urlStr = params[0];
URL url;
InputStream is = null;
BufferedReader br;
String line;
try {
url = new URL(urlStr);
is = url.openStream(); // throws an IOException
br = new BufferedReader(new InputStreamReader(is, "iso-8859-1"));
while ((line = br.readLine()) != null) {
result += line;
}
} catch (MalformedURLException mue) {
mue.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
if (is != null) is.close();
} catch (IOException ioe) {
// nothing to see here
}
}
Log.d("Downloaded", result);
return result;
}
My thoughts why this finally worked:
With this way of downloading data you don't need to define a buffer which can be full.
Hope it helps others too :)
Have a nice day!

what happens if you use another encoding like UTF-8 instead of ISO-8859-1?

Related

Can Java's FutureTask be an alternative to AsyncTask?

The docs say AsyncTask is designed to handle short operations(few seconds maximum) and states that Java classes like FutureTask are better for operations that last long. So I tried to send my location updates to the server using FutureTask but I am getting NetworkOnMainThreadException. I don't want to use AsyncTask because I wanted to keep the http connection open until the updates are cancelled. Here is my code:
SendLocation updates = new SendLocation(idt, String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
FutureTask ft = new FutureTask<String>(updates);
boolean b = ft.cancel(false);
ft.run();
class SendLocation implements Callable<String> {
String t, la, lo;
public SendLocation(String a, String b, String c){
this.t = a;
this.la = b;
this.lo = c;
}
public String call() {
sendUpdates(token, la, lo);
return "Task Done";
}
public void sendUpdates(String a, String b, String c){
HttpURLConnection urlConn = null;
try {
try {
URL url;
//HttpURLConnection urlConn;
url = new URL(remote + "driver.php");
urlConn = (HttpURLConnection) url.openConnection();
System.setProperty("http.keepAlive", "true");
//urlConn.setDoInput(true); //this is for get request
urlConn.setDoOutput(true);
urlConn.setUseCaches(false);
urlConn.setRequestProperty("Content-Type", "application/json");
urlConn.setRequestProperty("Accept", "application/json");
urlConn.setRequestMethod("POST");
urlConn.connect();
try {
//Create JSONObject here
JSONObject json = new JSONObject();
json.put("drt", a);
json.put("drlat", b);
json.put("drlon", c);
String postData = json.toString();
// Send POST output.
OutputStreamWriter os = new OutputStreamWriter(urlConn.getOutputStream(), "UTF-8");
os.write(postData);
Log.i("NOTIFICATION", "Data Sent");
os.flush();
os.close();
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
String msg = "";
String line = "";
while ((line = reader.readLine()) != null) {
msg += line;
}
Log.i("msg=", "" + msg);
} catch (JSONException jsonex) {
jsonex.printStackTrace();
Log.e("jsnExce", jsonex.toString());
}
} catch (MalformedURLException muex) {
// TODO Auto-generated catch block
muex.printStackTrace();
} catch (IOException ioex) {
ioex.printStackTrace();
try { //if there is IOException clean the connection and clear it for reuse(works if the stream is not too long)
int respCode = urlConn.getResponseCode();
InputStream es = urlConn.getErrorStream();
byte[] buffer = null;
int ret = 0;
// read the response body
while ((ret = es.read(buffer)) > 0) {
Log.e("streamingError", String.valueOf(respCode) + String.valueOf(ret));
}
// close the errorstream
es.close();
} catch(IOException ex) {
// deal with the exception
ex.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e("ERROR", "There is error in this code " + String.valueOf(e));
}
}
}
Doesn't it get executed in a worker thread? If the answer is no why does the docs say that it is an alternative to AsyncTask?
Your code must not be in the void run() method. This is where the asynchronous code is ran.

Parsing SHOUTcast 7.html metadata on Android

I am trying to check the status of a SHOUTcast stream using this URL:
http://85.17.167.136:8684/7.html
... which returns data like:
<HTML><meta http-equiv="Pragma" content="no-cache"></head><body>7,1,77,100,7,128,+44(0)7908 340 811 Follow Us #visionradiouk</body></html>
I know that the after the first comma returns 1 if the stream is up and running or returns 0 if the stream is down. My problem is getting the html of that page? I use this code, which works on other websites like Google etc.
TextView tView = (TextView) findViewById(R.id.textView1);
String htmlCode = "";
try {
URL url = new URL("http://85.17.167.136:8684/7.html");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String inputLine;
while ((inputLine = in.readLine())!= null)
htmlCode += inputLine;
System.out.println(htmlCode);
tView.setText(htmlCode);
in.close();
} catch (Exception e){
System.out.println("error");
}
}
Any ideas on what I am doing wrong?
Heres Pulsarman325's working solution, tidied up, with a little extra stuff i had to add to get it to work (try/catch and variable initialisations)
String url = "http://molestia.ponify.me:8062";
URL url2=null;
try
{
url2 = new URL(url + "/7.html");
}
catch (MalformedURLException e1)
{
e1.printStackTrace();
}
URLConnection con=null;
try
{
con = url2.openConnection();
}
catch (IOException e1)
{
e1.printStackTrace();
}
con.setRequestProperty("User-Agent", "Mozilla/5.0");
Reader r = null;
try
{
r = new InputStreamReader(con.getInputStream());
}
catch (IOException e)
{
e.printStackTrace();
}
StringBuilder buf = new StringBuilder();
int ch=0;
while (true)
{
try
{
ch = r.read();
}
catch (IOException e)
{
e.printStackTrace();
}
if (ch < 0)
break;
buf.append((char) ch);
}
String str = buf.toString();
String trackinfo = str.split(",")[6].split("</body>")[0];
Log.d("HTML", trackinfo);

Android: java.net.protocolException does not support output

I was previously using HttpClient and BasicNameValuePairs, for some reason i have to shift to HttpUrlConnection.
Hence this code, to make a HttpPost request with certain parameters:
public class MConnections {
static String BaseURL = "http://www.xxxxxxxxx.com";
static String charset = "UTF-8";
private static String result;
private static StringBuilder sb;
private static List<String> cookies = new ArrayList<String>();
public static String PostData(String url, String sa[][]) {
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(BaseURL + url)
.openConnection();
} catch (MalformedURLException e1) {
} catch (IOException e1) {
}
cookies = connection.getHeaderFields().get("Set-Cookie");
try{
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=" + charset);
}catch (Exception e) {
//Here i get Exception that "java.lang.IllegalStateException: Already connected"
}
OutputStream output = null;
String query = "";
int n = sa.length;
for (int i = 0; i < n; i++) {
try {
query = query + sa[i][0] + "="
+ URLEncoder.encode(sa[i][1], "UTF-8");
} catch (UnsupportedEncodingException e) {
}
}
try {
output = connection.getOutputStream();
output.write(query.getBytes(charset));
} catch (Exception e) {
//Here i get Exception that "android: java.net.protocolException: Does not support output"
} finally {
if (output != null)
try {
output.close();
} catch (IOException e) {
}
}
InputStream response = null;
try {
response = connection.getInputStream();
} catch (IOException e) {
//Here i get Exception that "java.io.IOException: BufferedInputStream is closed"
} finally {
//But i am closing it here
connection.disconnect();
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
response, "iso-8859-1"), 8);
sb = new StringBuilder();
sb.append(reader.readLine());
String line = "0";
while ((line = reader.readLine()) != null) {
sb.append("\n" + line);
}
response.close();
result = sb.toString();
} catch (Exception e) {
}
return result;
}
}
But i get such Exceptions as commented in the code.
Actually i am calling MConnections.PostData() twice from my Activity using a AsyncTask. This might cause the Exception: Already Connected but i am using connection.disconnect. But why am i still getting that Exception?
Am i using it the wrong way?
Thank You
For the protocol exception, try adding the following before you call getOutputStream():
connection.setDoOutput(true);
Discovered this answer thanks to Brian Roach's answer here: https://stackoverflow.com/a/14026377/387781
Side note: I was having this issue on my HTC Thunderbolt running Gingerbread, but not on my Nexus 4 running Jelly Bean.

How can I download Image File from an URL to ByteArray?

following is my code:
private byte[] downloadImage(String image_url) {
byte[] image_blob = null;
URL _image_url = null;
HttpURLConnection conn = null;
InputStream inputStream = null;
try {
_image_url = new URL(image_url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
conn = (HttpURLConnection) _image_url.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
conn.setDoInput(true);
try {
conn.connect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
conn.setUseCaches(false);
try {
inputStream = conn.getInputStream();
inputStream.read(image_blob);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
conn.disconnect();
}
return image_blob;
}
What I am trying to do is to get the byte array of an Image. Use it in a parcel to transfer it to another activity.
Using this code a NullPointerException is reported. Can any one say what is wrong?
You might want to try it like this:
DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(imageUrl);
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
int imageLength = (int)(entity.getContentLength());
InputStream is = entity.getContent();
byte[] imageBlob = new byte[imageLength];
int bytesRead = 0;
while (bytesRead < imageLength) {
int n = is.read(imageBlob, bytesRead, imageLength - bytesRead);
if (n <= 0)
; // do some error handling
bytesRead += n;
}
And by the way: The NullPointerException is caused because image_blob is null. You need to allocate the array first before you can read data into it.
Rather then sending image, you can send path of image which is download in cache. You can just use this methods to proive image path and download image into local path.
private String createLocal(String surl) {
URL url;
try {
url = new URL(surl);
String tempname=String.valueOf(surl.hashCode());
File root=getCacheDir();
File localfile=new File(root.getAbsolutePath()+"/"+tempname);
localfile.deleteOnExit();
if(!localfile.exists()){
InputStream is=url.openStream();
OutputStream os = new FileOutputStream(localfile);
CopyStream(is, os);
os.close();
}
return localfile.getAbsolutePath();
} catch (Exception e){
return null;
}
}
public static void CopyStream(InputStream is, OutputStream os) {
final int buffer_size=1024;
try {
byte[] bytes = new byte[buffer_size];
for(;;) {
int count=is.read(bytes, 0, buffer_size);
if(count == -1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
Your byte[] image_blob is null,you must new enough space like that before you use it:
image_blob = new byte[enough];
inputStream.read(image_blob);
public static byte[] getByteArray(String url) throws IOException {
InputStream inputStream = (InputStream) new URL(url).getContent();
return IOUtils.toByteArray(inputStream);
}

Android Inputstream.read problem on Gingerbread (while downloading)

I didn't find any question like this here.
Yesterday I finally got Gingerbread 2.3.4 on my Nexus One. When I opened my application (basically loads an XML Feed into a ListView) again, it got stuck while downloading.
It seems that InputStream stream; -> stream.read(buffer); doesn't return -1 any more, when it's finished.
The Code ist nearly the same from here Download Progress
Here's my code:
public InputStream getInputStreamFromURL(String urlString, DownloadProgressCallback callback)
throws IOException, IllegalArgumentException
{
InputStream in = null;
conn = (HttpURLConnection) new URL(urlString).openConnection();
fileSize = conn.getContentLength();
out = new ByteArrayOutputStream((int) fileSize);
conn.connect();
stream = conn.getInputStream();
// loop with step 1kb
while (status == DOWNLOADING) {
byte buffer[];
if (fileSize - downloaded > MAX_BUFFER_SIZE) {
buffer = new byte[MAX_BUFFER_SIZE];
} else {
buffer = new byte[(int) (fileSize - downloaded)];
}
int read = stream.read(buffer);
if (read == -1) {
break;
}
// writing to buffer
out.write(buffer, 0, read);
downloaded += read;
// update progress bar
callback.progressUpdate((int) ((downloaded / fileSize) * 100));
}// end of while
if (status == DOWNLOADING) {
status = COMPLETE;
}
in= (InputStream) new ByteArrayInputStream(out.toByteArray());
// end of class DownloadImageTask()
return in;
}
The problem basically is that when the download finishes, stream.read(buffer) returns 0 instead of -1. When I change
if (read == -1) {
break;
}
to 0 or
if (fileSize == downloaded) {
break;
}
I get ParseExceptions (ExpatParser) on my MainActivity.
On 2.2 it runs really perfect.
I cleared the app cache and tried a few other things already, but I'm really stuck now.
I hope that someone can help me. :)
UPDATE:
That's awesome, you're the man, Guillaume. :)
Thank you very much, that saved my evening! :)
Your Code for my needs here:
public InputStream getStreamFromURL(String urlString, DownloadProgressCallback callback){
// initialize some timeouts
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters,3000);
// create the connection
URL url;
try {
url = new URL(urlString);
URLConnection connection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
// connection accepted
if(httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
int size = connection.getContentLength();
int index = 0;
int current = 0;
InputStream input = connection.getInputStream();
BufferedInputStream buffer = new BufferedInputStream(input);
byte[] bBuffer = new byte[1024];
out = new ByteArrayOutputStream((int) size);
while((current = buffer.read(bBuffer)) != -1) {
out.write(bBuffer, 0, current);
index += current;
callback.progressUpdate((index/size)*100);
}
out.close();
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return (InputStream) new ByteArrayInputStream(out.toByteArray());
}
This code work on my 2.3.4 Nexus One :
try {
// initialize some timeouts
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
// create the connection
URL url = new URL(toDownload);
URLConnection connection = url.openConnection();
HttpURLConnection httpConnection = (HttpURLConnection) connection;
// connection accepted
if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
try {
file = new File(destination);
// delete the file if exists
file.delete();
} catch (Exception e) {
// nothing
}
int size = connection.getContentLength();
int index = 0;
int current = 0;
try {
file = new File(destination);
file.delete();
FileOutputStream output = new FileOutputStream(file);
InputStream input = connection.getInputStream();
BufferedInputStream buffer = new BufferedInputStream(input);
byte[] bBuffer = new byte[10240];
while ((current = buffer.read(bBuffer)) != -1) {
if (isCancelled()) {
file.delete();
break;
}
try {
output.write(bBuffer, 0, current);
} catch (IOException e) {
e.printStackTrace();
}
index += current;
publishProgress(index / (size / 100));
}
output.close();
} catch (SecurityException se) {
se.printStackTrace();
return 1;
} catch (FileNotFoundException e) {
e.printStackTrace();
return 1;
} catch (Exception e) {
e.printStackTrace();
return 2;
}
return 0;
}
// connection refused
return 2;
} catch (IOException e) {
return 2;
}

Categories

Resources