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.
Related
I'm reading the s3 android guide and im really confused on how to download my files.
They provide this code:
TransferObserver observer = transferUtility.download(
MY_BUCKET, /* The bucket to download from */
OBJECT_KEY, /* The key for the object to download */
MY_FILE /* The file to download the object to */
);
So what is MY_FILE? am i suppose to make a local empty file object and supply it into that transferUtility download function and it fills that empty file to the one download?
And, when i finish getting the file, (particularly for images) how do i upload that file into an imageView using glide or Picasso?
I am not sure how to use the TransferObserver object.
Hope someone can provide a working example, please!
cheers!
Although I am quite late answering this question. Hope this helps someone who is stuck in this problem.
You don't need to make the bucket public. You can directly show the image via Glide. Here is my repo to load image from amazon s3 bucket via Glide.
https://github.com/jontyankit/Glide-Amazon-Image-Load
You need to override GlideModule and register our component
public class CustomGlideModule implements GlideModule {
#Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
}
#Override
public void registerComponents(Context context, Glide glide) {
glide.register(ImageModel.class, InputStream.class, new ImageLoader.Factory());
}
}
Make custom ModelLoader class. This class fetches the image on the basis of model described above instead of URL
public class ImageLoader implements ModelLoader<ImageModel, InputStream> {
private final ModelCache<ImageModel, ImageModel> mModelCache;
public ImageLoader(ModelCache<ImageModel, ImageModel> mModelCache) {
this.mModelCache = mModelCache;
}
#Override
public DataFetcher<InputStream> getResourceFetcher(ImageModel model, int width, int height) {
ImageModel imageModel = model;
if (mModelCache != null) {
imageModel = mModelCache.get(model, 0, 0);
if (imageModel == null) {
mModelCache.put(model, 0, 0, model);
imageModel = model;
}
}
return new ImageFetcher(imageModel);
}
public static class Factory implements ModelLoaderFactory<ImageModel, InputStream> {
private final ModelCache<ImageModel, ImageModel> mModelCache = new ModelCache<>(500);
#Override
public ModelLoader<ImageModel, InputStream> build(Context context, GenericLoaderFactory factories) {
return new ImageLoader(mModelCache);
}
#Override
public void teardown() {
}
}
}
And at last make custom class DataFetcher. public InputStream loadData(Priority priority) is the method which will download image from Amazon.
public class ImageFetcher implements DataFetcher<InputStream> {
private final ImageModel imageModel;
private InputStream mInputStream;
boolean downloadComplete = false;
int transferId = 0;
public ImageFetcher(ImageModel imageModel) {
this.imageModel = imageModel;
}
#Override
public InputStream loadData(Priority priority) throws Exception {
return fetchStream(imageModel);
}
private InputStream fetchStream(final ImageModel imageModel) {
TransferUtility transferUtility = AmazonClient.getClient().getTransferUtility();
TransferObserver bolomessages = transferUtility.download(imageModel.getBucketName(), imageModel.getId(), new File(imageModel.getLocalPath()));
transferId = bolomessages.getId();
bolomessages.setTransferListener(new TransferListener() {
#Override
public void onStateChanged(int id, TransferState state) {
Log.wtf("AWSS3", "onStateChanged = " + state);
if (state == TransferState.COMPLETED) {
File initialFile = new File(imageModel.getLocalPath());
try {
mInputStream = new FileInputStream(initialFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
downloadComplete = true;
}
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal) {
}
#Override
public void onError(int id, Exception ex) {
// do something
Log.wtf("AWSS3", "onError");
ex.printStackTrace();
downloadComplete = true;
}
});
while (!downloadComplete){}
return mInputStream;
}
#Override
public void cleanup() {
if (mInputStream != null) {
try {
mInputStream.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
mInputStream = null;
}
}
}
#Override
public String getId() {
return imageModel.getId();
}
#Override
public void cancel() {
AmazonClient.getClient().getTransferUtility().cancel(transferId);
}
}
So I am able to use Glide or picasso to load the image using the url of the image in the s3 bucket. But you have to make the bucket public.
Here is how you upload the image:
Glide.with(getActivity().getBaseContext()).load("IMAGE URL FROM S3").centerCrop().into(cardImage);
And thanks to #KNeerajLal here is how you can make your bucket public.
Here:
making bucket public
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.
}
}
}
Hello StackOverflowers,
I developed project which is using Volley for communicating with REST web API. I use complex image loading process.
I want to load user's facebook profile picture and sometimes I want it first to get storage cached image and sometimes I want it to be always from internet.
The problem is that image url from facebook is always the same. This is why I made a basic check if image file size differs from the cached one.
I was using Volley's ImageLoader and it's cache implementation. Then I found it complex to do it with ImageLoader so I choose to use Picasso but it doesn't show cached image.
I know that for Picasso cache to work I need a custom "Downloader" and I know I can do it with OkHttp but my project is already using Volley for all REST calls.
So is it possible to use Volley as downloader for Picasso and its image cache structure?
Here is how I managed to fix the first issue and only the caching flow is the problem now:
public class PerfectImageLoader {
private static final String TAG = PerfectImageLoader.class.getSimpleName();
private Context mContext;
private SharedPreferences mSharedPreferences;
public PerfectImageLoader(Context context)
throws NullPointerException {
if (context == null) {
throw new NullPointerException("Context cannot be null");
}
mContext = context;
mSharedPreferences = context.getSharedPreferences(
context.getPackageName(), Context.MODE_PRIVATE);
}
public void getImage(final String imageUrl, final ImageView imageView) {
getImage(imageUrl, imageView, false);
}
public void getImage(final String imageUrl, final ImageView imageView,
final boolean isAwlaysFromInternet)
throws NullPointerException {
if (imageView == null) {
throw new NullPointerException("OnImageFromCacheListener cannot be null");
}
if (TextUtils.isEmpty(imageUrl)) {
throw new NullPointerException("image url cannot be null");
}
if (!isAwlaysFromInternet) {
loadCachedImage(imageUrl, imageView, null);
}
calculateFileSize(imageUrl, new OnFileSizeCheck() {
#Override
public void ready(final int networkFileSize) {
int cachedImageSize = mSharedPreferences
.getInt(imageUrl, 0);
TLog.v(TAG, "networkFileSize:" + networkFileSize);
TLog.v(TAG, "cachedImageSize:" + cachedImageSize);
if (cachedImageSize != networkFileSize || cachedImageSize == 0) {
TLog.v(TAG, "cachedImageSize != networkFileSize");
final Callback callback = new Callback() {
#Override
public void onSuccess() {
TLog.v(TAG, "downloaded");
mSharedPreferences.edit()
.putInt(imageUrl, networkFileSize).apply();
}
#Override
public void onError() {
TLog.v(TAG, "error");
if (isAwlaysFromInternet) {
mSharedPreferences.edit()
.remove(imageUrl).apply();
imageView.setImageBitmap(null);
}
}
};
if (isAwlaysFromInternet) {
TLog.v(TAG, "MemoryPolicy.NO_CACHE");
Picasso.with(mContext).load(imageUrl).memoryPolicy(MemoryPolicy.NO_CACHE)
.into(imageView, callback);
} else {
Picasso.with(mContext).load(imageUrl).into(imageView, callback);
}
} else {
TLog.v(TAG, "cachedImageSize == networkFileSize");
loadCachedImage(imageUrl, imageView, new Callback() {
#Override
public void onSuccess() {
}
#Override
public void onError() {
Picasso.with(mContext).load(imageUrl).into(imageView);
}
});
}
}
});
}
private void loadCachedImage(final String imageUrl, final ImageView imageView,
Callback callback) {
if (callback != null) {
Picasso.with(mContext)
.load(imageUrl)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView, callback);
} else {
Picasso.with(mContext)
.load(imageUrl)
.networkPolicy(NetworkPolicy.OFFLINE)
.into(imageView);
}
}
public static void calculateFileSize(String url, final OnFileSizeCheck fileSizeCallbacks)
throws NullPointerException {
if (fileSizeCallbacks != null && !TextUtils.isEmpty(url)) {
new AsyncTask<String, Void, Integer>() {
#Override
protected Integer doInBackground(String... params) {
Integer fileSize = null;
try {
URL urlObj = new URL(params[0]);
URLConnection urlConnection = urlObj.openConnection();
urlConnection.connect();
fileSize = urlConnection.getContentLength();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return fileSize;
}
#Override
protected void onPostExecute(Integer fileSize) {
super.onPostExecute(fileSize);
if (fileSizeCallbacks != null) {
fileSizeCallbacks.ready(fileSize);
}
}
}.execute(url);
} else {
if (fileSizeCallbacks == null) {
throw new NullPointerException("file size callbacks parameter is null");
}
if (url == null) {
throw new NullPointerException("url parameter is null");
} else if (TextUtils.isEmpty(url)) {
throw new NullPointerException("url parameter is empty");
}
}
}
}
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) {
}
}
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.