my question is that i have a code that is suppose to receive a variable that contains a website that has an image so this variable changes every time i send a new link this code should go online and download the image and save it to the sd-card then i read it and display it
so my problem with the code is if im sending 2 links to it, it downloads 1 of the images and it always stores it with the second image name (example: im sending image1 and image2 the code downloads image1 two times and stores it as "image2") when i mount the sd-card and check the image directory there is only 1 image there named image2, i thought that doInBackground was causing the problem but im also using onPostExecute() so please if someone can help me i would be thankful for his help Note this is how i call it:
Note: i have no errors in the code // no red marks
This is all the code:
private void UpdateAds(String Bookinfo,TextView myText){
elhgsdatabase db = new elhgsdatabase(this);
if (Bookinfo != "didn't read titels"){
String debContent="";
String output ="";
int NUMBEROFFIELDS = 5;
String s = addressString;
long idx;
String [] buffer = new String[NUMBEROFFIELDS];
output = "";
int l = 0;
while (s.indexOf("[")>-1){
int fk = s.indexOf("[");
int fl = s.indexOf("]");
if(fk > -1){
buffer[l] = s.substring(fk+1, fl);
s = s.substring(fl+1);
l++;
if (l == NUMBEROFFIELDS){
//1. Query the database to check if the book exists
//---get all titles---
db.open();
Cursor c = db.getBookTitle (buffer[0]);
if (c.getCount()==1)
{ myText.setText("This Books Exist \n"); }
else if(c.getCount()==0)
{ String locLink;
locLink = getLocalLink(buffer[3], buffer[0]);
c.moveToFirst();
if (!locLink.equalsIgnoreCase("-1")){
idx= db.insertTitle(buffer[0], buffer[1], buffer[2], getDate(buffer[3]), buffer[4], locLink);
}
else { //there was a problem with retrieval-saving of the Book info locally
myText.setText("There was a problem with retrieval-saving of the Book info locally\n");
}
}//if(c.getCount()==0)
else{//The table has two Books with the same Name. Do something
myText.setText("The table has two Books with the same Name\n");
}
c.close();
l = 0;
}//if(l == NUMBEROFFIELDS)
} //if (fk>-1)
}//while
db.close();
} //of if(BookInfo...
else {
myText.setText("Nothing is Done\n");
}
}
//This method gets the local link field of the active book records
// it goes on the web, gets the content and stores it in a place
// and saves the path of that place in the database for that
//it returns -1 if something wrong happened during the process
public String getLocalLink(String image_URL, String BookName){
/** This is what we do with this method:
* Go online, according to the link, get the content, call the method to save, get the local link
* and return it
*/
setContentView(R.layout.main);
reviewImageLink = image_URL;
URL reviewImageURL;
String name = reviewImageLink.substring(reviewImageLink.lastIndexOf("/") + 1);
try {
reviewImageURL = new URL(reviewImageLink);
if (!hasExternalStoragePublicPicture(name)) {
isImage = false;
new DownloadImageTask().execute(reviewImageURL);
Log.v("log_tag", "if");
isImage = true;
File sdImageMainDirectory = new File(Environment.getExternalStorageDirectory(), getResources()
.getString(R.string.directory));
sdImageMainDirectory.mkdirs();
File file = new File(sdImageMainDirectory, name);
Log.v("log_tag", "Directory created");
}
} catch (MalformedURLException e) {
Log.v(TAG, e.toString());
}
return ("/sdcard/Hanud/"+BookName+".jpg");
}
private class DownloadImageTask extends AsyncTask<URL, Integer, Bitmap> {
// This class definition states that DownloadImageTask will take String
// parameters, publish Integer progress updates, and return a Bitmap
protected Bitmap doInBackground(URL... paths) {
URL url;
try {
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);}
else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length- downloaded);
}
else {read = is.read(imageData, downloaded, buffersize);}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = reviewImageLink.substring(reviewImageLink
.lastIndexOf("/") + 1);
if (result != null) {
hasExternalStoragePublicPicture(name);
saveToSDCard(result, name);
isImage = true;
} else {
isImage = false;
}
}
}
public void saveToSDCard(Bitmap bitmap, String name) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "
+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "
+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your Video "
+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String name) {
String filename = name;
ContentValues values = new ContentValues();
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
sdImageMainDirectory.mkdirs();
File outputFile = new File(sdImageMainDirectory, filename);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, filename);
values.put(MediaStore.MediaColumns.DATE_ADDED, System
.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
Uri uri = this.getContentResolver().insert(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
try {
OutputStream outStream = this.getContentResolver()
.openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.PNG, 95, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
File file = new File(sdImageMainDirectory, name);
if (file != null) {
file.delete();
}
return file.exists();
}
public void showAllBooks( )
{
final elhgsdatabase db = new elhgsdatabase(this);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
// Get new entry
db.open();
long currTime = System.currentTimeMillis();
String p_query = "select * from ads where timeFrom<=?";
Cursor c = db.rawQuery(p_query, new String[] { Long.toString(currTime)});
if (c.moveToFirst())
{
do {
DisplayTitle(c);
} while (c.moveToNext());
}
db.close();
}
}, 5000); // 5000 miliseconds
}
public long getDate(String s){
String[] formats = new String[] {
"yyyy-MM-dd HH:mm:ss"
};
SimpleDateFormat sdf=null;
String st;
for (String format : formats) {
sdf = new SimpleDateFormat(format, Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("EST"));//UTC or EST
st = new String(sdf.format(new Date(0)));
System.err.format(format, st);
}
Calendar c = Calendar.getInstance();
Date dt;
try {
dt = sdf.parse(s);
c.setTime(dt);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return c.getTimeInMillis() ;
}
public void DisplayTitle(final Cursor c)
{
Toast.makeText(this,
"Title: " + c.getString(0) + "\n" +
"isbn: " + c.getString(1) + "\n" +
"Publisher: " + c.getString(2) + "\n" +
"Year: " + c.getString(3) + "\n" +
"Image On Line: " + c.getString(4) + "\n" +
"Image On SD " + c.getString(5) + "\n" ,
Toast.LENGTH_LONG).show();
String imageInSD = c.getString(5);
Bitmap bitmap = BitmapFactory.decodeFile(imageInSD);
myImageView=(ImageView)findViewById(R.id.imageview1);
myImageView.setImageBitmap(bitmap);
}
----------
I'm pretty sure you're setting the second image name to the reviewImageLink (not sure if this is a class variable or what) variable. Instead, try passing both the URL and the String to the AsyncTask. Instead of passing a URL... pass in an Object... where the first one is the URL and the second is the name, and use that in the onPostExecute.
You don't show how ImageLink is set up. But as the filename is constructed from it, I guess your problem has almost nothing to do with the code you showed here.
Related
Should I be using something other than the MediaScannerConnection.scanFile method to refresh the gallery?
After saving a new jpg I run media scanner to refresh the gallery app like so
MediaScannerConnection.scanFile(this,
new String[] { fullname }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d("ExternalStorage", "#### Scanned " + path + ":");
Log.d("ExternalStorage", "#### -> uri=" + uri);
}
});
The output of the log shows the following correct output
#### Scanned /data/data/com.mypackage/files/skit_106_01.jpg:
#### -> uri=content://media/external/images/media/95
The gallery app shows no media available
This code has been working perfectly for some time now. It was only when I created an Android avd against version 4.4.2 for further testing that the problem has surfaced.
The code I have seems to be the recommended way of refreshing the gallery app according to Androids documentation so maybe this issue is related to the way I am saving the file, the code for which is as follows.
UPDATE
The code checks for external storage availability and will write to external storage and if external storage is not available it will write the file to internal storage.
private void doSave(String fname, boolean doShare) {
fname = "skit_"+mCurrentSkitId +
"_"+mSkitManager.getCurrentFrameCount(
mCurrentSkitId)+1;
Log.d(TAG, "#### doSave fName = " + fname + " Current skit id = " + mCurrentSkitId);
CharSequence text = getResources().getString(R.string.saved_as)
+ " " + fname;
try {
Bitmap b = mMainView.getSaveBitmap();
if (b == null) {
text = getResources().getString(R.string.save_fail_1);
;
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
return;
}
fname = FileUtils.replaceInvalidFileNameChars(fname);
String value = fname;
File folder = FileUtils.getWritableFolder(this);
/*
* String folder =
* Environment.getExternalStorageDirectory().toString() +
* "/Pictures"; try { folder =
* Environment.getExternalStoragePublicDirectory
* (Environment.DIRECTORY_PICTURES).toString(); } catch
* (NoSuchFieldError e) {
*
* }
*/
String ext = ".jpg";
if (mPrefs.getString("format", "JPG").equals("PNG"))
ext = ".png";
String fullname = folder.getAbsolutePath() + File.separator + value
+ ext;
Map<String, String> hm = new HashMap<String, String>();
hm.put("filename", fullname);
FileOutputStream fos;
if (folder == getFilesDir())
fos = openFileOutput(value + ext, Context.MODE_WORLD_WRITEABLE);
else {
File f2 = new File(fullname);
fos = new FileOutputStream(f2);
}
b.compress(CompressFormat.JPEG, 95, fos);
fos.close();
String[] str = new String[1];
str[0] = fullname;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO) {
MediaScannerConnection.scanFile(this,
new String[] { fullname }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.d("ExternalStorage", "#### Scanned " + path + ":");
Log.d("ExternalStorage", "#### -> uri=" + uri);
}
});
}
text = text + value + ext + " "
+ getResources().getString(R.string.saved_end);
;
mLastSaveName = value;
setDetailTitle();
mSkitManager.createFrame(mCurrentSkitId, fullname);
} catch (Exception e) {
Map<String, String> hm = new HashMap<String, String>();
hm.put("text", e.toString());
e.printStackTrace();
text = getResources().getString(R.string.save_fail_2)
+ e.toString();
} catch (Error e) {
Map<String, String> hm = new HashMap<String, String>();
hm.put("text", e.toString());
e.printStackTrace();
text = getResources().getString(R.string.save_fail_2)
+ e.toString();
}
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
The code that does the check for external storage availability looks like this
public static File getWritableFolder(Context context) {
File folder = context.getFilesDir();
if (externalStorageAvailable()) {
try {
folder = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
if (!folder.exists() || !folder.canWrite()) {
folder = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
}
if (!folder.exists() || !folder.canWrite()) {
folder = Environment.getExternalStorageDirectory();
}
} catch (Exception e) {
folder = Environment.getExternalStorageDirectory();
} catch (Error e) {
folder = Environment.getExternalStorageDirectory();
}
if (!folder.exists() || !folder.canWrite()) {
folder = context.getFilesDir();
}
}
return folder;
}
private static boolean externalStorageAvailable() {
boolean mExternalStorageAvailable;
boolean mExternalStorageWriteable;
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (state.equals(Environment.MEDIA_MOUNTED_READ_ONLY)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
return mExternalStorageAvailable && mExternalStorageWriteable;
}
If anyone is able to pick holes in any of the above that might help to solve this issue then that would be great.
i was having mixed results with MediaScannerConnection so i used the sendBroadcast method instead. I do not know if the sendBroadcast method is not standard/should not be used but it works for me.
public void galleryAddPic(File currentPhotoPath) {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(currentPhotoPath);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
Also regarding the MediaScannerConnection : https://stackoverflow.com/a/4825615/1497188
I am loading 10 Images from URL's that are stored in array . only last index url is loading and saving image in SD card . here is my code :
for(int j=0; j<List.size();j++)
{
reviewImageLink =List.get(j).get(TAG_Image).toString();
URL reviewImageURL;
String name = reviewImageLink;//.substring(reviewImageLink .lastIndexOf("/") + 1,reviewImageLink.length());
try {
reviewImageURL = new URL(reviewImageLink);
if (!hasExternalStoragePublicPicture(name)) {
isImage = false;
new DownloadImageTask().execute(reviewImageURL);
Log.v("log_tag", "if");
isImage = true;
File sdImageMainDirectory = new File(Environment.getExternalStorageDirectory(), getResources().getString(R.string.directory));
//if(!sdImageMainDirectory.exists()){
sdImageMainDirectory.mkdirs();
File file = new File(sdImageMainDirectory, name);
Log.v("log_tag", "Directory created");}
}
catch (MalformedURLException e) {
Log.v(TAG, e.toString()); }
}
}//try
catch (Exception e) {
e.printStackTrace();}
DownloaderTask:
class DownloadImageTask extends AsyncTask<URL, Integer, Bitmap> {
// This class definition states that DownloadImageTask will take String
// parameters, publish Integer progress updates, and return a Bitmap
protected Bitmap doInBackground(URL... paths) {
URL url;
try {
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = reviewImageLink.substring(reviewImageLink.lastIndexOf("/") + 1,reviewImageLink.length());
if (result != null) {
hasExternalStoragePublicPicture(name);
saveToSDCard(result, name);
isImage = true;
} else {
isImage = false;
}
}
}
public void saveToSDCard(Bitmap bitmap, String name) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your Video "+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String name)
{
String filename = name;
ContentValues values = new ContentValues();
File sdImageMainDirectory = new File(Environment.getExternalStorageDirectory(), getResources().getString(R.string.directory));
sdImageMainDirectory.mkdirs();
File outputFile = new File(sdImageMainDirectory, filename);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, filename);
values.put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "output.jpeg");
Uri uri = this.getContentResolver().insert(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,values);
//Uri result = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, image);
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
try
{
OutputStream outStream = this.getContentResolver().openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, outStream);
outStream.flush();
outStream.close();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File sdImageMainDirectory = new File(Environment.getExternalStorageDirectory(), getResources().getString(R.string.directory));
File file = new File(sdImageMainDirectory, name);
if (file != null)
{
file.delete();
}
return file.exists();
}
Pass the list to DownloadImageTask instead of URL then put a for loop in doInBackground,
I have a code that downloads an image from a website and saves it on the SD-card.
When I send 2 web addresses for some reason, it only downloads the first image 2 times and saves them both with the second image name so if there is image1 and image2 on the website the code will only download image1 two times and save it on SD-card as image2 can please someone tell me what am I doing wrong?
public String getLocalLink(String image_URL, String imageName){
/** This is what we do with this method:
* Go online, according to the link, get the content, call the method to save.
*/
ImageLink = image_URL;
URL ImageLinkURL;
try {
ImageLinkURL = new URL(ImageLink);
//URL url = new URL(strURL);
if (!hasExternalStoragePublicPicture(imageName)) {
isImage = false;
new DownloadImageTask().execute(ImageLinkURL);
Log.v("log_tag", "if");
isImage = true;
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources()
.getString(R.string.directory));
sdImageMainDirectory.mkdirs();
File file = new File(sdImageMainDirectory, imageName);
Log.v("log_tag", "Directory created");
}
} catch (MalformedURLException e) {
Log.v(TAG, e.toString());
}
return ("/sdcard/Hanud/”+imageName+".jpg");
}
private class DownloadImageTask extends AsyncTask<URL, Integer, Bitmap> {
// This class definition states that DownloadImageTask will take String
// parameters, publish Integer progress updates, and return a Bitmap
protected Bitmap doInBackground(URL... paths) {
URL url;
try {
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length
- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = ImageLink.substring(ImageLink
.lastIndexOf("/") + 1);
if (result != null) {
hasExternalStoragePublicPicture(name);
saveToSDCard(result, name);
isImage = true;
} else {
isImage = false;
}
}
}
public void saveToSDCard(Bitmap bitmap, String name) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "
+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "
+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your image "
+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String name) {
String filename = name;
ContentValues values = new ContentValues();
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
sdImageMainDirectory.mkdirs();
File outputFile = new File(sdImageMainDirectory, filename);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, filename);
values.put(MediaStore.MediaColumns.DATE_ADDED, System
.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
Uri uri = this.getContentResolver().insert(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
try {
OutputStream outStream = this.getContentResolver()
.openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.PNG, 95, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
File file = new File(sdImageMainDirectory, name);
if (file != null) {
file.delete();
}
return file.exists();
}
I have made a test on your case. My example is very simple, I put a button on the stage. When I click the button, I will start two asynctask to download two pictures. I am creating a folder in my sdcard. After testing, I can get two pictures in the folder.
After I check your code, I guess you have a class variable ImageLink, which is assigned twice when you call getLocalLink twice. So the image will be stored in your second image name file.
You can check my example, it works for your requirement. You can create multiple asyncTask to download multiple images. Please just check the AsyncTask part.
http://jmsliu.com/1929/android-progress-dialog-example.html
Merged with android download image and then read it from sd-card using sqlite.
hi to all i have this problem with my code and i tried every thing that i know of and i posted it on some forums and didnt get an answer im new to android and im still learning .....
my question is that i have a code that is suppose to receive a variable that contains a website that has an image so this variable changes every time i send a new link this code should go online and download the image and save it to the sd-card then i read it and display it
so my problem with the code is if im sending 2 links to it, it downloads 1 of the images and it always stores it with the second image name (example: im sending image1 and image2 the code downloads image1 two times and stores it as "image2") when i mount the sd-card and check the image directory there is only 1 image there named image2,
i thought that doInBackground was causing the problem but im also using onPostExecute()
so please if someone can help me i would be thankful for his help
Note this is how i call it:
locLink = getLocalLink(buffer[3], buffer[0]);
buffer[3] = image website (example:http://www.oceanwideimages.com/images/7049/large/24M2444-16-palm-fringed-tropical-island.jpg)
buffer[0] = new file name (example 1 as a string)
this is the code:
private class DownloadImageTask extends AsyncTask<URL, Integer, Bitmap> {
// This class definition states that DownloadImageTask will take String
// parameters, publish Integer progress updates, and return a Bitmap
protected Bitmap doInBackground(URL... paths) {
URL url;
try {
url = paths[0];
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length
- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
Log.e(TAG, "Exception: " + e.toString());
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = ImageLink.substring(ImageLink
.lastIndexOf("/") + 1);
if (result != null) {
hasExternalStoragePublicPicture(name);
saveToSDCard(result, name);
isImage = true;
} else {
isImage = false;
}
}
}
public void saveToSDCard(Bitmap bitmap, String name) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "
+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "
+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your image "
+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String name) {
String filename = name;
ContentValues values = new ContentValues();
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
sdImageMainDirectory.mkdirs();
File outputFile = new File(sdImageMainDirectory, filename);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, filename);
values.put(MediaStore.MediaColumns.DATE_ADDED, System
.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
Uri uri = this.getContentResolver().insert(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);
try {
OutputStream outStream = this.getContentResolver()
.openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.PNG, 95, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File sdImageMainDirectory = new File(Environment
.getExternalStorageDirectory(), getResources().getString(
R.string.directory));
File file = new File(sdImageMainDirectory, name);
if (file != null) {
file.delete();
}
return file.exists();
}
and this is how i read it:
String imageInSD = c.getString(5); //"/sdcard/Hanud/image1.jpg"or image2;
Bitmap bitmap = BitmapFactory.decodeFile(imageInSD);
myImageView=(ImageView)findViewById(R.id.imageview1);
myImageView.setImageURI(null);
myImageView.setImageBitmap(bitmap);
I'm developing an android app. Now I'm parsing bbcode to html and display it inside a textview, the textview is inside a custom listview. I use Html.ImageGetter() to display the images downloaded from AsyncTask.
It works great for a low number of pictures. But if the app is asked to download 40-50 pictures, 40-50 tasks are created and it becomes a mess. Each task opens a stream to download the images. After that it decodes the bytes into bitmaps, resize them, save them to the sdcard and recycles the bitmaps.
Now if the app is loading all this images at the same time it uses a huge amount of ram. I managed to make it pass 48 mb. There is a big gap between 16 and 48 :(. I searched on how to solve this. I downloaded AsyncTask code from google:
http://google.com/codesearch/p?hl=en&sa=N&cd=2&ct=rc#uX1GffpyOZk/core/java/android/os/AsyncTask.java&q=lang:java%20AsyncTask
And set the pool size to 3. But this didn't helped. I really can't figure out where I'm loosing ram. As soon as I put a big task queue my ram goes crazy. After a few images are received it gets worst. I don't think it is the images since I can get to 30 mb before any image is displayed. The app itself including the view, information and its service uses 13 mb, all the rest is leaked here.
Does the queue itself make big ram allocations? Or is the Html.ImageGetter() leaking a huge amount of memory somehow? Is there a better way to do this?
Here I load the images:
public void LoadImages(String source) {
myurl = null;
try {
myurl = new URL(source);
} catch (MalformedURLException e) {
e.printStackTrace();
}
new DownloadImageFromPost().execute(myurl);
}
private class DownloadImageFromPost extends AsyncTask<URL, Integer, Bitmap> {
#Override
protected Bitmap doInBackground(URL... params) {
URL url;
Log.d(TAG, "Starting new image download");
try {
url = params[0];
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
int length = connection.getContentLength();
InputStream is = (InputStream) url.getContent();
byte[] imageData = new byte[length];
int buffersize = (int) Math.ceil(length / (double) 100);
int downloaded = 0;
int read;
while (downloaded < length) {
if (length < buffersize) {
read = is.read(imageData, downloaded, length);
} else if ((length - downloaded) <= buffersize) {
read = is.read(imageData, downloaded, length
- downloaded);
} else {
read = is.read(imageData, downloaded, buffersize);
}
downloaded += read;
publishProgress((downloaded * 100) / length);
}
Bitmap bitmap = BitmapFactory.decodeByteArray(imageData, 0,
length);
if (bitmap != null) {
Log.i(TAG, "Bitmap created");
} else {
Log.i(TAG, "Bitmap not created");
}
is.close();
return bitmap;
} catch (MalformedURLException e) {
Log.e(TAG, "Malformed exception: " + e.toString());
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.toString());
} catch (Exception e) {
}
return null;
}
protected void onPostExecute(Bitmap result) {
String name = Environment.getExternalStorageDirectory() + "/tempthumbs/" + myurl.toString().hashCode() +".jpg";
String rname = Environment.getExternalStorageDirectory() + "/tempthumbs/" + myurl.toString().hashCode() +"-t.jpg";
try {
if (result != null) {
hasExternalStoragePublicPicture(name);
ImageManager manager = new ImageManager(context);
Bitmap rezised = manager.resizeBitmap(result, 300, 300);
saveToSDCard(result, name, myurl.toString().hashCode() +".jpg");
saveToSDCard(rezised, rname, myurl.toString().hashCode() +"-t.jpg");
result.recycle();
rezised.recycle();
} else {
}
} catch(NullPointerException e) {
}
Log.d(TAG, "Sending images loaded announcement");
Intent i = new Intent(IMAGE_LOADED);
i.putExtra("image", name);
i.putExtra("source", myurl.toString());
i.putExtra("class", true);
context.sendBroadcast(i);
}
}
private boolean hasExternalStoragePublicPicture(String name) {
File file = new File(name);
if (file != null) {
file.delete();
}
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return file.exists();
}
public void saveToSDCard(Bitmap bitmap, String name, String nam) {
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
mExternalStorageAvailable = mExternalStorageWriteable = true;
Log.v(TAG, "SD Card is available for read and write "
+ mExternalStorageAvailable + mExternalStorageWriteable);
saveFile(bitmap, name, nam);
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
Log.v(TAG, "SD Card is available for read "
+ mExternalStorageAvailable);
} else {
mExternalStorageAvailable = mExternalStorageWriteable = false;
Log.v(TAG, "Please insert a SD Card to save your Video "
+ mExternalStorageAvailable + mExternalStorageWriteable);
}
}
private void saveFile(Bitmap bitmap, String fullname, String nam) {
ContentValues values = new ContentValues();
File outputFile = new File(fullname);
values.put(MediaStore.MediaColumns.DATA, outputFile.toString());
values.put(MediaStore.MediaColumns.TITLE, nam);
values.put(MediaStore.MediaColumns.DATE_ADDED, System
.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpg");
Uri uri = context.getContentResolver().insert(
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
values);;
try {
OutputStream outStream = context.getContentResolver()
.openOutputStream(uri);
bitmap.compress(Bitmap.CompressFormat.JPEG, 95, outStream);
outStream.flush();
outStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();
}
And here i call Html.ImageGetter(), this is inside a list getView:
holder.content.setText(Html.fromHtml(
processor.preparePostText(posts.get(position).post_content),
new Html.ImageGetter() {
#Override public Drawable getDrawable(String source) {
Log.d("Forum Service", "image source: " + source);
if (imageSources.contains(source)) {
for (int x = 0; x < imageSources.size(); x++) {
if (source.equals(imageSources.get(x))) {
String tmp = oImages.get(x);
tmp = tmp.substring(0, tmp.length() - 4);
tmp = tmp + "-t.jpg";
Drawable d = Drawable.createFromPath(tmp);
try {
d.setBounds(0, 0, d.getIntrinsicWidth(),
d.getIntrinsicHeight());
} catch (NullPointerException e) {
}
Log.d("Forum Service", "Loaded image froms sdcard");
return d;
}
}
} else if (notLoadedImages.contains(source)) {
Log.d("Forum Service", "Waiting for image");
return null;
} else {
notLoadedImages.add(source);
LoadAllIcons loader = new LoadAllIcons(context);
loader.LoadImages(source);
Log.d("Forum Service", "Asked for image");
return null;
}
return null;
}
}, null));
Thanks!
Finally the problem was that all Tasks loaded at the same time. Therefor 40 images where allocated in ram while downloading. I managed to limit the amount of running tasks by doing this modifications on AsyncTask:
private static final int CORE_POOL_SIZE = 2;
private static final int MAXIMUM_POOL_SIZE = 2;
private static final int KEEP_ALIVE = 1;
private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(100);
Mateo there goes your answer http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html
And you're done!