I am trying to download and save all the images from a url array but the problem is only last image gets saved with the name img7.jpg. I don't understand where the problem is? I want all the images to be downloaded and saved with the name img1.jpg, img2.jpg, img3.jpg and so on. Where in the code do I need to make changes?
public class MainActivity extends ActionBarActivity {
ImageView imageView;
public static String[] stringArray = {"http://upload.wikimedia.org/wikipedia/en/9/90/Broken_Boundaries_of_Rohtas_Fort.jpg",
"http://upload.wikimedia.org/wikipedia/en/a/a0/Rohtas_View_4.jpg",
"http://upload.wikimedia.org/wikipedia/en/0/07/Rohtas_Fort_Gate.jpg",
"http://upload.wikimedia.org/wikipedia/en/7/78/Rohtas_Village_View_2nd.jpg",
"http://www.worldheritagesite.org/picx/w586.jpg",
"http://wpcontent.answcdn.com/wikipedia/en/thumb/6/68/Rani_Mahal_Rohtas_Fort_2.jpg/930px-Rani_Mahal_Rohtas_Fort_2.jpg",
"http://photos.wikimapia.org/p/00/01/75/75/69_big.jpg"};
int i = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView)findViewById(R.id.imageView1);
for (String url : stringArray){
Picasso.with(this)
.load(url)
.into(target);
i++;
}
}
private Target target = new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
File file = new File(Environment.getExternalStorageDirectory().getPath() +"/img"+i+".jpg");
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 75, ostream);
ostream.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
if (placeHolderDrawable != null) {
}
}
};
}
In your case Picasso loads your images asynchronously. What means, that
Picasso.with(this)
.load(url)
.into(target);
isn't waiting until your picture is downloaded and stored to disk. So, your counter i is always (stringArray.length - 1), if it comes to saving the image.
Do something like this:
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int index = 0;
for (String url : stringArray) {
Picasso.with(this)
.load(url)
.into(new IndexTarget(index));
index++;
}
}
class IndexTarget implements Target {
private final int mIndex;
public IndexTarget(int index){
this.mIndex = index;
}
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
File file = new File(Environment.getExternalStorageDirectory().getPath() +"/img"+mIndex+".jpg");
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 75, ostream);
ostream.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
}
Related
I'm trying to use Glide to save my image from a View...
Glide.with(mContext).asBitmap().load(zoneSetupViewPaint.getDrawingCache())
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(#NonNull final Bitmap resource, #Nullable Transition<? super Bitmap> transition) {
Log.d("COLOR", " hereee " );
fixBitmap = resource;
}
}
);
Then I do this:
fixBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
I wonder if it's possible at all. This one isn't working, I tried converting my View to a Bitmap but I lose quality. I also tried using a Drawable with Glide but that just doesn't work.
To download and save an image using Glide use the code below:
Glide.with(this)
.as(byte[].class)
.load(photoPath)
.apply(new RequestOptions()
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
.format(DecodeFormat.PREFER_ARGB_8888))
.into(new SimpleTarget<byte[]>() {
#Override
public void onResourceReady(#NonNull byte[] resource, #Nullable Transition<? super byte[]> transition) {
new SaveTask(new SaveTask.SimpleListener() {
#Override
public void onPostExecute(File savedFile) {
if (getActivity() == null) return;
CustomToast.showSuccess(getActivity(), R.string.image_saved_in_gallery);
}
}, "jpg").execute(resource);
}
});
SaveTask.java
public class SaveTask extends AsyncTask<byte[], Void, File> {
private Listener mListener;
private String mExtension;
public SaveTask(Listener listener, String extension) {
mListener = listener;
mExtension = extension != null && !extension.isEmpty() ? extension : "jpg";
}
#Override
protected void onPreExecute() {
if (mListener != null) mListener.onPreExecute();
}
#Override
protected File doInBackground(byte[]... params) {
File sdcard = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File file = new File(String.format("%s%s%s%sIMG_%s.%s", sdcard, File.separator, MainApplication.getAppContext().getString(R.string.app_name), File.separator, new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(new Date()), mExtension));
File dir = file.getParentFile();
try {
if (!dir.mkdirs() && (!dir.exists() || !dir.isDirectory())) {
throw new IOException("Cannot ensure parent directory for file " + file);
}
BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(file));
s.write(params[0]);
s.flush();
s.close();
return file;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(File savedFile) {
if (mListener != null) mListener.onPostExecute(savedFile);
if (savedFile == null) return;
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(savedFile));
MainApplication.getAppContext().sendBroadcast(intent);
}
public interface Listener {
void onPreExecute();
void onPostExecute(File savedFile);
}
public static class SimpleListener implements Listener {
public void onPreExecute() {}
public void onPostExecute(File savedFile) {}
}
}
Feel free to change the file saving path as you want.
I'm trying to download multiple pictures using picasso. here's my code:
for(int i=1; i <=20; i++){
String url = img_url + i + "/profile.jpg";
String img_dir = img_dir + i;
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
}
Url of the site looks like this:
site.com/img/equipment/1/profile.jpg,
site.com/img/equipment/2/profile.jpg,
site.com/img/equipment/3/profile.jpg
and so on ...
i tried
Picasso.with(this).load(url).into(picassoImageTarget(getApplicationContext(),img_dir, img_name));
without the for loop and it is working. images are not download when i place it inside the loop.
here's my Target
private Target picassoImageTarget(Context context, final String imageDir, final String imageName) {
Log.d("picassoImageTarget", " picassoImageTarget");
ContextWrapper cw = new ContextWrapper(context);
final File directory = cw.getDir(imageDir, Context.MODE_PRIVATE); // path to /data/data/yourapp/app_imageDir
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
new Thread(new Runnable() {
#Override
public void run() {
final File myImageFile = new File(directory, imageName); // Create image file
FileOutputStream fos = null;
try {
fos = new FileOutputStream(myImageFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Log.i("image", "image saved to >>>" + myImageFile.getAbsolutePath());
}
}).start();
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
if (placeHolderDrawable != null) {}
}
};
}
please help. thanks.
Targets are held in WeakReferences.
You need to hold a reference to the Targets you want to keep to prevent them from being garbage collected.
Maybe your code would look something like:
final class MyLoader {
final ArrayList<Target> targets = new ArrayList<>(20);
void load(...) {
for(...) {
Target target = picassoImageTarget(...);
targets.add(target);
picasso.load(...).into(target); // TODO: Maybe remove from list when complete.
}
}
}
I have a list of urls for images. I want to use Picasso to download these images to local storage on Android. I am using following method (using custom target). However I don't see all the images getting downloaded.
public void downloadAllMapImages(List<ProjectMapModel> models) {
List<Target> targetList=Lists.newArrayList();
for(ProjectMapModel model:models){
for (Map.Entry<Integer, String> entry : model.getMaps().entrySet()) {
String url=entry.getValue();
Target target=mapImageTarget(model.getProjectId(),entry.getKey());
targetList.add(target);
Picasso.with(this)
.load(url)
.into(target);
}
}
if(!isImageDownloadSuccessful)
showDownloadMapImageDataError();
//whatever images were downloaded, we need to write them to database
listDetailPresenter.onImageDownloadingSuccessful(projectMapOutputModels);
}
private Target mapImageTarget(final int projectId, final int mapType) {
//create the file name
final File file = new File(this.getExternalFilesDir(null) + File.separator + projectId+"_"+ mapType + ".jpg");
final String filePath=file.getAbsolutePath();
return new Target() {
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
// loading of the bitmap was a success
// write the image to file
new Thread(new Runnable() {
#Override
public void run() {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
} catch (IOException e) {
Log.e(DashboardActivity.class.getName(), e.toString());
isImageDownloadSuccessful=false;
} finally {
try {
outputStream.close();
Log.i(DashboardActivity.class.getName(), "image saved");
} catch (IOException e) {
Log.e(DashboardActivity.class.getName(), e.toString());
isImageDownloadSuccessful=false;
}
}
projectMapOutputModels.add(new ProjectMapOutputData(projectId,filePath,mapType));
Log.i("image", "image saved to >>>" + filePath);
}
}).start();
//notify presenter that this image has been download and the path can be sent to presenter
}
#Override
public void onBitmapFailed(Drawable errorDrawable) {
// loading of the bitmap failed
// TODO show error message toast. dont write file path to database. continue with next image
isImageDownloadSuccessful=false;
}
#Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
};
}
Am I missing anything? Any help on this is really appreciated!
I am using Picasso for my image handling and use it to download images from a backend server and save to the local device. I use Target to save the image
Picasso.with(context)
.load(url)
.into(target);
Since the target code gets a bitmap, I have to use bitmap.compress() to write the image to local disk and I use JPEF format with quality of 100 assuming this will preserve the original quality.
Reading this it seems like this might not be what I want. In one case, the image on the backend was 90kb and the image that was written was 370kb. The original image can be generated using an arbitrary quality value. What is the easiest way to save the image using Picasso without the size/quality changing?
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom arg1) {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
FileOutputStream out = null;
try {
out = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void info) {
}
}.execute();
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
};
UPDATE: more elegant solution here: https://github.com/square/picasso/issues/1025#issuecomment-102661647
Solved the problem using this solution.
In my PagerAdapter's instantiateItem() method, I run an AsyncTask that will download the image, save it to a file and then call Picasso with that image file.
PagerAdapter instantiateItem():
RemoteImageToImageViewAsyncTask remoteImageToImageViewAsyncTask =
new RemoteImageToImageViewAsyncTask(imageView, url, imagePath);
remoteImageToImageViewAsyncTask.execute();
RemoteImageToImageViewAsyncTask
public class RemoteImageToImageViewAsyncTask extends AsyncTask<Void, Void, Void> {
ImageView imageView;
String url;
File output;
public RemoteImageToImageViewAsyncTask(ImageView imageView, String url, File output) {
this.imageView = imageView;
this.url = url;
this.output = output;
}
#Override
protected Void doInBackground(Void... params) {
// Downloads the image from url to output
ImageDownloader.download(url, output);
return null;
}
#Override
protected void onPostExecute(Void params) {
Picasso.with(context)
.load(output)
.into(imageView);
}
}
I'm trying to show my news in a custom ListView. Each news is included of some images and I want to
1.download images from server
2.save in local storage
3.save path of images into SQLite
4.show images in ListView using my custom adapter.
I just have problem with steps 1 & 2. I can get news from server and show them in my ListView
and show images from cache by add below code in my adapter:
Picasso.with(context).load(image[position]).into(iv);
By using Picasso.with(context).load(image[position]).into(target) , just I can save one
image in storage.
Please suggest me your idea ...
UPDATE: When I use below code, just one image (last index of my image array) being saved!
How can I save all images in array with this code?!
#Override
protected void onPostExecute(Void result) {
SaveImages();
pDialog.dismiss();
super.onPostExecute(result);
}
String fileName = null;
public void SaveImages() {
for(int i = 0; i < image.length; i++) {
Picasso.with(this).load(image[i]).into(target);
fileName = "image-" + i + ".jpg";
}
}
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
}
#Override
public void onBitmapLoaded(Bitmap bitmap, LoadedFrom arg1) {
File file = new File(Environment.getExternalStorageDirectory().getPath() +"/" + fileName);
try {
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 75, ostream);
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable arg0) {
}
};
Try to put Target target definition before call to Picasso.with(this).load(image[i]).into(target);
P.S. Using the following code and I saved images very well. Thanks, anyway.
My Code:
final String fileName = mDataset.get(i).getAid() + ".jpg";
Target target = new Target() {
#Override
public void onPrepareLoad(Drawable arg0) {
return;
}
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom arg1) {
try {
File file = null;
// judge "imgs/.nomedia"'s existance to judge whether path available
if(LightCache.testFileExist(GlobalConfig.getFirstStoragePath()
+ "imgs" + File.separator +".nomedia") == true)
file = new File(GlobalConfig.getFirstStoragePath()
+ "imgs" + File.separator + fileName);
else file = new File(GlobalConfig.getSecondStoragePath()
+ "imgs" + File.separator + fileName);
file.createNewFile();
FileOutputStream ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, ostream);
ostream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onBitmapFailed(Drawable arg0) {
return;
}
};
Picasso.with(GlobalConfig.getContext())
.load(Wenku8API.getCoverURL(mDataset.get(i).getAid()))
.into(target);
Custom target for storing photo in phone gallery.
public class TargetPhoneGallery implements Target
{
private final WeakReference<ContentResolver> resolver;
private final String name;
private final String desc;
public TargetPhoneGallery(ContentResolver r, String name, String desc)
{
this.resolver = new WeakReference<ContentResolver>(r);
this.name = name;
this.desc = desc;
}
#Override
public void onPrepareLoad (Drawable arg0)
{
}
#Override
public void onBitmapLoaded (Bitmap bitmap, LoadedFrom arg1)
{
ContentResolver r = resolver.get();
if (r != null)
{
MediaStore.Images.Media.insertImage(r, bitmap, name, desc);
}
}
#Override
public void onBitmapFailed (Drawable arg0)
{
}
}
Picasso.with(context).load(image[position]).into(new TargetPhoneGallery(view.getContentResolver(), "image name", "image desc"));
although this post is old, it seems the question hasn't been answered yet.
Reading your code, it appears the call you make to picasso could be asynchronous.
You should definitely check that, as if it is the case, you are starting image.length tasks, changing the filename at each new task, leading all tasks to complete and save to the last filename that was set.
To solve this, you should override Target constructor and add a filename parameter so it's ready when the task ends, in your onBitmapLoaded listener.