I am writing android code to change the field in a Nest thermostat using the newly released API. Authentication and getting the field values is working just perfect, however I am haing problem with changing the field values. Based on the the API for changing the field values you need to use HTTP put, but once I am doing this, nothing happens in the device (the value (e.g. the value of target_temperature_f doesn't change!))
Here is my android code:
String url = "https://developer-api.nest.com/devices/thermostats/"
+ this.device_id + "?auth=" + this.access_token;
try{
HttpClient httpclient = new DefaultHttpClient();
/** set the proxy , not always needed */
HttpHost proxy = new HttpHost(proxy_ip,proxy_port);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,proxy);
// Set the new value
HttpPut httpPut = new HttpPut(url);
httpPut.setHeader("Content-Type", "application/json");
JSONObject jsonObj = new JSONObject("{\"target_temperature_f\":'60'}");
HttpEntity put_entity = new StringEntity(jsonObj.toString());
httpPut.setEntity(put_entity);
HttpResponse put_response = httpclient.execute(httpPut);
I can set the field in the device via "curl" command in linux though!! So the device is working fine.
Any help is highly appreciated!
I'm unsure of how to do it using the DefaultHttpClient and according to the documentation it has been deprecated in favor of HttpURLConnection.
Here's some code that uses HttpURLConnection that I've tested with Hue lights.
This will open a URL connection and perform a POST query with the given body. The readFromHttpConnection method expects a JSON response. It looks like Nest uses JSON so this may work for your needs.
private String synchronousPostMethod(String destination, String body)
{
Log.i(TAG, "Attempting HTTP POST method. Address=" + destination + "; Body=" + body);
String responseReturn;
try
{
HttpURLConnection httpConnection = openConnection(destination);
httpConnection.setDoOutput(true);
httpConnection.setRequestMethod("POST");
writeToHttpConnection(httpConnection, body);
responseReturn = readFromHttpConnection(httpConnection);
}
catch(Exception e)
{
responseReturn = RESPONSE_FAIL_MESSAGE + "; exception = " + e;
}
Log.i(TAG, "Result of HTTP POST method: " + responseReturn);
return responseReturn;
}
These are the helper methods.
private HttpURLConnection openConnection(String destination)
{
HttpURLConnection httpConnection = null;
try
{
URL connectionUrl = new URL(destination);
httpConnection = (HttpURLConnection) connectionUrl.openConnection();
}
catch(MalformedURLException malformedUrlException)
{
Log.w(TAG, "Failed to generate URL from malformed destination: " + destination);
Log.w(TAG, "MalformedURLException = " + malformedUrlException);
}
catch(IOException ioException)
{
Log.w(TAG, "Could not open HTTP connection. IOException = " + ioException);
}
return httpConnection;
}
private boolean writeToHttpConnection(HttpURLConnection httpConnection, String data)
{
// No data can be written if there is no connection or data
if(httpConnection == null || data == null)
{
return false;
}
try
{
OutputStreamWriter outputStream = new OutputStreamWriter(httpConnection.getOutputStream());
outputStream.write(data);
outputStream.close();
}
catch(IOException ioException)
{
Log.w(TAG, "Failed to get output stream from HttpUrlConnection. IOException = " + ioException);
return false;
}
return true;
}
private String readFromHttpConnection(HttpURLConnection httpConnection)
{
String responseReturn = "";
if(httpConnection != null)
{
try
{
InputStream response = httpConnection.getInputStream();
int size;
do
{
byte[] buffer = new byte[mResponseBufferSize];
size = response.read(buffer, 0, mResponseBufferSize);
// Convert the response to a string then add it to the end of the buffer
responseReturn += new String(buffer, 0, size);
}while(size < mResponseBufferSize || size <= 0);
// Cleanup
response.close();
}
catch (IOException ioException)
{
Log.w(TAG, "Failed to get input stream from HttpUrlConnection. IOException = " + ioException);
}
}
return responseReturn;
}
Related
So we're encountering a scenario where our Android clients are receiving a redirect from the server (following a POST -- Post/Redirect/Get) and Android is removing the body for the conversion to GET but seems to be leaving the Content-Length header in the GET request. I've verified that the request isn't making it into the web application (by placing a delegating handler that fires before a controller is selected). We also verified via cURL that if the content-length is removed from the request, the request goes through just fine.
So we're trying to find a solution on either front:
a) how do we stop android from sending that header? or
b) how do we tell IIS to allow or strip out the content-length header so that the request can get through?
UPDATE:
Requested java code that makes the call, as requested...
OutputStream postOut = null;
HttpURLConnection connection = null;
try {
URL url = new URL("<<url here>>");
connection = (HttpURLConnection) url.openConnection();
final String method = "POST";
final String data = "name=frank";
final String contentType = "application/x-www-form-urlencoded";
connection.setDoInput(true);
connection.setRequestProperty("Accept", contentType);
connection.setRequestProperty("Connection", "Close");
connection.setRequestProperty("Content-Type", contentType);
connection.setRequestMethod(method);
connection.setConnectTimeout(0);
connection.setReadTimeout(0);
connection.setUseCaches(false);
connection.setDefaultUseCaches(false);
connection.setChunkedStreamingMode(0);
if (method.equals("POST")) {
byte[] bits = data.getBytes();
connection.addRequestProperty("Content-Length", "" + bits.length);
connection.setDoOutput(true);
dumpHeaders(connection.getRequestProperties());
postOut = connection.getOutputStream();
if (postOut != null)
{
postOut.write(bits, 0, bits.length);
postOut.flush();
postOut.close();
postOut = null;
}
} else {
dumpHeaders(connection.getRequestProperties());
}
int httpStatus = connection.getResponseCode();
if (httpStatus / 100 > 3) {
Log.d("TEST", readResponse(connection.getErrorStream(), connection));
} else {
Log.d("TEST", readResponse(connection.getInputStream(), connection));
}
String finalUrl = connection.getURL().toExternalForm();
Log.d("TEST", "HTTP Status: " + httpStatus + ", URL: " + finalUrl);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
if (connection.getErrorStream() != null) {
Log.d("TEST", readResponse(connection.getErrorStream(), connection));
} else {
Log.d("TEST", e.getMessage());
}
}
if (connection != null) {
connection.disconnect();
}
im currently trying to implement the Steam Web API using the given code in the following repository -> https://github.com/Overv/SteamWebAPI/blob/master/SteamAPISession.cs into my Android app and im getting different exceptions dependend on using the given wep api ip ( 63.228.223.110 ) or the adress ( https://api.steampowered.com/ ) itself.
my code actually looks like this in the given method when building up a connection to the web api:
private String steamRequest( String get, String post ) {
final int MAX_RETRIES = 3;
int numberOfTries = 0;
HttpsURLConnection request = null;
while(numberOfTries < MAX_RETRIES) {
if (numberOfTries != 0) {
Log.d(TAG, "Retry -> " + numberOfTries);
}
try {
request = (HttpsURLConnection) new URL("https://api.steampowered.com/" + get).openConnection(); //or 63.228.223.110/ ???
SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
String host = "api.steampowered.com";
int port = 443;
int header = 0;
socketFactory.createSocket(new Socket(host, port), host, port, false);
request.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
request.setSSLSocketFactory(socketFactory);
request.setDoOutput(false);
// request.setRequestProperty("Host", "api.steampowered.com:443");
// request.setRequestProperty("Protocol-Version", "httpVersion");
request.setRequestProperty("Accept", "*/*");
request.setRequestProperty("Accept-Encoding", "gzip, deflate");
request.setRequestProperty("Accept-Language", "en-us");
request.setRequestProperty("User-Agent", "Steam 1291812 / iPhone");
request.setRequestProperty("Connection", "close");
if (post != null) {
byte[] postBytes;
try {
request.setRequestMethod("POST");
postBytes = post.getBytes("US-ASCII");
// request.setRequestProperty("Content-Length", Integer.toString(postBytes.length));
request.setFixedLengthStreamingMode(postBytes.length);
request.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
PrintWriter out = new PrintWriter(request.getOutputStream());
out.print(post);
out.close();
// DataOutputStream requestStream = new DataOutputStream(request.getOutputStream());
//// OutputStreamWriter stream = new OutputStreamWriter(request.getOutputStream());
//// stream.write(postBytes, 0, postBytes.length);
// requestStream.write(postBytes, 0, postBytes.length);
// requestStream.close();
message++;
} catch (ProtocolException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
int statusCode = request.getResponseCode();
InputStream is;
Log.d(TAG, "The response code of the status code is" + statusCode);
if (statusCode != 200) {
is = request.getErrorStream();
Log.d(TAG, String.valueOf(is));
}
// String src = null;
// OutputStreamWriter out = new OutputStreamWriter(request.getOutputStream());
// out.write(src);
// out.close();
Scanner inStream = new Scanner(request.getInputStream());
String response = "";
while (inStream.hasNextLine()) {
response += (inStream.nextLine());
}
// String src;
// BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream()));
// StringBuilder builder = new StringBuilder();
// while ((src = in.readLine()) != null) {
// builder.append(src);
// }
// String jsonData = builder.toString();
Log.d(TAG, response); //jsonData
// in.close();
return response; //jsonData
} catch (MalformedURLException ex) {
Toast.makeText(getActivity(), ex.toString(), Toast.LENGTH_LONG).show();
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (request != null) {
request.disconnect();
}
}
numberOfTries++;
}
Log.d(TAG, "Max retries reached. Giving up on connecting to Steam Web API...");
return null;
}
following exception occurs when using https://api.steampowered.com/ as url:
W/System.err﹕ java.io.FileNotFoundException: https://api.steampowered.com/ISteamOAuth2/GetTokenWithCredentials/v0001
D/OptionsFragment﹕ Failed to log in!
i've really tried and researched on those issues, but i just can't get a solution. If someone got a good hint on helping to solve these exceptions please let me know!
EDIT:
I've researched some more!
Looking up on https://partner.steamgames.com/documentation/webapi#creating the direct ip adress shouldn't be used and therefore only the DNS name itself (for further clarification look on the given link). Hence, looking up on the API interface list itself -> http://api.steampowered.com/ISteamWebAPIUtil/GetSupportedAPIList/v0001/?format=json there doesn't seem to be a given Interface with a method called ISteamOAuth2/GetTokenWithCredentials.(Or not anymore!) Only ISteamUserAuth and ISteamUserOAuth which seem to handle Authentication stuff.
I will update this post again if i should get a working connection and handling with the steam web api.
Cheers!
This is a bit of a complicated question as I do not know the exact problem. The main issue is that it takes a very long to get a very small package of data from our REST server from our Android app. I will describe it in detail and hope you can help me.
Problem
Data retrieval is fast enough (+/- 100ms) when:
Connected with WiFi
Connected with HSDPA
Running on Android Emulator with network settings (delay and speed) set to GPRS
However, when I use a phone on a location with bad connection (3G instead of HSDPA) calling the services can take up to 4s (current timeout on the AsyncTask).
Android
This is the code used to communicate with the services:
/**
* Get json string from service
*
* #param urlString url of service
* #return json result from service
*/
private String callService(String urlString) {
InputStream in = null;
HttpURLConnection c = null;
Scanner s = null;
String json = null;
try {
URL url = new URL(urlString);
Log.i(getClass().getName() + ".callService()", "start calling service: " + url);
long start = java.lang.System.currentTimeMillis();
try {
setAuthentication();
c = (HttpURLConnection) url.openConnection();
c.connect();
in = new BufferedInputStream(c.getInputStream());
s = new Scanner(in);
s.useDelimiter("\\A");
json = s.next();
} catch (IOException e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
}
Log.i(getClass().getName() + ".callService()", "complete calling service: (" + (System.currentTimeMillis() - start) + " ms) " + url);
return json;
} catch (Exception e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
} finally {
if (s != null) {
s.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
Log.e(getClass().getName() + ".callService()", "error: " + e.getMessage(), e);
}
}
if (c != null) {
c.disconnect();
}
}
return json;
}
I have tried several ways to call this, but currently this is done using an AsyncTask:
/**
* Retrieve json from service
*
* #param url url of service
* #return json
*/
public String getJsonFromServiceBasic(String url) {
ServiceTask task = new ServiceTask();
try {
return task.execute(url).get(4000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " interrupt exception: " + e.getMessage(), e);
} catch (ExecutionException e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " execution exception: " + e.getMessage(), e);
} catch (TimeoutException e) {
task.cancel(true);
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
} catch (Exception e) {
Log.e(getClass().toString() + " getJsonFromServiceBasic(" + url + ")", " timeout exception: " + e.getMessage(), e);
}
return null;
}
/**
* AsyncTask way of calling service
*/
class ServiceTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String json = callService(urls[0]);
return json;
}
}
AndroidManifest.xml:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Services
I do not think this is the issue, as it works fast enough with HSDPA, but I am not sure.
Restlet services on tomcat7 behind a proxy. We're using a ChallengeAuthenticator for authentication.
I have solved this problem by switching to Apache's HttpClient.
I am not sure why this is a solution as Google suggests using the HttpURLConnection, but for me this works.
Using this method instead of the callService method will solve my troubles with slow internet access.
private String callServiceClient(String urlString) {
String json = null;
HttpParams httpParams = new BasicHttpParams();
int connection_Timeout = 5000;
HttpConnectionParams.setConnectionTimeout(httpParams, connection_Timeout);
HttpConnectionParams.setSoTimeout(httpParams, connection_Timeout);
DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
httpClient.getCredentialsProvider().setCredentials(new AuthScope(null, -1),
new UsernamePasswordCredentials(user, password));
HttpGet httpget = new HttpGet(urlString);
// Execute the request
HttpResponse response;
try {
response = httpClient.execute(httpget);
// Examine the response status
StatusLine responseCode = response.getStatusLine();
Log.i(getClass() + ".callServiceClient()", "responsecode: " + responseCode);
if (responseCode.getStatusCode() != HttpStatus.SC_OK) {
return json;
}
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
json = convertStreamToString(instream);
// now you have the string representation of the HTML request
instream.close();
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
e.printStackTrace();
}
return json;
}
My Android app is talking to a webserver using SSL and GET requests. After switching to API 10 (Gingerbread) the SSL connection works - but only for the first time after the app starts...
The first request is sent by the main activity - after getting a response, another activity starts and sends multiple requests. And none of them is answered. In both cases the request is sent using a litte WebService class that is initiated in a new AsyncTask. After downsizing this alass, the only thing it actually contains is the URL(-String). Each activity starts its own instance of this class.
Here is the method that should do the GET request. As easily visible I included some code to avoid keep-alive - not that I don't like it, but it has been suggested in other answers to do so to avoid problems with multiple connections. Well, it did not work in my case.
public String webGet(String methodName, Map<String, String> params) {
String getUrl = webServiceUrl + methodName;
index++;
final int connectionID = index;
int i = 0;
for (Map.Entry<String, String> param : params.entrySet()) {
if (i == 0) {
getUrl += "?";
} else {
getUrl += "&";
}
try {
getUrl += param.getKey() + "=" + URLEncoder.encode(param.getValue(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
i++;
}
String response;
Log.e("WebGetURL", "["+connectionID+"] " + getUrl);
URL url;
try {
url = new URL(getUrl);
} catch (MalformedURLException e) {
Log.e("WebService", "Malformed URL: " + getUrl);
return null;
}
HttpURLConnection urlConnection;
try {
Log.e("WebGetResponse", "["+connectionID+"] openConnection()");
System.setProperty("http.keepAlive", "false");
if (webServiceSsl) {
Log.e("WebService", "Using HTTPS");
urlConnection = (HttpsURLConnection) url.openConnection();
} else {
urlConnection = (HttpURLConnection) url.openConnection();
}
urlConnection.setUseCaches(false);
urlConnection.setRequestProperty("Connection","Keep-Alive");
urlConnection.setDoOutput(false);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("GET");
} catch (IOException e) {
Log.e("WebService", "I/O exception opening connection: " + e.getMessage());
e.printStackTrace();
return null;
}
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(10000);
urlConnection.setRequestProperty("Connection", "close");
try {
urlConnection.connect();
Log.e("WebGetResponse", "["+connectionID+"] getInputStream()");
// This is the last thing I hear from my thread
BufferedInputStream bin = new BufferedInputStream(urlConnection.getInputStream());
Log.e("WebGetResponse", "["+connectionID+"] gotInputStream()");
byte[] contents = new byte[1024];
int bytesRead=0;
StringBuilder strFileContents = new StringBuilder();
Log.e("WebGetResponse", "["+connectionID+"] Waiting for data");
while((bytesRead = bin.read(contents)) != -1) {
String add = new String(contents, 0, bytesRead);
strFileContents.append(add);
}
bin.close();
response = strFileContents.toString();
} catch (IOException e) {
Log.e("WebService", "I/O exception reading stream: " + e.getMessage());
e.printStackTrace();
return null;
} finally {
urlConnection.disconnect();
}
Log.e("WebGetResponse", "["+connectionID+"] " + response);
return response;
}
I have been trying ans searching - I don't get the problem. Actually I cannot test the class on a non-https server currently, so I am unaware if the problem occurs in HTTP as well. However, the handshake seems to work, because the first request works well.
And here is the code that should start the request (final param is the GET content to send):
class ServerDataThread extends AsyncTask<Integer, Integer, String[]> {
#Override
protected String[] doInBackground(Integer... attempts) {
sendActive++;
int count = attempts.length;
String[] responses = new String[count];
for (int i = 0; i < count; i++) {
responses[i] = server.webGet("collector.php", params);
}
return responses;
}
protected void onPostExecute(String[] responses) {
sendActive--;
for (int i = 0; i < responses.length; i++) {
if (responses[i] == null) {
continue;
}
onResponseData(responses[i]);
}
}
}
new ServerDataThread().execute(0);
Could anyone please help me out with a hint what I am doing wrong? Thank you very much!
BurninLeo
My code (reproduced below), connects to a url and downloads the file to disk on android. All standard stuff. When I try using this code on a file on S3 accessed via a subdomain on our server mapped to a bucket (e.g. foo.example.com => bucket called foo.example.com), it often fails. Turns out (using the handy curl command..
"curl -v -L -X GET http://foo.example.com/f/a.txt")
.. that there's a redirect going on here.
The file download works ok, as HttpURLConnection will follow redirects by default, but the calls that require the header infomation (getContentLength, getHeaderFieldDate("Last-Modified", 0 ) etc) are returns the headers from the 307 redirect, and not the actual file thats downloaded.
Anyone know how to get around this?
Thanks
File local = null;
try {
Log.i(TAG, "Downloading file " + source);
conn = (HttpURLConnection) new URL(source).openConnection();
fileSize = conn.getContentLength(); // ** THIS IS WRONG ON REDIRECTED FILES
out = new BufferedOutputStream(new FileOutputStream(destination, false), 8 * 1024);
conn.connect();
stream = new BufferedInputStream(conn.getInputStream(), 8 * 1024);
byte[] buffer = new byte[MAX_BUFFER_SIZE];
while (true) {
int read = stream.read(buffer);
if (read == -1) {
break;
}
// writing to buffer
out.write(buffer, 0, read);
downloaded += read;
publishProgress(downloaded, fileSize);
if (isCancelled()) {
return "The user cancelled the download";
}
}
} catch (Exception e) {
String msg = "Failed to download file " + source + ". " + e.getMessage();
Log.e(TAG, msg );
return msg;
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close file " + destination);
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close file " + destination);
e.printStackTrace();
}
} else {
long dateLong = conn.getHeaderFieldDate("Last-Modified", 0 ); // ** THIS IS WRONG ON REDIRECTED FILES
Date d = new Date(dateLong);
local.setLastModified(dateLong);
}
have you tried to set redirects to false and try to manually capture the redirected URL and associated header fields with it?
For example something like this:
URL url = new URL(url);
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
ucon.setInstanceFollowRedirects(false);
URL secondURL = new URL(ucon.getHeaderField("Location"));
URLConnection conn = secondURL.openConnection();
This example captures the redirected URL, but you could easily tweak this to try for any other header field. Does this help?
Consider using httpclient-android. You should get the right headers after redirection with this:
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(YOUR_URL);
HttpResponse response = client.execute(request);
response.getAllHeaders()
Note that android comes with an older version of httpclient, but it has the same problem as you reported. You actually need to import "httpclient-android" for a newer version.
Note: The code snippet is for v4.3. For other versions, look for how to do it in regular apache HttpClient.
Well, I've been playing a bit and this code, which uses the HttpClient library rather than HttpUrlConnection works fine. The headers it returns are those of the final redirect hop.
At least on the devices I've tested it on.
HttpClient client = null;
HttpGet get = null;
HttpResponse response = null;
try {
client = new DefaultHttpClient();
get = new HttpGet(source);
response = client.execute(get);
Header contentSize = response.getFirstHeader("Content-Length");
if (contentSize != null) {
String value = contentSize.getValue();
fileSize = Long.parseLong(value);
}
if (fileSize == -1) {
Log.e(TAG, "Failed to read the content length for the file " + source);
}
Header lastModified = response.getFirstHeader("Last-Modified");
lastModifiedDate = null;
if (lastModified != null) {
lastModifiedDate = DateUtils.parseDate(lastModified.getValue());
}
if (lastModifiedDate == null) {
Log.e(TAG, "Failed to read the last modified date for the file " + source);
}
out = new BufferedOutputStream(new FileOutputStream(destination, false), 8 * 1024); // false means don't append
stream = new BufferedInputStream(response.getEntity().getContent(), 8 * 1024);
byte[] buffer = new byte[MAX_BUFFER_SIZE];
int count = 0;
while (true) {
int read = stream.read(buffer);
if (read == -1) {
break;
}
// writing to buffer
out.write(buffer, 0, read);
downloaded += read;
publishProgress(downloaded, fileSize);
if (isCancelled()) {
Log.w(TAG, "User Cancelled");
return; // NOTE that onPostExecute is not called here..
}
}// end of while
publishProgress(downloaded, fileSize);
} catch (Exception e) {
String msg = "Failed to download file " + source + ". " + e.getMessage();
Log.e(TAG, msg );
return msg;
} finally {
if (out != null) {
try {
out.flush();
out.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close file " + destination);
e.printStackTrace();
}
}
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
Log.e(TAG, "Failed to close file " + destination);
e.printStackTrace();
}
}
}