I have created a HTTP file server with the objective of transferring media files (mp3, ogg etc) to an Android device. When the server is accessed from the android browser like
10.0.2.2:portNumber/path/to/file
The server initiates the file download process. Of course the customer would not do such a thing, Its fine for testing the file server.
I m new to Android development and have learned that httpclient package can manage get/post requests. Here is the sample code I have been using for reading the response
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
return response;
The above code works fine when the server sends a list of file in JSON. Since the server part of sending file has been coded, the point where I m stuck is in retrieving the media file on android.
I m confused about how to receive the mp3 files send by the server. Should they be read in a stream ? Thanks
Yes, you want to read the file onto disk via an inputstream.
Here's an example. If you don't want a file download progress bar then remove the progress related code.
try {
File f = new File("yourfilename.mp3");
if (f.exists()) {
publishProgress(100,100);
} else {
int count;
URL url = new URL("http://site:port/your/mp3file/here.mp3");
URLConnection connection = url.openConnection();
connection.connect();
int lengthOfFile = connection.getContentLength();
long total = 0;
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(f);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int)(total/1024),lengthOfFile/1024);
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
}
} catch (Exception e) {
Log.e("Download Error: ", e.toString());
}
Related
I am trying to get a picture from a Hikvision IP Camera URL which has a a URL that is more or less formed like this:http://IPaddress:port#/Streaming/channels/1/picture
However as you notice the folder is just named picture with no straight link to an image and its extensions. When I use Picasso library or just normal HttpConnection it fails to get the image / bitmap. How else can I retrieve the image? When I enter the URL in my web browser it loads perfectly and shows me that the picture is .jpeg format.EDIT
Whenever I try to access the snapshot image using InputStream and Bitmap I get a FileNotFoundException error
The problem as pointed out by Dario was the authentication. Status 401 was being returned and that is why the FileNotFoundException was being thrown. The answer he gave me had a lot of deprecated methods my Gradle couldnt even get some of the classes.However I found another way with help from the following forums 1, 2 so I combined with another page for the authentication which I cant find and had the following:
boolean isSaved = false;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI(AppConst.IMAGE_URL));
UsernamePasswordCredentials credentials =
new UsernamePasswordCredentials(AppConst.USERNAME, AppConst.PASSWORD);
BasicScheme scheme = new BasicScheme();
Header authorizationHeader = scheme.authenticate(credentials, request);
request.addHeader(authorizationHeader);
HttpResponse response = client.execute(request);
Log.d("responseType",response!=null? response.getEntity().getContentType().toString():"emptyType");
Log.d("responseCode", response != null ? String.valueOf(response.getStatusLine().getStatusCode()) : "emptyCode");
if((response.getStatusLine().getStatusCode()==200) && (response.getEntity()!=null)){//status OK and not empty
//save stuff
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
String path = APP_DIR+System.currentTimeMillis()+".jpg";
FileOutputStream output = new FileOutputStream(path);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = instream.read(buffer)) != -1) {
output.write(buffer, 0, len);
}
output.close();
Log.d("Snapshot Filename: ", path);
isSaved = true;
}
}else{
isSaved= false;
}
}catch (Exception ex){
Log.e("saveImageError",ex!=null? ex.getMessage():"error");
}
Had to add the following line in the gradle under the android section: useLibrary 'org.apache.http.legacy'
I am facing problem while trying to upload a zip file containing images converted into byte array to a restful wcf service from a json client using HTTPPost. The byte array is encoded into BASE64 enclosed into JSON object and sent using StringEntity with 2 more parameters. Around 6KB of file gets uploaded without any flaws but file more than 6KB are not send and I get a Bad Request - 400 status code. Following code is used to upload the file:
File file = new File(dir, "file.zip");
byte[] buf = new byte[10240000];
fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum);
Log.v("read : buf ", buf + " : " + readNum + " bytes");
}
byte[] bytes = bos.toByteArray();
imgData = Base64.encodeToString(bytes, Base64.DEFAULT);
JSONObject sendData=null;
Log.d("Image Data length", imgData.length()+"");
Log.d("Image data ", imgData);
try {
sendData= new JSONObject();
sendData.put("_binaryData", imgData);
sendData.put("_fileName", "fileName");
sendData.put("userid", userID);
int len = imgData.length();
int l=sendData.toString().length();
entity = new StringEntity(sendData.toString());
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// Send request
int len = imgData.length();
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
request.setHeader("Connection", "Keep-Alive");
request.setParams(httpParameters);
DefaultHttpClient httpClient = new DefaultHttpClient();
request.setEntity(entity);
HttpResponse response = httpClient.execute(request);
HttpEntity responseEntity = response.getEntity();
String str=response.getStatusLine().getReasonPhrase();
int i=response.getStatusLine().getStatusCode();
Log.v("ReasonPhrase :: StatusCode",str+" "+i);
int contentLength = (int) responseEntity.getContentLength();
char[] buffer = new char[(int) responseEntity
.getContentLength()];
InputStream stream = responseEntity.getContent();
Please help me in solving this.
If a message with <6k bytes does through, but messages with >6k don't, I'd take a look at the client and host limits for things like:
MaxBufferSize
MaxBufferPoolSize
MaxReceivedMessageSize
You don't say whether or not you have control over the host server settings, but you can increase and decrease the limits on items like those mentioned earlier. You can set them to Integer.Max if necessary, a size that would allow file uploads > 1 GB.
I make a GET request to a server using HttpUrlConnection.
After connecting:
I get response code: 200
I get response message: OK
I get input stream, no exception thrown but:
in a standalone program I get the body of the response, as expected:
{"name":"my name","birthday":"01/01/1970","id":"100002215110084"}
in a android activity, the stream is empty (available() == 0), and thus I can't get
any text out.
Any hint or trail to follow? Thanks.
EDIT: here it is the code
Please note: I use import java.net.HttpURLConnection; This is the standard
http Java library. I don't want to use any other external library. In fact
I did have problems in android using the library httpclient from apache (some of their anonymous .class can't be used by the apk compiler).
Well, the code:
URLConnection theConnection;
theConnection = new URL("www.example.com?query=value").openConnection();
theConnection.setRequestProperty("Accept-Charset", "UTF-8");
HttpURLConnection httpConn = (HttpURLConnection) theConnection;
int responseCode = httpConn.getResponseCode();
String responseMessage = httpConn.getResponseMessage();
InputStream is = null;
if (responseCode >= 400) {
is = httpConn.getErrorStream();
} else {
is = httpConn.getInputStream();
}
String resp = responseCode + "\n" + responseMessage + "\n>" + Util.streamToString(is) + "<\n";
return resp;
I see:
200
OK
the body of the response
but only
200
OK
in android
Trying the code of Tomislav I've got the answer.
My function streamToString() used .available() to sense if there is any data received,
and it returns 0 in Android. Surely, I called it too soon.
If I rather use readLine():
class Util {
public static String streamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
return sb.toString();
}
}
then, it waits for the data to arrive.
Thanks.
You can try with this code that will return response in String:
public String ReadHttpResponse(String url){
StringBuilder sb= new StringBuilder();
HttpClient client= new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
try {
HttpResponse response = client.execute(httpget);
StatusLine sl = response.getStatusLine();
int sc = sl.getStatusCode();
if (sc==200)
{
HttpEntity ent = response.getEntity();
InputStream inpst = ent.getContent();
BufferedReader rd= new BufferedReader(new InputStreamReader(inpst));
String line;
while ((line=rd.readLine())!=null)
{
sb.append(line);
}
}
else
{
Log.e("log_tag","I didn't get the response!");
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
The Stream data may not be ready, so you should check in a loop that the data in the stream is available before attempting to access it.
Once the data is ready, you should read it and store in another place like a byte array; a binary stream object is a nice choice to read data as a byte array. The reason that a byte array is a better choice is because the data may be binary data like an image file, etc.
InputStream is = httpConnection.getInputStream();
byte[] bytes = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] temp = new byte[is.available()];
while (is.read(temp, 0, temp.length) != -1) {
baos.write(temp);
temp = new byte[is.available()];
}
bytes = baos.toByteArray();
In the above code, bytes is the response as byte array. You can convert it to string if it is text data, for example data as utf-8 encoded text:
String text = new String(bytes, Charset.forName("utf-8"));
I make an application , this can download file form server.
use this code >>>
public int startDownload(String url, String filename) {
// create url connector
URL u;
byte[] buffer = new byte[1024];
try {
u = new URL(url + filename);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
InputStream in = c.getInputStream();
m_lMaxDownloadSz = c.getContentLength();
FileOutputStream f = new FileOutputStream(new File(FILE_PATH, filename));
m_bCancelDownload = false;
m_lCurrentDownloadSz = 0;
int len = 0;
while ((len = in.read(buffer, 0, 1024)) > 0) {
// if download is canceled.
if (m_bCancelDownload) {
f.close();
c.disconnect();
return FILE_DOWNLOAD_CANCELED;
}
if (knot++ >= PROGRESS_STEP) {
knot = 0;
myProgressDialog.setProgress(GetDownloadStatus());
}
f.write(buffer, 0, len);
m_lCurrentDownloadSz += len;
}
f.close();
c.disconnect();
} catch (Exception e) {
return FILE_DOWNLOAD_FAILED;
}
if (GetDownloadStatus() == 100) {
return FILE_DOWNLOAD_FINISHED;
} else {
return FILE_DOWNLOAD_FAILED;
}
}
and I want to use with PHP force download , but it not work , ordinary it use with file path like 'app/aaa.apk' it work! ,and I change to PHP file like 'php/forcedl.php' it not work.
I needs to use with php force download, How do I use?
ps. i have little english language skill , cause english language is not my main language
thank you
I discover for my answer
android-Java Code
__example:
byte[] buffer = new byte[1024];
String url = "http://www.bla-bla.com/forcedownload.php"
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
filesize = execute.getEntity().getContentLength();
fileOutput = new FileOutputStream(new File(FILE_PATH, "file_copyformserver.apk"));
while ((len = content.read(buffer, 0, 1024)) > 0) {
fileOutput.write(buffer, 0, len);
Thread.sleep(100);
}
fileOutput.close();
} catch (Exception e) {
e.printStackTrace();
}
php file
__example:
$file = '/home/bla-bla/domains/bla-bla.com/file/file.apk'; //not public folder
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/vnd.android.package-archive');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
this is short code , sorry if cannot run. :)
This is perhaps not the best way to do it, but have you considered renaming the file upon successfully downloading it? I haven't tried it, but I believe you can do it using the File.renameTo() method in Android.
Here's some pseudo code that I think will work, can't try it out right now though:
File.renameTo(new File(FILE_PATH, filename.replace(".apk", ".php")));
I have tried other methods to download info from a URL, but needed a faster one. I need to download and parse about 250 separate pages, and would like the app to not appear ridiculously slow. This is the code I am currently using to retrieve a single page, any insight would be great.
try
{
URL myURL = new URL("http://www.google.com");
URLConnection ucon = myURL.openConnection();
InputStream inputStream = ucon.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);
int current = 0;
while ((current = bufferedInputStream.read()) != -1) {
byteArrayBuffer.append((byte) current);
}
tempString = new String(byteArrayBuffer.toByteArray());
}
catch (Exception e)
{
Log.i("Error",e.toString());
}
Try to keep the connection open if the requests are to the same server. Also, try to avoid reallocations in the buffer, and read as much as possible in one go.
const int APPROX_MAX_PAGE_SIZE = 300;
try
{
URL myURL = new URL("http://www.google.com");
URLConnection ucon = myURL.openConnection();
ucon.setRequestHeader("Connection", "keep-alive") // (1)
InputStream inputStream = ucon.getInputStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(APPROX_MAX_PAGE_SIZE); // (2)
int current = 0;
byte[] buf = new byte[APPROX_MAX_PAGE_SIZE];
int read;
do {
read = bufferedInputStream.read(buf, 0, buf.length); // (3)
if(read > 0) byteArrayBuffer.append(buf, 0, read);
} while (read >= 0);
tempString = new String(byteArrayBuffer.toByteArray());
}
catch (Exception e)
{
Log.i("Error",e.toString());
}
Set Keep-alive header (not sure if you need this, on J2SE it is a configurable property as well)
Allocate what is "usually enough" in the buffer to avoid reallocation.
Read more than one byte at once
Disclaimer: This was written "in the blind" without access to a Java compiler. It may be that setRequestHeader is only available on a HttpURLConnection (cast needed), or that some parameters are wrong, but please feel free to edit if so.
Why don't you use the built in apache http components?
HttpClient httpClient = new DefaultHttpClient();
HttpGet request = new HttpGet(uri);
HttpResponse response = httpClient.execute(request);
int status = response.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
ByteArrayOutputStream ostream = new ByteArrayOutputStream();
response.getEntity().writeTo(ostream);
}
Use a pooled HTTPClient and try to make 2 or 3 requests at once. And try to create a memory pool to avoid allocations and the GC stalls.