Android HttpUrlConnection how to read response into pieces - java

actually I need a little more information about how to read response from HttpUrlConnection class in Android SDK. I'm trying to read a response from web server,but when it's too big my applications is throwin an OutOfMemoryException. So any source/help/suggestions on how to read the whole response into pieces is welcomed.
As I made a research I found out that I should set something like this : ((HttpURLConnection) connection).setChunkedStreamingMode(1024); But my problem is that I don't know how to read this chuncked stream. So I'll be very happy if someone can guide me through the right way.
Thanks!
Sample Code :
TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
String deviceId = tm.getDeviceId();
Log.w("device_identificator","device_identificator : "+deviceId);
String resolution = Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getWidth())+ "x" +
Integer.toString(getWindow().getWindowManager().getDefaultDisplay().getHeight());
Log.w("device_resolution","device_resolution : "+resolution);
String version = "Android " + Build.VERSION.RELEASE;
Log.w("device_os_type","device_os_type : "+version);
Log.w("device_identification_string","device_identification_string : "+version);
String locale = getResources().getConfiguration().locale.toString();
Log.w("set_locale","set_locale : "+locale);
String clientApiVersion = null;
PackageManager pm = this.getPackageManager();
PackageInfo packageInfo;
packageInfo = pm.getPackageInfo(this.getPackageName(), 0);
clientApiVersion = packageInfo.versionName;
Log.w("client_api_ver","client_api_ver : "+clientApiVersion);
long timestamp = System.currentTimeMillis()/1000;
String timeStamp = Long.toString(timestamp);
String url = "http://www.rpc.shutdown.com";
String charset = "UTF-8";
String usernameHash = hashUser(username,password);
String passwordHash = hashPass(username,password);
String query = String.format("username_hash=%s&password_hash=%s&new_auth_data=%s&debug_data=%s&client_api_ver=%s&set_locale=%s&timestamp=%s&"+
"device_os_type=%s&mobile_imei=%s&device_sync_type=%s&device_identification_string=%s&device_identificator=%s&device_resolution=%s",
URLEncoder.encode(usernameHash, charset),
URLEncoder.encode(passwordHash, charset),
URLEncoder.encode("1", charset),
URLEncoder.encode("1", charset),
URLEncoder.encode(clientApiVersion, charset),
URLEncoder.encode(locale, charset),
URLEncoder.encode(timeStamp, charset),
URLEncoder.encode(version, charset),
URLEncoder.encode(deviceId, charset),
URLEncoder.encode("14", charset),
URLEncoder.encode(version, charset),
URLEncoder.encode(deviceId, charset),
URLEncoder.encode(resolution, charset));
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
OutputStream output = null;
try {
output = connection.getOutputStream();
output.write(query.getBytes(charset));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
}
int status = ((HttpURLConnection) connection).getResponseCode();
Log.i("","Status : "+status);
for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
Log.i("Headers","Headers : "+header.getKey() + "=" + header.getValue());
}
InputStream response = connection.getInputStream();
Log.i("","Response : "+response.toString());
int bytesRead = -1;
byte[] buffer = new byte[8*1024];
while ((bytesRead = response.read(buffer)) >= 0) {
String line = new String(buffer, "UTF-8");
Log.i("","line : "+line);
handleDataFromSync(buffer);
}

Simply allocate a byte buffer that can hold a small amount of data and read from the input stream into this buffer (using the read method). Something like:
InputStream is = connection.getInputStream();
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = is.read(buffer)) >= 0) {
// process the buffer, "bytesRead" have been read, no more, no less
}

To read the Response Header try to use :
String sHeaderValue = connection.getHeaderField("Your_Header_Key");

Related

Getting an access token using OAuth, the response appears to be encoded

I'm pretty new to OAuth and am trying to refresh a token using a simple java client. Everything seems to go ok (or I think it does), the problem is I can't tell from the response if it's a good one. The http response code is 200, but when trying to parse the response for access_token, I get a null. Also difficult to troubleshoot is the "raw" response is garbled, or encoded in some way. I was thinking maybe it's byte but it doesn't seem to be. Here's the code:
private static String getClientCredentials() {
String postParams = "grant_type=refresh_token&refresh_token=1234567890";
Pattern pat = Pattern.compile(".*\"access_token\"\\s*:\\s*\"([^\"]+)\".*");
String clientId = "myClientID123";
String clientSecret = "myClientSecret123";
String tokenUrl = "https://www.host.com/oauth2/tenant/token";
String auth = clientId + ":" + clientSecret;
String authentication = Base64.getEncoder().encodeToString(auth.getBytes());
BufferedReader reader = null;
HttpsURLConnection connection = null;
String returnValue = "";
try {
URL url = new URL(tokenUrl);
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", "Basic " + authentication);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
connection.setRequestProperty("Connection", "keep-alive");
connection.setDoOutput(true);
OutputStream outStream = connection.getOutputStream();
outStream.write(postParams.getBytes());
outStream.flush();
outStream.close();
System.out.println("Resp code: " + connection.getResponseCode());
System.out.println("Resp message: " + connection.getResponseMessage());
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = null;
StringWriter out = new StringWriter(connection.getContentLength() > 0 ? connection.getContentLength() : 2048);
while ((line = reader.readLine()) != null) {
out.append(line);
}
String response = out.toString();
Matcher matcher = pat.matcher(response);
if (matcher.matches() && matcher.groupCount() > 0) {
returnValue = matcher.group(1);
}
System.out.println("response: " + response);
System.out.println("returnValue: " + returnValue);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
connection.disconnect();
}
return returnValue;
}
Here's the console output, sorry, I had to screenshot it because the characters didn't paste right:
Response Screenshot
Am I trying something that isn't allowed or is there a way to decode the response so I can run the pattern match to extract only the access_token? Or am I going about it all wrong? Any help is greatly appreciated in advance!

Passing json array in a key value pair in Java

I'm trying to send data using rest webservice in Java. I'm able to post data using Java in POST but now I need to send data in rawModeData and I also need to send JSONArray in surveysData key.
Please find the attached screenshot
This is the Code that I'm using to send data
try {
URL url = new URL(webServiceData.getSyncSurveyDataUrl());
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// ConnectionType
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setRequestProperty("charset", "utf-8");
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// Create the output form content
OutputStream out = httpURLConnection.getOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
JSONObject objects = new JSONObject();
objects.put("constituency", constituency);
objects.put("longitude", longitude);
objects.put("latitude", latitude);
objects.put("createdOn", createdOn);
for (Map.Entry<String, String> map : linkedHashMap.entrySet()) {
objects.put(map.getKey(), map.getValue());
}
writer.write("createdByDeviceId");
writer.write("=");
writer.write(URLEncoder.encode(loginModel.getDeviceId(), "UTF-8"));
writer.write("&");
writer.write("createdByMobileNumber");
writer.write("=");
writer.write(URLEncoder.encode(loginModel.getMobileNumber(), "UTF-8"));
writer.write("&");
writer.write("state");
writer.write("=");
writer.write(URLEncoder.encode(loginModel.getLoggedInState(), "UTF-8"));
writer.write("&");
writer.write("eventId");
writer.write("=");
writer.write(URLEncoder.encode(loginModel.getEventId(), "UTF-8"));
writer.write("&");
writer.write("surveysData");
writer.write("=");
writer.write(URLEncoder.encode(objects.toString(), "UTF-8"));
if (httpURLConnection.getResponseCode() != 200) {
System.out.println("Exception in 200: " + httpURLConnection.getResponseCode());
System.out.println("Exception Message: " + httpURLConnection.getResponseMessage());
/*errorLabel.setText(httpURLConnection.getResponseMessage());
errorLabel.setVisible(true);*/
}
} catch (Exception e) {
return false;
}
I'm getting 401 error message
I think you missed some authentication token in headers. Something like : httpURLConnection.setRequestProperty("tokenKey", "yourAuthToken");
You are not connecting to connection. Also I think that you need to setFixedLengthStreamingMode on connection and write output as byte array. Example:
//...
String queryParameters = formatQueryParameters(requestData);
byte[] output = queryParameters.getBytes(Charset.forName("UTF-8"));
connection.setFixedLengthStreamingMode(output.length);
connection.connect();
DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
dataOutputStream.write(output);
//...
public static String formatQueryParameters(Map<String, String> requestData) throws UnsupportedEncodingException {
String equals = URLEncoder.encode("=", "UTF-8");
String ampersand = URLEncoder.encode("&", "UTF-8");
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, String> entry : requestData.entrySet()) {
String encodedKey = URLEncoder.encode(entry.getKey(), "UTF-8");
String encodedValue = URLEncoder.encode(entry.getValue(), "UTF-8");
builder.append(encodedKey).append(equals).append(encodedValue).append(ampersand);
}
builder.deleteCharAt(builder.lastIndexOf(ampersand));
return builder.toString();
}

Getting unicode results in MailChimp oauth2 token creation

I have generated the access code by using https://login.mailchimp.com/oauth2/authorize API. But when I try to create the token using https://login.mailchimp.com/oauth2/token, I'm getting unicode result like this.
(?M?? ?0F?UJ?N?NQ? %`??'
"?????nb??f=?&9????i'f??]?~j*$??W??Reg??_T1-???;?oc)
qryStr = {"client_secret":"**********","grant_type":"authorization_code","redirect_uri":"https%3A%2F%2Flocalhost%3A9443%2Fverifymailchimp.sas","client_id":"********","code":"*************"}
HttpURLConnection connection = null;
try
{
URL reqURL = new URL("https://login.mailchimp.com/oauth2/token");
connection = (HttpURLConnection) reqURL.openConnection();
connection.setConnectTimeout(3000); // 3 seconds
connection.setReadTimeout(5000); // 5 seconds
connection.setUseCaches(false);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Accept", "application/json");
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); //No I18N
connection.setRequestProperty("Content-Length", "" + Integer.toString(qryStr.getBytes().length)); //No I18N
connection.setDoOutput(true);
OutputStream os = null;
try
{
os = connection.getOutputStream();
os.write(qryStr.getBytes(CHARSET));
}
finally
{
try{os.close();}catch(Exception e){}
}
int resCode = connection.getResponseCode();
boolean success = (resCode >= 200 && resCode < 300);
InputStream is = success ? connection.getInputStream() : connection.getErrorStream();
if (is == null)
{
return null;
}
String contentStr = null;
try
{
InputStreamReader reader = new InputStreamReader(is, CHARSET);
StringBuilder buffer = new StringBuilder();
char[] bytes = new char[1024];
int bytesRead;
while ((bytesRead = reader.read(bytes, 0, bytes.length)) > 0)
{
buffer.append(bytes, 0, bytesRead);
}
contentStr = buffer.toString();//?M?? ?0F?UJ?N?NQ? %`??' "?????nb??f=?&9????i'f??]?~j*$??W??Reg??_T1-???;?oc
}
finally
{
try{is.close();}catch(Exception e){}
}
}
Can anyone please tell the cause?
I found the cause of this case. An access code is valid for 30 seconds. Need to generate the token before the expiry. If they conveyed the proper error message, we can able to sort out the problem without any confusion :(

POST params empty, what am I doing wrong? HttpURLConnection / Android / Java

The code below shows a method, downloadUrl(), that takes a String, "myurl," its parameter. There are only two possible urls that I ever send to it, and the behavior of the method is different for each.
when myurl = URL1, it uses a GET request and everything works fine.
when myurl = URL2, however, it uses a POST request, and the response from the php page indicates that the post parameters sent with the request were empty. You can see the line where I set the POST params, so I don't understand why it's sending no params?!
Thanks for any help!
-Adam.
private String downloadUrl(String myurl) throws IOException {
InputStream is = null;
String response = "";
try {
URL urlObject = new URL(myurl);
HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();
// find out if there's a way to incorporate these timeouts into the progress bar
// and what they mean for shitty network situations
conn.setReadTimeout(10000 /* milliseconds */);
conn.setConnectTimeout(15000 /* milliseconds */);
conn.setDoInput(true);
// INSERTED QUICK CHECK TO SEE WHICH URL WE ARE LOADING FROM
// it's important because one is GET, and one is POST
if (myurl.equals(url2)){
Log.i(TAG, "dlurl() in async recognizes we are doing pre-call");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
BufferedWriter writer = new BufferedWriter(
new OutputStreamWriter(os, "UTF-8"));
String postParams = "?phone=" + phone;
writer.write(postParams);
Log.i(TAG, "we're adding " + postParams + "to " + urlObject);
writer.flush();
writer.close();
os.close();
}
else {
conn.setRequestMethod("GET");
conn.connect();
}
// Starts the query
int responseCode = conn.getResponseCode();
Log.i(TAG, "from " + myurl + ", The response code from SERVER is: " + responseCode);
is = conn.getInputStream();
// Convert the InputStream into a string
// i guess we look up how to do this
if (responseCode == HttpsURLConnection.HTTP_OK) {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
response += line;
}
} else {
response = "from downloadUrl, php page response was not OK: " + responseCode;
}
// it's good to close these things?
is.close();
conn.disconnect();
Log.i(TAG, "response is " + response);
return response;
// Makes sure that the InputStream is closed after the app is
// finished using it.
} finally {
if (is != null) {
is.close();
}
}
}
try with following code block to send parameters of the POST request.
Map<String,String> params = new LinkedHashMap<>();
params.put("phone", "phone");
StringBuilder postPraamString = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postPraamString.length() != 0) postPraamString.append('&');
postPraamString.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postPraamString.append('=');
postPraamString.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
writer.write(postDataBytes);
So I figured out the root of the problem...
In the line:
String postParams = "?phone=" + phone;
The problem was that leading question mark. The question mark should only be used in GET requests.

Streaming Google Speech api

currently I can recognize speech to text using google's speech api. Now that I have this, I was just wondering if there is a way I can stream the response of transcribed text and give it more text to transcribe at the same time. In other words I want to speak into the microphone, and as I speak I want a response from the google servers. The code I am using currently:
System.out.println("openning connection");
HttpsURLConnection httpConn = null;
ByteBuffer buff = ByteBuffer.wrap(data);
byte[] destdata = new byte[2048];
int resCode = -1;
OutputStream out = null;
try {
URL url = new URL(urlStr);
URLConnection urlConn = url.openConnection();
if (!(urlConn instanceof HttpsURLConnection)) {
throw new IOException ("URL must be HTTPS");
}
httpConn = (HttpsURLConnection)urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.setInstanceFollowRedirects(true);
httpConn.setRequestMethod("POST");
httpConn.setRequestProperty("User-Agent", USER_AGENT);
httpConn.setDoOutput(true);
httpConn.setRequestProperty("AcceptEncoding", "gzip,deflate,sdch");
httpConn.setChunkedStreamingMode(0); //TransferType: chunked
httpConn.setRequestProperty("Content-Type", "audio/l16; rate=" + sampleRate);
// this opens a connection, then sends POST & headers.
out = httpConn.getOutputStream();
//beyond 15 sec duration just simply writing the file
// does not seem to work. So buffer it and delay to simulate
// bufferd microphone delivering stream of speech
// re: net.http.ChunkedOutputStream.java
while(buff.remaining() >= destdata.length){
buff.get(destdata);
out.write(destdata);
};
byte[] lastr = new byte[buff.remaining()];
buff.get(lastr, 0, lastr.length);
out.write(lastr);
out.close();
resCode = httpConn.getResponseCode();
if(resCode >= HttpURLConnection.HTTP_UNAUTHORIZED){//Stops here if Google doesn't like us/
System.out.println("unauthorized");
throw new HTTPException(HttpURLConnection.HTTP_UNAUTHORIZED);//Throws
}
String line;//Each line that is read back from Google.
BufferedReader br = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
while ((line = br.readLine( )) != null) {
System.out.println(line);
if(line.length()>19 && resCode > 100 && resCode < HttpURLConnection.HTTP_UNAUTHORIZED){
GoogleResponse gr = new GoogleResponse();
parseResponse(line, gr);
fireResponseEvent(gr);
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
finally {httpConn.disconnect();}
Thanks for any help.

Categories

Resources