How would i know if i downloading of images failed?
What happens is that i download the image url first, and from there get the image filename to store to my database. Then have two methods to download from the url, and save is as the filename. Btw, they are being called by a method that is being called by an AsyncTask.
Here are the two methods (that are handed down by my senior) that is handles the download of the image files:
private void imageProcessing(String url, String filename) {
String root = Environment.getExternalStorageDirectory().toString();
// String root1= getResources().getIdentifier(name, defType, defPackage)
File myDir = new File(root + "/arson/images");
File nomedia = new File(myDir, ".nomedia");
if (!nomedia.exists()) {
Log.wtf("nomedia not exists", nomedia.getAbsolutePath().toString());
try {
nomedia.createNewFile();
} catch (IOException e1) {
Log.e("NEW FILE CREATION", e1.toString());
e1.printStackTrace();
}
} else {
Log.wtf("nomedia exists", nomedia.getAbsolutePath().toString());
}
File file = new File(myDir, filename);
if (file.exists()) {
file.delete();
}
try {
Bitmap bitmap = downloadBitmap(url);
myDir.mkdirs();
FileOutputStream out = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
Log.e("BITMAP PROCESS", e.toString());
}
}
public static Bitmap downloadBitmap(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
System.setProperty("http.keepAlive", "false");
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or
// IllegalStateException
getRequest.abort();
} finally {
if (client != null)
client.close();
}
return null;
}
Thanks in advance!
There are two kind of possible issues here.
1) HTTP Status Code is not 200 : You are returning null if this happens, and when you get null you can know there has been a problem downloading.
2) HTTP Status Code is 200 but file download fails : You will either have an exception here, or none at all. If you have an exception you are already catching it. For the other case where there is no exception you have to change your implementation a little. You will have to save the downloaded file first (temp file), read the contentLength and verify that it matches with what you got from the server. If the contentLength is correct, you can then use BitmapFactory to read the file from the device.
Related
We have an Android app, which we deploy by opening a browser on the device go to the customer url, then the browser downloads the file. We are also trying to download a separate .xml settings file. If I try this with in the browser, the xml will just display. In the Android app, could I copy the xml from the cache?
Is there any other way of downloading the xml?
Could I use a different file type, which the browser would download?
Thanks
Here's a method to download an xml file from a URL
try {
//set the download URL, a url that points to a file
URL url = new URL("http://your/path/to/file.xml");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
//set the path where we want to save the file
File SDCardRoot = Environment.getExternalStorageDirectory();
//create a new file, specifying the path, and the filename
//which we want to save the file as.
File file = new File(SDCardRoot,"data.xml");
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(file);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
progressDialog.setMax(totalSize);
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//now, read through the input buffer and write the contents to the file
while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
//add the data in the buffer to the file in the file output stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You should probably do this in the background, i.e. use an AsyncTasc.
If you need to load a small xml file the Document class is fairly straight forward to use. You can use an http get request to grab the xml file. Here is a simple function you can call, pass in a url, and get a xml document object you can dig into:
public static Document getXML(final String url) throws ExecutionException, InterruptedException {
Document out = null;
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Document> result = executor.submit(new Callable<Document>() {
public Document call() throws Exception {
HttpGet uri = new HttpGet(url);
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse resp = null;
try {
resp = client.execute(uri);
} catch (IOException e) {
e.printStackTrace();
}
StatusLine status = resp.getStatusLine();
if (status.getStatusCode() != 200) {
Log.d("http error", "HTTP error, invalid server status code: " + resp.getStatusLine());
}
// try {
HttpEntity entity = resp.getEntity();
InputStream in = entity.getContent();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document dom = null;
try {
dom = builder.parse(in);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return dom;
}
});
try {
out = result.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return out;
}
I am downloading requested image from my server , this image is successfully displayed after downloading but when i try to store the same image on my SD card it returns null.
Here is my code for downloading image and saving it.I am getting null on a call to bitmap.compress()
void saveImage() {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/saved_images");
myDir.mkdirs();
String fname = "Image.png";
File file = new File (myDir, fname);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
message_bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
//write the bytes in file
FileOutputStream fo;
try {
fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/*if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
message_bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}*/
}
static public Bitmap downloadBitmap(String url) {
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode + " while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(new FlushedInputStream(inputStream));
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or IllegalStateException
getRequest.abort();
Log.w("ImageDownloader", "Error while retrieving bitmap from " + url + e.toString());
} finally {
if (client != null) {
}
}
return null;
}
I think you are pretty close there. How about something similar to the below which downloads and saves an image:
try {
img_value = new URL("your_url");
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
mIcon1 = BitmapFactory.decodeStream(img_value.openConnection()
.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
String filename = "your_filename.jpg";
File file = new File(dir, filename);
if (file.exists()) {
try{
file.delete();
}catch(Exception e){
//sdcard plugged in
}
}
try {
FileOutputStream out = new FileOutputStream(file);
mIcon1.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();//will occur if the phone is plugged in
}
Im aiming to create an app that allows me to download multiple images from an array of urls and allow the user to swipe through them.
Im a bit unsure on how to do this as im not sure how to save the images on the kindle (it has no sd card).
Any help on how to save images from the web locally (to be accessed asap) would be great!
You can use this method in a loop with your array. Do not worry about the external directory. The devices which haven't got sd card slot, have a separate place from the internal memory to act like an "external memory".
public Bitmap downloadImage(String url)
{
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet getRequest = new HttpGet(url);
try
{
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK)
{
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null)
{
InputStream inputStream = null;
try
{
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
saveImageToExternalMemory(bitmap, url); //edit the name if need
return bitmap;
}
finally
{
if (inputStream != null)
{
inputStream.close();
}
entity.consumeContent();
}
}
}
catch(IOException e)
{
getRequest.abort();
}
catch (Exception e)
{
getRequest.abort();
}
finally
{
if (client != null)
{
client.getConnectionManager().shutdown();
}
}
return null;
}
This will save the image with the name of the url, you can edit to your needs. And to save the image for external memory (it doesn't matter if the device has an sd card or not). For example, I have a Nexus 7 and it works.
public void saveImageToExternalMemory(Bitmap bitmap, String name) throws IOException
{
File dir = new File(Environment.getExternalStorageDirectory().toString()+"/yourdirectoryname");
if (!dir.exists())
dir.mkdirs();
File file = new File(dir, name+ ".jpg"); //or the type you need
file.createNewFile();
OutputStream outStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
}
This method requires
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
in the manifest, and downloading requires:
<uses-permission android:name="android.permission.INTERNET"/>
So my latest app runs into this problem where it complains in the logcat that theres no room left on the device to save files but that is definitely not the case as I can close my app open the stock camera and take a picture. How has everybody else dealt with this problem.
Edit: The error occurs in this method
private void writeFile(Bitmap bmp, File f) {
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
bmp.compress(Bitmap.CompressFormat.PNG, 80, out);//<---error here
} catch (NullPointerException e) {
e.printStackTrace();
Log.w("nullpointerException on image error", "nullpointer");
} catch (FileNotFoundException e) {
Log.w("fileNotfoundException on image error", "filenotfound");
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
try { if (out != null ) out.close(); }
catch(Exception ex) {}
}
}
and this is the logcat report on this error:
java.io.IOException: no space left on device
at org.apache.harmony.luni.platform.OSFileSystem.write(Native Method)
at dalvik.system.BlockGuard$WrappedFileSystem.write(BlockGuard.java:171)
at java.io.FileOutputStream.write(FileOutputStream.java:300)
at android.graphics.Bitmap.nativeCompress(Native Method)
at data.ImageManager.writeFile(ImageManager.java:215)
at data.ImageManager.getBitmap(ImageManager.java:192)
at data.ImageManager.access$1(ImageManger.java:102)
at data.ImageManager$ImageQueueManager.run(ImageManager.java:290)
at java.lang.Thread.run(Thread.java:1019)
Edit: Heres how I though you create a directory on external memory
This is what Im using to create the place that I thought would be the sd card
String sdState = android.os.Environment.getExternalStorageState();
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
cacheDir = new File(sdDir,"data/gr");
}
else
cacheDir = context.getExternalCacheDir();
if(!cacheDir.exists())
cacheDir.mkdirs();
if(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
File adSdDir = android.os.Environment.getExternalStorageDirectory();
adCacheDir = new File(adSdDir,"data/ad");
}else
adCacheDir = context.getExternalCacheDir();
if(!adCacheDir.exists())
adCacheDir.mkdirs();
}
and then in the method that I look for or create the image to go into the directory:
private Bitmap getBitmap(ImgRequestObj ids) {
String url = null;
String filename = ids.objId.toString();
File f = null;
try{
if(ids.objName.equals("mark")){
url = graffMarksURL;
f = new File(cacheDir, filename);
}else if(ids.objName.equals("admark")){
url = adMarksURL;
f = new File(adCacheDir, filename);
}
// Is the bitmap in our cache?
Bitmap bitmap = BitmapFactory.decodeFile(f.getPath());
if(bitmap != null) return bitmap;
// Nope, have to download it
try {
BitmapFactory.Options bfOptions=new BitmapFactory.Options();
bfOptions.inDither=false; //Disable Dithering mode
bfOptions.inPurgeable=true; //Tell to gc that whether it needs free memory, the Bitmap can be cleared
bfOptions.inInputShareable=true; //Which kind of reference will be used to recover the Bitmap data after being clear, when it will be used in the future
DefaultHttpClient client;
HttpResponse response = null;
HttpParams params = null;// new Http parameters to be used for extra buffering room in VM
HttpPost post = null;
InputStream is = null;
BufferedInputStream bis = null;
Bitmap bmp = null;
ArrayList<NameValuePair> nvp1 = new ArrayList<NameValuePair>();
nvp1.add(new BasicNameValuePair("id", ids.objId.toString()));
// - martin passing id to php script select statement
client = new DefaultHttpClient();
try {
post = new HttpPost(url);
params = post.getParams();//Setting the new Http params to post
post.setEntity(new UrlEncodedFormEntity(nvp1));
try{
HttpConnectionParams.setSocketBufferSize(params, 8192);//Defining the new buffer size
response = client.execute(post);
}
catch(HttpResponseException e){
e.getCause();
}
//Capture response from query and prepare as input
HttpEntity entity = response.getEntity();
// move content to Input Stream
is = entity.getContent();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bis = new BufferedInputStream(is);
try{
bmp = BitmapFactory.decodeStream(bis, null, bfOptions);
}finally{}
if( is != null )
try {
is.close();
//response = null;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Log.w("inputstream of image closed", "for this image "+id.toString());
if( bis != null )
try {
//response = null;
bis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bitmap = bmp;
writeFile(bitmap, f);
try{
bmp = null;
}catch(NullPointerException e){
e.printStackTrace();
}
return bitmap;}
catch(Exception e){
e.printStackTrace();
}
return bitmap;
}catch(NullPointerException e){
e.printStackTrace();
}
return null;
}
you are actually using internal memory by using getCacheDir() in your else statement. However, if you want to store large data then its recommended to use getExternalCacheDir() because not all android phones have huge internal storage, but they do/may have bigger external storage.
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = context.getExternalCacheDir();
cacheDir = new File(sdDir,"data");
}
else
Log.e("storage", "SD card not found");
I ended up changing my code where I create my directories to the following:
String sdState = android.os.Environment.getExternalStorageState();
if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
File sdDir = android.os.Environment.getExternalStorageDirectory();
cacheDir = new File(sdDir,"data/gr");
}
else
cacheDir = context.getExternalFilesDir(sdState); <--changed
if(!cacheDir.exists())
cacheDir.mkdirs();
if(sdState.equals(android.os.Environment.MEDIA_MOUNTED)){
File adSdDir = android.os.Environment.getExternalStorageDirectory();
adCacheDir = new File(adSdDir,"data/ad");
}else
adCacheDir = context.getExternalFilesDir(sdState); <--changed
if(!adCacheDir.exists())
adCacheDir.mkdirs();
}
So far using this I am able to once again save images I take with the camera with all the images in my area download.
How can I save an images to the SD card that I retrieve from the image's URL?
First you must make sure your application has permission to write to the sdcard. To do this you need to add the uses permission write external storage in your applications manifest file. See Setting Android Permissions
Then you can you can download the URL to a file on the sdcard. A simple way is:
URL url = new URL ("file://some/path/anImage.png");
InputStream input = url.openStream();
try {
//The sdcard directory e.g. '/sdcard' can be used directly, or
//more safely abstracted with getExternalStorageDirectory()
File storagePath = Environment.getExternalStorageDirectory();
OutputStream output = new FileOutputStream (new File(storagePath,"myImage.png"));
try {
byte[] buffer = new byte[aReasonableSize];
int bytesRead = 0;
while ((bytesRead = input.read(buffer, 0, buffer.length)) >= 0) {
output.write(buffer, 0, bytesRead);
}
} finally {
output.close();
}
} finally {
input.close();
}
EDIT :
Put permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
An excellent example can be found in the latest post on Android developer's blog:
static Bitmap downloadBitmap(String url) {
final AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
inputStream = entity.getContent();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// Could provide a more explicit error message for IOException or
// IllegalStateException
getRequest.abort();
Log.w("ImageDownloader", "Error while retrieving bitmap from " + url,
e.toString());
} finally {
if (client != null) {
client.close();
}
}
return null;
}