Fresco add Bitmap to Cache programmatically - android

I am uploading an image to my server and once uploaded my server responds with the new URI for it (can be the same URL as the old one), I want to remove the old cached image and insert the new one for the new URI.
I try to accomplish this by doing:
// Retrofit2 onResponse
String newImageUri = response.body().getUri();
String oldImageUri = Preferences.getUser().getImageUrl();
// Remove old image from cache
Fresco.getImagePipeline().evictFromCache(Uri.parse(oldImageUri));
Fresco.getImagePipeline().evictFromDiskCache(Uri.parse(oldImageUri));
Fresco.getImagePipeline().evictFromMemoryCache(Uri.parse(oldImageUri));
Fresco.getImagePipelineFactory().getMainFileCache().remove(new SimpleCacheKey(oldImageUri));
// Insert new image at new URI
try {
Fresco.getImagePipelineFactory().getMainFileCache().insert(new SimpleCacheKey(newImageUri), new WriterCallback() {
#Override
public void write(OutputStream os) throws IOException {
os.write(imageData); // byte[] or the new Bitmap
}
});
}
catch (Exception e) {
e.printStackTrace();
}
uriProfileImage.setImageURI(newImageUri);
There are no exceptions but I still only see the old image.

I solved it, it was an error with the Uri format for the new Uri...

Uri uri = Uri.parse("http://frescolib.org/static/fresco-logo.png");
Fresco.getImagePipelineFactory().getMainDiskStorageCache().remove(new CacheKey(uri.toString()));
Fresco.getImagePipelineFactory().getSmallImageDiskStorageCache().remove(new CacheKey(uri.toString()));

Related

FileNotFound Exception while converting Firebase uri into bitmap?

i'm developing an app in which i'm retrieving a profile image from firebase but while conversion into bitmap format ,it's getting FileNotFoundException so any solution for this ?
databaseReference.child(uid).child("Profile_image").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String url= (String) dataSnapshot.getValue();
Uri uri;
try {
uri = Uri.parse(url);
InputStream inputStream =getContentResolver().openInputStream(uri); //this line
Bitmap bitamp = BitmapFactory.decodeStream(inputStream);
String bitmap=saveToInternalStorage(bitamp);
loadImageFromStorage(bitmap);
}catch (NullPointerException e){
} catch (FileNotFoundException e) {
Toast.makeText(MainActivity.this, "File not Found", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This is meant to be a comment, but I don't have a high enough reputation to comment yet:
If your String url is the http url of Firebase storage, then Uri.parse(url) is not going to get you the correct Uri. From my experience, you can only be confident that Uri.parse(String stringUri) will return the correct Uri if the string came from Uri's toString() method.
Receiving an invalid Uri would cause getContentResolver().openInputStream(uri) crash as you say it is.
With that being said, if you're storing the Uri as a String in your database, then you need to get that String value and use Uri.parse(String stringUri) on it as opposed to calling that method on the http url.
i think you have to use Picasso direcltly
Picasso.get().load(uri).into(target);

Display an image without saving it

My app can download an image from a raspberry. it works fine. This is the code
public void downloadFile() {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect("******");
ftpClient.login("****","*****");
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
String remoteFile1;
File downloadFile1 = new File(filePath);
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
if (success) {
System.out.println("File #1 has been downloaded successfully.");
} else {
System.out.println("Error in downloading file !");
}
boolean logout = ftpClient.logout();
if (logout) {
System.out.println("Connection close...");
}
} catch (IOException ex) {
System.out.println("Error: " + ex.getMessage());
ex.printStackTrace();
} finally {
try {
ftpClient.disconnect();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And then I can display it so the user of my app can see it. For the image loading, Im using this code and it works too.
private void loadImage(String imagePath) {
Uri imageUri;
String fullImagePath;
Drawable image;
ImageView imageDisplay;
imageUri = Uri.parse(imagePath);
fullImagePath = imageUri.getPath();
image = Drawable.createFromPath(fullImagePath);
imageDisplay=(ImageView) findViewById(R.id.imageDisplay);
imageDisplay.setImageDrawable(image);
}
Now I want to display the image without downloading it in my gallery. But I can't figure out how to do this.
Can someone help me please.
You cannot show an image without download it. Actually when you see something "remotely", you are downloading it.
If you mean that the image is too large and you don't want to download, but want a mechanism for the user can view it. One possible solution is make a thumbnail (reduced image) in server side and show that "preview" to the user. Then if the user want to download it to the gallery you could get the original image.
If you want to display an image without downloading it, it has to be uploaded in a image hosting site or alike so you will just use the link instead of the whole FTP Client.
Basically, you are using a code that is intended for saving an image. And the one you are using for loading the images fetches data from the Drawable. So you are in the wrong path.

Android camera2: java.lang.IllegalStateException: maxImages (1) has already been acquired, call #close before acquiring more

Hello having trouble to fix this issue.
I already have a imageReader.close called inside the ImageAvailable callback but still having the error:
java.lang.IllegalStateException: maxImages (1) has already been acquired, call #close before acquiring more.
Code I have is here:
private ImageReader.OnImageAvailableListener imageAvailableListener = new ImageReader.OnImageAvailableListener()
{
#Override
public void onImageAvailable(ImageReader reader) {
Image img = mReader.acquireLatestImage();
mReader.close();
}
};
ps. I also use the argument reader as well but not seem to solve the problem
Ok I have solved my problem. I need to close the img object not the ImageReader.
private ImageReader.OnImageAvailableListener imageAvailableListener = new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
String status = Environment.getExternalStorageState();
if (!status.equals(Environment.MEDIA_MOUNTED)) {
Toast.makeText(getApplicationContext(), "your SD card is not available", Toast.LENGTH_SHORT).show();
return;
}
Image image = reader.acquireNextImage();
ByteBuffer buffer = image.getPlanes()[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
image.close();//after you use the image's content ,you can close it
String filePath = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/";
String picturePath = System.currentTimeMillis() + ".jpg";
imgFile = new File(filePath, picturePath);
Uri uri = Uri.fromFile(imgFile);
try {//Store to folder
FileOutputStream fileOutputStream = new FileOutputStream(imgFile);
fileOutputStream.write(data);
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
startEditPictureActivity(uri, imgFile);
}
};
close() needs to be called on the Image object that acquireLatestImage() returns.
So, going from the OP's implementation of onImageAvailable() in his sample, just adding .close() after the acquireLatestImage() should do the trick.
Like so:
public void onImageAvailable(ImageReader reader) {
Image image = reader.acquireLatestImage().close(); // Note the added `close()` call.
}
I should also add that the image will no longer be usable after you call close() on it (see docs).
So the solution I've mentioned above will get you rid off the exception OP mentioned, but you also won't be able to do anything with the image. This is obviously easy to fix by first doing whatever you want with the image and only then calling close() on it.

How to share image that is downloaded and cached with Volley?

In my app I download images from server using Volley and its ImageLoader (with BitmapLruCache). I want to create a share option, researched a little bit, and found that share intent can only share localy stored images. First question, is this right?
Second, if that is right, what should I do? Should I download image again and save it to local storage? Or put it in MediaStore? Or I can pull image from cache and share cached version? What are the best practices?
Any suggestion is welcome, or code snippet.
What I did is made another request for getting the image, and added an ImageListener which provides ImageContainer containing bitmap.
MyApplication.getImageLoader(activity).get(imageURL, new ImageListener() {
#Override
public void onErrorResponse(VolleyError error) {}
#Override
public void onResponse(ImageContainer response, boolean isImmediate) {
Bitmap mBitmap = response.getBitmap();
ContentValues image = new ContentValues();
image.put(Media.MIME_TYPE, "image/jpg");
Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, image);
try {
OutputStream out = getContentResolver().openOutputStream(uri);
boolean success = mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.close();
if (!success) {
} else {
imageUri = uri;
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
// Create the share Intent
Intent shareIntent = ShareCompat.IntentBuilder.from(activity).setType("image/jpg").setText(shareText).getIntent();
shareIntent.putExtra(Intent.EXTRA_STREAM, imageUri);
mShareActionProvider.setShareIntent(shareIntent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
As image is already downloaded and cached (using BitmapLRU cache and ImageLoader), this new request gives me bitmap from cache so no new network data is made.

Download image from new Google+ (plus) Photos Application

Recently Google added the Photos app for Google+ (plus) and it shows up when you launch an Intent to choose an image. However, if I select an image from Google+ Photos and try to use it in my application none of my current logic is able to return a usable URI or URL to actually get an image that I can download and manipulate. I'm currently using the "common" methods to try to manipulate the URI that can be found here on Stack Overflow and elsewhere. I can provide code if needed, but at this point I think it's kind of irrelevant since it works well for everything else except this new app. Any ideas on how to get a usable image?
The URI looks something like the following:
content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh5.googleusercontent.com%<a bunch of letters and numbers here>
The MediaColumns.DATA info always returns null and the MediaColumns.DISPLAY_NAME always returns image.jpg no matter what I select from the Google Photos app. If I try to paste everything from https to the end in my browser, nothing comes up. Not sure how to get usable info from this.
When receiving the data intent, you should use the contentResolver to get the photos.
Here's what you should do:
String url = intent.getData().toString();
Bitmap bitmap = null;
InputStream is = null;
if (url.startsWith("content://com.google.android.apps.photos.content")){
is = getContentResolver().openInputStream(Uri.parse(url));
bitmap = BitmapFactory.decodeStream(is);
}
I did faced issues selecting images from new Google Photos app. I was able to resolve it by below code.
It works for me, basically what i did is i am checking if there is any authority is there or not in content URI. If it is there i am writing to temporary file and returning path of that temporary image. You can skip compression part while writing to temporary image
public static String getImageUrlWithAuthority(Context context, Uri uri) {
InputStream is = null;
if (uri.getAuthority() != null) {
try {
is = context.getContentResolver().openInputStream(uri);
Bitmap bmp = BitmapFactory.decodeStream(is);
return writeToTempImageAndGetPathUri(context, bmp).toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public static Uri writeToTempImageAndGetPathUri(Context inContext, Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(inContext.getContentResolver(), inImage, "Title", null);
return Uri.parse(path);
}
P.S. : I have answered a similar question here
You have to use projection in order to get ImageColumns.DATA (or MediaColumns.DATA):
private String getRealPathFromURI(Uri contentURI) {
// Projection makes ContentResolver to get needed columns only
String[] medData = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentURI, medData, null, null, null);
// this is how you can simply get Bitmap
Bitmap bmp = MediaStore.Images.Media.getBitmap(getContentResolver(), contentURI);
// After using projection cursor will have needed DATA column
cursor.moveToFirst();
final int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}

Categories

Resources