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"/>
Related
I am Trying to Get a Picture from Firebase Storage from the DownloadURl inside my Firebase Database ..
Firebase Structure
Users
|_9304809841
|__IMAGE :"https://firebasestorage.googleapis.com/v0/b/zumi-
60a8f.appspot.com/o/Profile_Image%2Fcropped-122662379.jpg?
alt=media&token=c8f3e9ee-637d-4bdd-9a76-a186ecd07e37"
I am Using the Below Code To Get the Image from the URL ..
final DefaultHttpClient client = new DefaultHttpClient();
final HttpGet getRequest = new HttpGet(URL); //FETCHING THE URL FROM FIREBASE DATABASE..
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
//Toast.makeText(MainActivity.this, "Error in HttpSTATUS", Toast.LENGTH_SHORT).show();
//return;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
//inputStream = (InputStream) new URL(params[0].toString()).getContent();
byte[] image = new byte[inputStream.available()];
inputStream.read(image);
values.put("image", image); //inserting the Values into ContentVAlues
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
if (values != null) {
Cdb.insert("current_Luser", null, values); // INSERTING INTO SQLite DB
}
}
else
{
//Toast.makeText(MainActivity.this, "Entity is Null", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// You Could provide a more explicit error message for IOException
getRequest.abort();
Log.d("",e.toString());
// Toast.makeText(MainActivity.this, "Error "+e.toString(), Toast.LENGTH_SHORT).show();
}
return null;
}
}
I am Trying to Retrieve the Image using
Cursor c=Cdb.rawQuery("select email_phone,status,Dname,image from current_Luser",null);
Toast.makeText(this, "No of record : "+c.getCount(), Toast.LENGTH_SHORT).show();
if(c.moveToNext()) {
if (c.getCount() > 0) {
email.setText(c.getString(0).replace("#zumi.com", "").toString());
name.setText(c.getString(2));
status.setText(c.getString(1));
byte[] img = c.getBlob(3);
Bitmap bmp = BitmapFactory.decodeByteArray(img, 0, img.length);
showpotos.setImageBitmap(bmp);
}
The Data is Inserted as [B#d0ca6a3 Value into SQLite DB..But It Does Not Show up in the Image View....
Pls Help..
The use of available() in this statement may be causing problems:
byte[] image = new byte[inputStream.available()]
The documentation for available() says:
Note that while some implementations of InputStream will return the
total number of bytes in the stream, many will not. It is never
correct to use the return value of this method to allocate a buffer
intended to hold all data in this stream
Hi guys i started developing an android application and i am bit confused on which is the best way to accomplish it
Application Flow
when the activity starts it fetches data from the database(sqlite), the database returns a list of data ,this list of data contains text and url for image.
so now i want that as soon as activity start the listview will be populated with the text data and the images.
The images will be first searched locally if not present then the images will be fetched from url after the fetching is completed the image will be added to its respective view and also stored on the device
These images once downloaded should remain on device until the app is uninstalled
Issues
as soon we start the activity the list view gets populated with the data from local database but the images takes time to download
so i tried asynchronous image loader but the problem was if the activity was started and the device isn't connect to net the image wont show but after that if we connect to internet these images wont show
is their any easier way to handle the images so that if i need to delete these images in future i can. If some one can provide refrence to any project or available libraries to handle these task .Thnx in advance
I don't the way you are loading the images to list but i suggest you to use picasso a library to load images :
for url:
Picasso.with(context).load("http://i.imgur.com/DvpvklR.png").into(imageView);
for Resource :
Picasso.with(context).load(R.drawable.landing_screen).into(imageView1);
loading from file:
Picasso.with(context).load(new File(...)).into(imageView2);
more details are here: http://square.github.io/picasso/
To download image and save to disk:
new ImageDownloader().execute(downloadUrl);
private class ImageDownloader extends AsyncTask {
#Override
protected String doInBackground(String... param) {
// TODO Auto-generated method stub
return downloadBitmap(param[0]);
}
#Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
}
#Override
protected void onPostExecute(String result) {
Log.i("Async-Example", "onPostExecute Called");
Bitmap myBitmap = BitmapFactory.decodeFile(result));
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
simpleWaitDialog.dismiss();
}
private String downloadBitmap(String url) {
// initilize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
//forming a HttoGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
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 {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap that android understands
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return SaveBitmapToDir(bitmap);
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// You Could provide a more explicit error message for IOException
getRequest.abort();
Log.e("ImageDownloader", "Something went wrong while" +
" retrieving bitmap from " + url + e.toString());
}
return null;
}
private String SaveBitmapToDir(Bitmap bmp)
{
FileOutputStream out = null;
File file = null;
try {
SimpleDateFormat s = new SimpleDateFormat("ddMMyyyy_hhmmss");
String dateTime = s.format(new Date());
String path = Environment.getExternalStorageDirectory().toString();
OutputStream fOut = null;
file = new File(path, "MyApp_"+dateTime+".jpg");
out = new FileOutputStream(file);
bmp.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
To store key-value pair i suggest you to use android's shared preference to store the image name and the location on the disk.
Here is a tutorial for Shared Preference
To store values in shared preferences:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("image name","image path oon disk");
editor.apply();
To retrieve values from shared preferences:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String imagePath = preferences.getString("image name","");
if(!imagePath.equalsIgnoreCase(""))
{
//your action here with the image path
}
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.
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;
}