I have the following web server class found here. I need to write an Android application(client) which can retrieve a file from this server. It would be great if anyone would be able to help me to do it. Thank you.
Server host address is: My-PC/ipaddress
When I execute the client it gives an exception.
java.net.ConnectException: Connection refused: connect
WebServer.Java
import java.io.*;
import java.net.*;
public class WebServer extends Thread {
public WebServer() {
this.start();
}
private void displayString(String string) { //an alias to avoid typing so much!
System.out.println(string);
}
private static final int UMBRA_PORT = 30480;
private static final int ROOM_THROTTLE = 200;
private InetAddress hostAddress;
//this is a overridden method from the Thread class we extended from
public void run() {
//we are now inside our own thread separated from the gui.
ServerSocket serversocket = null;
//To easily pick up lots of girls, change this to your name!!!
displayString("The simple httpserver v. 0000000000\nCoded by Jon Berg" +
"<jon.berg[on server]turtlemeat.com>\n\n");
//Pay attention, this is where things starts to cook!
try {
//print/send message to the guiwindow
displayString("Trying to bind to localhost on port " + Integer.toString(UMBRA_PORT) + "...");
//make a ServerSocket and bind it to given port,
//serversocket = new ServerSocket(port);
}
catch (Exception e) { //catch any errors and print errors to gui
displayString("\nFatal Error:" + e.getMessage());
return;
}
// Attempt to get the host address
try
{
hostAddress = InetAddress.getLocalHost();
}
catch(UnknownHostException e)
{
System.out.println("Could not get the host address.");
return;
}
// Announce the host address
System.out.println("Server host address is: "+hostAddress);
// Attempt to create server socket
try
{
serversocket = new ServerSocket(UMBRA_PORT,0,hostAddress);
}
catch(IOException e)
{
System.out.println("Could not open server socket.");
return;
}
// Announce the socket creation
System.out.println("Socket "+serversocket+" created.");
displayString("OK!\n");
//go in a infinite loop, wait for connections, process request, send response
while (true) {
displayString("\nReady, Waiting for requests...\n");
try {
//this call waits/blocks until someone connects to the port we
//are listening to
Socket connectionsocket = serversocket.accept();
//figure out what ipaddress the client commes from, just for show!
InetAddress client = connectionsocket.getInetAddress();
//and print it to gui
displayString(client.getHostName() + " connected to server.\n");
//Read the http request from the client from the socket interface
//into a buffer.
BufferedReader input =
new BufferedReader(new InputStreamReader(connectionsocket.
getInputStream()));
//Prepare a outputstream from us to the client,
//this will be used sending back our response
//(header + requested file) to the client.
DataOutputStream output =
new DataOutputStream(connectionsocket.getOutputStream());
//as the name suggest this method handles the http request, see further down.
//abstraction rules
http_handler(input, output);
}
catch (Exception e) { //catch any errors, and print them
displayString("\nError:" + e.getMessage());
}
} //go back in loop, wait for next request
}
//our implementation of the hypertext transfer protocol
//its very basic and stripped down
private void http_handler(BufferedReader input, DataOutputStream output) {
int method = 0; //1 get, 2 head, 0 not supported
String http = new String(); //a bunch of strings to hold
String path = new String(); //the various things, what http v, what path,
String file = new String(); //what file
String user_agent = new String(); //what user_agent
try {
//This is the two types of request we can handle
//GET /index.html HTTP/1.0
//HEAD /index.html HTTP/1.0
String tmp = input.readLine(); //read from the stream
String tmp2 = new String(tmp);
tmp.toUpperCase(); //convert it to uppercase
if (tmp.startsWith("GET")) { //compare it is it GET
method = 1;
} //if we set it to method 1
if (tmp.startsWith("HEAD")) { //same here is it HEAD
method = 2;
} //set method to 2
if (method == 0) { // not supported
try {
output.writeBytes(construct_http_header(501, 0));
output.close();
return;
}
catch (Exception e3) { //if some error happened catch it
displayString("error:" + e3.getMessage());
} //and display error
}
//}
//tmp contains "GET /index.html HTTP/1.0 ......."
//find first space
//find next space
//copy whats between minus slash, then you get "index.html"
//it's a bit of dirty code, but bear with me...
int start = 0;
int end = 0;
for (int a = 0; a < tmp2.length(); a++) {
if (tmp2.charAt(a) == ' ' && start != 0) {
end = a;
break;
}
if (tmp2.charAt(a) == ' ' && start == 0) {
start = a;
}
}
path = tmp2.substring(start + 2, end); //fill in the path
}
catch (Exception e) {
displayString("errorr" + e.getMessage());
} //catch any exception
//path do now have the filename to what to the file it wants to open
displayString("\nClient requested:" + new File(path).getAbsolutePath() + "\n");
FileInputStream requestedfile = null;
try {
//try to open the file,
requestedfile = new FileInputStream(path);
}
catch (Exception e) {
try {
//if you could not open the file send a 404
output.writeBytes(construct_http_header(404, 0));
//close the stream
output.close();
}
catch (Exception e2) {}
displayString("error" + e.getMessage());
} //print error to gui
//happy day scenario
try {
int type_is = 0;
//find out what the filename ends with,
//so you can construct a the right content type
if (path.endsWith(".zip") ) {
type_is = 3;
}
if (path.endsWith(".jpg") || path.endsWith(".jpeg")) {
type_is = 1;
}
if (path.endsWith(".gif")) {
type_is = 2;
}
if (path.endsWith(".ico")) {
type_is = 4;
}
if (path.endsWith(".xml")) {
type_is = 5;
}
//write out the header, 200 ->everything is ok we are all happy.
output.writeBytes(construct_http_header(200, 5));
//if it was a HEAD request, we don't print any BODY
if (method == 1) { //1 is GET 2 is head and skips the body
byte [] buffer = new byte[1024];
while (true) {
//read the file from filestream, and print out through the
//client-outputstream on a byte per byte base.
int b = requestedfile.read(buffer, 0,1024);
if (b == -1) {
break; //end of file
}
output.write(buffer,0,b);
}
//clean up the files, close open handles
}
output.close();
requestedfile.close();
}
catch (Exception e) {}
}
//this method makes the HTTP header for the response
//the headers job is to tell the browser the result of the request
//among if it was successful or not.
private String construct_http_header(int return_code, int file_type) {
String s = "HTTP/1.0 ";
//you probably have seen these if you have been surfing the web a while
switch (return_code) {
case 200:
s = s + "200 OK";
break;
case 400:
s = s + "400 Bad Request";
break;
case 403:
s = s + "403 Forbidden";
break;
case 404:
s = s + "404 Not Found";
break;
case 500:
s = s + "500 Internal Server Error";
break;
case 501:
s = s + "501 Not Implemented";
break;
}
s = s + "\r\n"; //other header fields,
s = s + "Connection: close\r\n"; //we can't handle persistent connections
s = s + "Server: SimpleHTTPtutorial v0\r\n"; //server name
switch (file_type) {
//plenty of types for you to fill in
case 0:
break;
case 1:
s = s + "Content-Type: image/jpeg\r\n";
break;
case 2:
s = s + "Content-Type: image/gif\r\n";
break;
case 3:
s = s + "Content-Type: application/x-zip-compressed\r\n";
break;
case 4:
s = s + "Content-Type: image/x-icon\r\n";
case 5:
s = s + "Content-Type: text/xml\r\n";
break;
default:
s = s + "Content-Type: text/html\r\n";
break;
}
////so on and so on......
s = s + "\r\n"; //this marks the end of the httpheader
//and the start of the body
//ok return our newly created header!
return s;
}
}
Client.Java
public class WatchMeManagerClient {
private static Socket socket;
private static PrintWriter printWriter;
public static void main(String[] args) throws Exception {
try {
URL url;
URLConnection urlConn;
DataInputStream dis;
url = new URL("http://ipaddress/xml/userGroup.xml");
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
dis = new DataInputStream(urlConn.getInputStream());
String s;
while ((s = dis.readLine()) != null) {
System.out.println(s);
}
dis.close();
}
catch (MalformedURLException mue) {
System.out.println(mue.toString());
} catch (IOException ioe) {
System.out.println(ioe.toString());
}
}
}
When I run the code on PC it works. But when I try to execute it on the Android Device it gives following errors.
Such problems are either due to one of the following:
The port is wrong
Firewall is stopping it.
Using Sockets require the following permission which I think you are missing:
<uses-permission android:name="android.permission.INTERNET" />
Did you allow internet access in your manifest?
<uses-permission android:name="android.permission.INTERNET"/>
Related
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!
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;
}
The server should send a message "Hello :: enter QUIT to exit" to the client, then the client types in any text and the server echos back the client's text adding "From server: " before their message.
But there seems to be a mix up in the order and I can't seem to find where! I've been on this all day!
This is the Server's code:
import java.net.*;
public class Server {
public static void main(String[] args) {
int nreq = 1;
try
{
ServerSocket sock = new ServerSocket (8080);
for (;;)
{
Socket newsock = sock.accept();
System.out.println("Creating thread ...");
Thread t = new ThreadHandler(newsock,nreq);
t.start();
}
}
catch (Exception e)
{
System.out.println("IO error " + e);
}
System.out.println("End!");
}
}
ThreadHandler code:
import java.io.*;
import java.net.*;
class ThreadHandler extends Thread {
Socket newsock;
int n;
ThreadHandler(Socket s, int v) {
newsock = s;
n = v;
}
// #SuppressWarnings("deprecation")
public void run() {
try {
PrintWriter outp = new PrintWriter(newsock.getOutputStream(), true);
BufferedReader inp = new BufferedReader(new InputStreamReader(
newsock.getInputStream()));
outp.println("Hello :: enter QUIT to exit");
boolean more_data = true;
String line;
while (more_data) {
line = inp.readLine();
if (line == null) {
more_data = false;
} else {
outp.println("From server: " + line + "\n");
if (line.trim().equals("QUIT"))
more_data = false;
}
}
newsock.close();
} catch (Exception e) {
System.out.println("IO error " + e);
}
}
}
And the Client code:
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Client {
// #SuppressWarnings("deprecation")
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
try {
Socket s = new Socket("localhost", 8080);
PrintWriter outp = new PrintWriter(s.getOutputStream(), true);
BufferedReader inp = new BufferedReader(new InputStreamReader(
s.getInputStream()));
boolean more_data = true;
System.out.println("Established connection");
String line;
while (more_data) {
line = inp.readLine();
String userInput = scanner.nextLine();
outp.println(userInput);
if (line == null) {
more_data = false;
} else
System.out.println(line);
}
System.out.println("end of while");
} catch (Exception e) {
System.out.println("IO error " + e);
}
}
}
I'm testing it out so after I'm going to make the client an Android phone - if that's possible -
Update:
I've changed the server's code to:
outp.println("Hello :: enter QUIT to exit \n");
boolean more_data = true;
String line;
while (more_data) {
line = inp.readLine();
System.out.println("Message '" + line + "' echoed back to client.");// !!
if (line == null) {
System.out.println("line = null");
more_data = false;
} else {
outp.println("From server: " + line + ". \n");
if (line.trim().equals("QUIT"))
more_data = false;
}
}
newsock.close();
System.out.println("Disconnected from client number: " + n);
and added "\n" at the end of the Hello message as Luis Miguel Serrano suggested, And changed the Client's side as below:
boolean more_data = true;
System.out.println("Established connection");
String line;// = inp.readLine();
while (more_data) {
line = inp.readLine();
System.out.println(line);
if (line == null) {
// nothing read
more_data = false;
} else
line = inp.readLine();
System.out.println(line);
String userInput = scanner.nextLine();
if (userInput.trim() == "QUIT") {
s.close();
System.out.println("Disconnected from server.");
more_data = false;
} else
outp.println(userInput);
}
System.out.println("end of while");
And it works fine now.
If anyone could suggest me some Android client-java server tutorials would appreciate it.
In sequence of your comment, it could be a flushing issue. Try adding the following line:
outp.flush();
after:
outp.println("Hello :: enter QUIT to exit");
When you write to a stream, sometimes the things you write are kept in a buffer. If you want to make sure that buffer is emptied and the string is actually sent, you need to call the flush() method.
Update
Also, add "\n" to the end of your Hello welcome message from the server. I think that will make it work.
I have a client in Android and server in C#, they communicate through socket.
I have this problem - if I run my client app in debug mode and place a breakpoint in right place - it works perfectly, but without it it doesn't.
Client sends adress of an image to server, server makes a thumbnail of it, converts it to byte[] and sends it back. Client gets the byte[], converts it back into image and shows it.
I've also found out that when it doesn't get the right byte[] its size is 2896 and sometimes 1448, no matter what the original size of the array sent was.
Here's the client:
private void connectSocket(String a){
try {
InetAddress serverAddr = InetAddress.getByName("192.168.1.2");
Socket socket = new Socket(serverAddr, 4444);
String message = a;
flag = 0;
if(a.indexOf(".jpg")>0){
flag = 1;
}
ListItems.clear();
if(!a.equalsIgnoreCase("get_drives"))){
//.....
}
if(!ListItems.isEmpty()){
if(ListItems.get(0).matches("^[A-Z]{1}:$")){
ListItems.set(0, ListItems.get(0)+"\\");
}
}
PrintWriter out = null;
BufferedReader in = null;
InputStream is = null;
try {
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
is = socket.getInputStream();
out.println(message);
String text = "";
String finalText = "";
if(flag!=1){
while ((text = in.readLine()) != null) {
finalText += URLDecoder.decode(text, "UTF-8");
}
String[] result = finalText.split("#");
for(int i = 0; i<result.length; i++)
ListItems.add(result[i]);
}
if(flag ==1){
byte[] buffer = new byte[9999];
//placing breakpoint at the next line or before it makes it work fine
int size = is.read(buffer);
//but placing a breakpoint at the line below doesn't make it work
//it starts getting another byte array
byte[] bufffer2 = new byte[size];
for(int g = 0; g<size;g++){
bufffer2[g] = buffer[g];
}
//is.read(bufffer2);
//int read = is.read(buffer);
image = (ImageView)findViewById(R.id.imageView1);
//while ((text = in.readLine()) != null) {
// byte[] b = in.readLine().getBytes();
Bitmap bmp=BitmapFactory.decodeByteArray(bufffer2,0,bufffer2.length);
image.setImageBitmap(bmp);
//}
}
adapter.notifyDataSetChanged();
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
} finally {
socket.close();
}
} catch (UnknownHostException e) {
Log.e("TCP", "C: UnknownHostException", e);
e.printStackTrace();
} catch (IOException e) {
Log.e("TCP", "C: IOException", e);
e.printStackTrace();
}
}
Here's the server:
public class serv {
public static void Main() {
try {
IPAddress ipAd = IPAddress.Parse("192.168.1.2");
TcpListener myList=new TcpListener(ipAd,4444);
m:
myList.Start();
Socket s=myList.AcceptSocket();
byte[] b=new byte[100];
int k=s.Receive(b);
char cc = ' ';
string test = null;
Console.WriteLine("Recieved...");
for (int i = 0; i < k-1; i++)
{
Console.Write(Convert.ToChar(b[i]));
cc = Convert.ToChar(b[i]);
test += cc.ToString();
}
string[] response = null;
ASCIIEncoding asen = new ASCIIEncoding();
switch (test)
{
default:
MyExplorer(test, s);
break;
}
s.Close();
myList.Stop();
goto m;
}
catch (Exception e) {
Console.WriteLine("Error..... " + e.StackTrace);
}
}
public static void MyExplorer(string r, Socket s){
Image imgThumb = null;
if (r.Contains(".jpg"))
{
Image image = null;
image = Image.FromFile(r);
// Check if image exists
if (image != null)
{
imgThumb = image.GetThumbnailImage(100, 100, null, new IntPtr());
s.Send(imageToByteArray(imgThumb));
byte[] b = imageToByteArray(imgThumb);
}
return;
}
}
public static byte[] imageToByteArray(System.Drawing.Image imageIn)
{
MemoryStream ms = new MemoryStream();
imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
return ms.ToArray();
}
}
The read(byte []) method in InputStream reads as many bytes as currently available. It does not necessarily mean that there won't be more bytes available later. So you need to do something like
while(true) {
int s = is.read(buffer);
if(s == -1) break;
// else
add read buffer to image array
}
extract image from image array
where "image array" is some byte array where you keep adding the read buffer until you reach then end of the stream.
The reason your code works with the breakpoint is that by the time you go through the debugger the whole stream is available, while in non-debug the whole stream is not yet available when you do the read.
The difference is likely due to the fact that on the debugger, you are able to slow and stop the application - this gives time for the server to respond to your call. It looks like you are not using any asynchronous methods to call connect socket (well, I can't see any evidence of this from your code anyway).
To fix this, you should try extending the AsyncTask object examples here
EDIT: #Carsten probably has the correct solution, but you should STILL use an AsyncTask if you are not already.
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();
}
}
}