I am currently working with android and i am using a http connection with some headers (i havent included them or the real url for security purposes) to get a JSON response from an API, and feeding that response back into the application. The problem that i am having is that when using the getContentLength method of the http request, the wrong length is being returned (wrong length returned is 1225, the correct length in characters of the JSON array is 3365).
I have a feeling that the JSON is not fully loaded when my reader starts to read it, and as such is only reading the loaded JSON at that point. Is there any way around this, possibly using a delay on the HTTP connection or waiting until it is fully loaded to read the data?
URL url = new URL("https://www.exampleofurl.com");
HttpURLConnection request = (HttpURLConnection) url.openConnection();
request.connect();
int responseCode = request.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK) {
InputStream inputStream = request.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
long contentLength2 = Long.parseLong(request.getHeaderField("Content-Length"));
Log.i("contentLength: ", "Content: " + contentLength2);
I generally don't recommend always relying on "Content-Length" as it may not be available (you get -1), or perhaps affected by intermediate proxy.
Why don't you just read your stream until it is exhausted into memory buffer (say, StringBuilder) and then get the actual size, for example :
BufferedReader br = new BufferedReader(inputStream); // inputStream in your code
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
// finished reading
System.out.println("data size = " + sb.length());
JSONObject data = new JSONObject(sb.toString());
// and don't forget finally clauses with closing streams/connections
Related
I'm a newbie in android programming and I want to sent data to php server and receive data to show in android
but I have no idea to create it, I don't no to use library? and Can give some example for me to practice about it.
ps. sorry my english is not good.
example Myphp "xxx.xxx.x.x/api.php"
$keyword = $_GET['keyword'];
$index= $_GET['index'];
$path = "http://xxxxxxx/webservice/&query=".urlencode($keyword)."&index=".$index."";
$jsondata = file_get_contents($path);
$jsons = json_decode($jsondata,true);
echo json_encode($jsons);
I want to send keyword and index from edittext to php server and receive json data to show listview.
HttpURLConnection can be used for get,put,post,delete requests :
try {
// Construct the URL
URL url = new URL("http://xxxxxxx/webservice/&query="
+keyword.getText().toString()
+"&index="+index.getText().toString());
// Create the request
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// Read the input stream into a String
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
// Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
// But it does make debugging a *lot* easier if you print out the completed
// buffer for debugging.
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
}
JsonStr = buffer.toString(); //result
} catch (IOException e) {
}
where keyword and index will be your EditText Variables.
For my project i need to download a pdf file from google drive using java
I get my httpresponse code 200 and by using following method i store it in abc.pdf file
String url = "https://docs.google.com/uc?id="+fileid+"&export=download";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
// optional default is GET
conn.setRequestMethod("GET");
//add request header
conn.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = conn.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
OutputStream f0 = new FileOutputStream("C:\\Users\\Darshil\\Desktop\\abc.pdf",true);
while ((inputLine = in.readLine()) != null) {
//System.out.println(inputLine);
byte b[]=inputLine.getBytes();
//System.out.println(b);
f0.write(b);
}
in.close();
f0.close();
But when i try to open abc.pdf in my adobe reader x i get following error:
There was an error opening this document.The file is damaged and could not be repaired
You seem to be directly accessing the Google drive using Raw HTTP requests.
You may be better of using the Google Drive SDK. This link contains good examples to address the use cases you state in your question.
However if you do want to stick to your technique then you should not be using a BufferedReader.readLine(). This is because the PDF file is a binary finally that would depend upon the correct byte sequences to be preserved in order to be read correctly by the PDF reader software. Hopefully the below technique should help you:
//read in chunks of 2KB
byte[] buffer = new byte[2048];
int bytesRead = 0;
try(InputStream is = conn.getInputStream())
{
try(DataOutputStream os = new DataOutputStream(new FileOutputStream("file.pdf"))
{
while((bytesRead = is.read(buffer)) != -1)
{
os.write(buffer, 0, bytesRead);
}
}
}
catch(Exception ex)
{
//handle exception
}
Note that I am using the try-with-resources statement in Java 7
Hope this helps.
This question already has answers here:
Why does LogCat not show the full message?
(2 answers)
Closed 8 years ago.
I work with HttpUrlConnection in my App and in my common Java Test and I implemented a method and that Method (common for both of them, so, identical!!!) behaves in Android case in another way.
Both of them can right receive an identical response from Server but in Java Test I can show this response while in Android App is chunked to 3200 Chars.
That's my Code
private String sendPost() throws Exception{
String url = "http://www.something.com/my_page.jsp?";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
String urlParameters ="param1=val1¶m2=val2";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
// return result
Log.i("TAG", "sendPost:: Response length : " + response.length()); // <- This line returns the same length!!!
return response.toString();
}
All I can get of this object con from Class HttpUrlConnection like ContentLength, ContentType, etc is the same in both of these cases, therefore I suspect, there must be an intern Setting/Parameter of String/StringBuffer in Android, which distinguishes these case but I don't know what. readLine reads the same or at least the same number of chars cause the length of response is the same in both of cases.
If you could say me, what is wrong, I'd be very thankful.
Kind Regards
I can't understand your description of the symptoms; i.e. why you think that something is being truncated.
However, I can assure you that it is NOT due to a limit on the length of String or StringBuffer.
Those two classes do have a limit, but it is 2**31 (i.e. >2 billion) characters. You will typically get an OutOfMemoryError before your buffer gets that big.
This is the code I'm using to get response text.
private static String request(String urlstr){
// create connection
try {
URL url = new URL(urlstr);
URLConnection conn = url.openConnection();
StringBuilder response = new StringBuilder();
conn.setUseCaches(false);
conn.setRequestProperty("User-Agent", USER_AGENT);
// read response
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
response.append(line);
}
in.close();
return response.toString();
} catch (Exception e){
return null;
}
}
The problem is that when querying the very same request (simple get request, response is json) with my chrome browser I get the response almost 1 second faster than with this code in my application.
I wonder if theres anything I'm doing wrong in my code? Or it is chrome handling that request faster somehow?
Maybe there are some techniques to make this process faster?
Thanks
You seem to read the response line by line, but in the end you append every line to one single response, so it is not really required to read the response line by line. You can also do
char[] cbuf = new char[1024];
int len;
while ((len = in.read(cbuf)) != -1)
response.append(cbuf, 0, len);
Like this the response can be read in much larger chunks and you don't have the overhead of the readLine() method that has to look for newline characters in the input and split the content into lines.
You could also do a
new StringBuilder(connection.getContentLength());
to avoid that the StringBuilder has to increase it's capacity every time new content is appended. The StringBuilder is using a char[] internally and every time the array is not big enough for the new content it has to be copied to a new array with a larger size.
I am currently developing an Android application and encounter the following problem.
I am making an HTTP request to a server that is supposed to send me back XML content that I then parse. I noticed recurring errors while parsing long XML strings so I decided to display the result of my requests and discovered that the string (or the stream?) that I receive is randomly truncated. Sometimes I get the whole string, sometimes half, sometimes a third, and it seems to follow a certain pattern in the amount of characters that are truncated, what I mean by that is that I sometimes get 320 characters after a request then 156 after the next then 320 twice, then 156 again (these aren't the actual numbers but it follows a pattern).
Here is my code for the request and conversion of the InputStream into a string:
private String downloadUrlGet(String myurl) throws IOException {
InputStream is = null;
// Only display the first 20000 characters of the retrieved
// web page content.
int len = 20000;
try {
URL url = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setRequestProperty("Content-Type", "application/xml");
// Starts the query
conn.connect();
int response = conn.getResponseCode();
Log.d(DEBUG_TAG, "The response is: " + response);
is = conn.getInputStream();
// Convert the InputStream into a string
String contentAsString = readIt(is, len);
return contentAsString;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
// Reads an InputStream and converts it to a String.
private String readIt(InputStream stream, int len) throws IOException, UnsupportedEncodingException {
Reader reader = null;
reader = new InputStreamReader(stream, "UTF-8");
char[] buffer = new char[len];
reader.read(buffer);
return new String(buffer);
}
The length of the XML that I try to retrieve is much less than 20000.
I tried to use HttpURLConnection.setChunkedStreamingMode() with 0 and various other numbers as parameter but it didn't change anything.
Thanks in advance for any suggestions.
You are making the usual mistake of assuming that read() fills the buffer. See the Javadoc. It isn't obliged to do that. It isn't obliged to transfer more than one byte as a matter of fact. You need to read in a loop until you have encountered end of stream (read() returns -1).