I am using Picasso in my Android application to load images from URL. These images are displayed in some ListView. When user clicks on some item in this ListView, I need to create a sharing Intent with selected image.
I create sharing intent with this code:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(localPath));
shareIntent.putExtra(Intent.EXTRA_TEXT, mUrl);
shareIntent.setType("image/jpg");
startActivity(Intent.createChooser(shareIntent, getString(R.string.label_share)));
In code above, there is a local variable localPath. This variable has to contain path to image. I suppose that Picasso has some cache, where downloaded images are stored. Is there any way how can I retrieve the path of selected image?
UPDATE: Partial solution
Finally, I found a solution which works for me. But I do not know, if this is a correct solution or if better solution exists.
I created a class which implements com.squareup.picasso.Target interface and in method onBitmapLoaded(Bitmap bitmap, LoadedFrom from) I provided this implementation:
#Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
mImageView.setImageBitmap(bitmap);
mImageUri = getBitmapUri(bitmap, mName));
}
private Uri getBitmapUri(Bitmap bitmap, String title) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(mContext.getContentResolver(), bitmap, title, null);
return Uri.parse(path);
}
After that, I have mImageUri which I can pass to sharing intent. Maybe this part of code will be useful for someone.
But I don't know if better solution exist. In my solution I have to store Bitmap on disk, but maybe there is a same image on disk already, because Picasso loaded it. And also, I do not know if I have to delete image from MediaStore when I do not need it anymore.
Related
Scenario: I am using MessagingStyle notification in a chat application. For image messages, I am using setData function to create image notification in conversation style.
public Message setData(String dataMimeType, Uri dataUri)
This method required dataUri but I have URL of image so I have created a bitmap from image url and then create a uri from batmap using function below.
public static Uri getImageUri(Context applicationContext, Bitmap photo) {
try {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(applicationContext.getContentResolver(), photo, "IMG_" + Calendar.getInstance().getTime(), null);
if (path == null) {
return null;
}
return Uri.parse(path);
} catch (SecurityException ex) {
ex.printStackTrace();
return null;
}
}
Problem: Now the problem is that when user open image gallery, these notifications images are showing because I used mediastore to create URI. I don’t want these image to show in gallery.
Limitation: I am also saving that URI in case If I have to generate this notification again. So I can’t delete that image immediately to avoid showing in gallery.
Question: Is there any way to save image privately in external storage where gallery don’t have access. But notification manager can access?
Is there any way to create Uri form url without downloading it? I have tried this but it also not working
url = new URL(messageNotification.getAttachmentImage());
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
imageUri= Uri.parse(uri.toString());
Another workaround to show image in notification by using Messagings style like conversation as in WhatsApp
Download your image directly from url to a file in getExternalFilesDir(). Dont use an intermediate bitmap.
The MediaStore has no access to your getExternalFilesDir() so Gallery apps dont know about your files there.
The user can still use the Files app to see those images.
Then use a FileProvider to serve your files. Construct an uri with FileProvider.getUriForFile().
store your bitmap as File in some app-specific directory (not gallery) and make URI from file path. be aware of Scoped Storage and pick proper place for storing Bitmaps - check out in HERE, probably getFilesDir()/getCacheDir() method will be the best option
also worth trying may be this line:
Uri uri = Uri.parse(messageNotification.getAttachmentImage());
(encodedImageUrl = URLEncoder.encode(imageUrl, "utf-8") may be needed)
Good morning, I'm using this Github library: https://github.com/burhanrashid52/PhotoEditor as photo editor. I have a GalleryFragment in which user choose image from his gallery, the I pass correctly the image to the EditImageActivity where user can apply sticker, filters, ecc. and then clicking on a button, user can pass the edited image to InfoActivity, where he can add other info and publish the image.
The problem is that when user edits an image and pass it to InfoActivity it is shown the original image without changes, and also when he publishes it, the image saved is the original, not the modified.
I'm trying to use Bitmap to do that:
This is the code of EditImageActivity where I try to send the edited image in a intent to InfoActivity:
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Bitmap bmp =((BitmapDrawable)mPhotoEditorView.getSource().getDrawable()).getBitmap();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
Intent intent = new Intent(EditImageActivity.this, InfoActivity.class);
intent.putExtra("imm", byteArray);
startActivity(intent);
And this is the piece of code of InfoActivity, where I try to retrieve the intent with the edited image from EditImageActivity, to show it in a ImageView:
byte[] byteArray = getIntent().getByteArrayExtra("imm");
assert byteArray != null;
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
immagine.setImageBitmap(bmp);
So it works when user doesn't edit image, while when he edits image, it shows the original.
I think that the problem is in this code (the code that I use in EditImageActivity to get a bitmap of the edited image), because it passes the original image instead of the modified image:
Bitmap bmp =((BitmapDrawable)mPhotoEditorView.getSource().getDrawable()).getBitmap();
Can someone help me please?
Yes, it seems that the problem is when you fetch the edited image from your PhotoEditorView. If you see the documentation, to retrieve this image, is necessary to implement the next approach:
PhotoEditor.saveAsFile(filePath, new PhotoEditor.OnSaveListener() {
#Override
public void onSuccess(#NonNull String imagePath) {
Log.e("PhotoEditor","Image Saved Successfully");
}
#Override
public void onFailure(#NonNull Exception exception) {
Log.e("PhotoEditor","Failed to save Image");
}
});
So the library needs a file to save it and if is success, then returns the path file, with the path file you needs to create the Bitmap object.
I have a custom camera app with two activities. The first activity (MainActivity) allows the user to take a photo with a custom camera. I would like to open this photo in the second activity (DrawActivity) so that the user can eventually draw on it. My MainActivity works great, the camera opens, snaps and saves the image to the phones external storage. I am having trouble with the DrawActivity opening the photo. I am passing what I believe to be the Uri of the image from my MainActivity to my DrawActivivty with the following code:
Intent myIntent = new Intent(MainActivity.this, DrawActivity.class);
myIntent.putExtra("mybitmap",values.toString());
startActivity(myIntent);
Where values are defined (before I create the above intent):
FileOutputStream fout = new FileOutputStream(imageFile);
fout.write(ostream.toByteArray());
fout.close();
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATE_TAKEN,
System.currentTimeMillis());
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath());
MainActivity.this.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
I can not get the DrawActivity to display the photo. I set up a Toast message just to see what my DrawActivity was receiving, and I got this message. I set up the toast code with this:
Bundle extras = getIntent().getExtras();
String imageuri = extras.getString("mybitmap");
Toast.makeText(this, imageuri, Toast.LENGTH_LONG).show();
and try to pass it to my image view with:
ImageView iv = (ImageView) findViewById(R.id.imageDisplay);
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(imageuri));
iv.setImageBitmap(bitmap);
iv.setVisibility(View.VISIBLE);
When I pull up the photo properties in the stock photo app on my phone the image path is this. Am I passing the wrong information? Too much information? Am I parsing the passed information incorrectly?
You are passing the values which is not the imageUri, and you can get the bitmap from the image path. So, pass the file path only from your MainActivity to DrawActivity. After passing the path, you can get the Bitmap by the following code.
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
mImageView.setImageBitmap(bitmap);
Rob i suggest you this kind of User friendly architecture. Because going to another activity is ok but if you can do everything in the same activity like this is good approach as i know.
I've found a lot of answers for questions like mine but they doesn't make sense for me. Let me explain.
I have a ImageButton that let the user take a picture and display it on interface. When i try to get image URI, it returns null:
Uri uri = data.getData();
I've made some searches on internet and found solutions like:
#Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
try {
if (resultCode == Activity.RESULT_OK) {
updateProfilePicure = Boolean.TRUE;
switch(requestCode){
case 0:
Bundle extras = data.getExtras();
Object xx = data.getData();
Bitmap imageBitmap = (Bitmap) extras.get("data");
Uri tempUri = getImageUri(imageBitmap);
imageView.setImageBitmap(imageBitmap);
break;
default: break;
}
}
} catch(Exception e){
e.printStackTrace();
}
}
public Uri getImageUri(Bitmap inImage) {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
String path = MediaStore.Images.Media.insertImage(
ApplicationContext.getInstance().getContext().getContentResolver(), inImage,
"Title", null);
return Uri.parse(path);
}
For me, it doesn't make sense because when the call goes to method onActivityResult(), the picture is already saved on DCIM folder and don't have any reason to save it again. So why should i use it?
Is possible to find another way to retrieve the URI from captured image?
Thank's in advance.
the picture is already saved on DCIM folder and don't have any reason to save it again.
Not necessarily. Quoting the documentation for ACTION_IMAGE_CAPTURE:
The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field.
(the "extra field" here is an extra keyed as data)
The code snippet that you pasted is retrieving the data extra, and so the image is not stored anywhere.
Is possible to find another way to retrieve the URI from captured image?
You already have the code for this, in your first code snippet -- if you are specifying the Uri as EXTRA_OUTPUT in your ACTION_IMAGE_CAPTURE request, you will get a Uri back to the image that was taken in the Intent handed to onActivityResult().
I'm trying to share from my app to Hyves using share intent. If I have hyves app installed and share from gallery it switch to hyves app, and upload image correctly to hyves, so it should work.
Problem is, I can't find it documented how should proper intent for hyves work, but I assume that gallery uploads images only, so I have this:
Bitmap image = BitmapFactory.decodeFile(MyGlobals.INSTANCE.activeSetting.f_image_path);
It's line of code where I pull my "active" or "selected" image within my app. At this point image is saved to SD Card, so I might read uri instead of decoding file, but I want it this way to have same approach for both hyves and facebook.
Then I call:
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", image);
startActivityForResult(hyvesIntent, 666);
First of all, I'm not sure if setPackage is OK to be used here, but I'm checking if this package exist to enable / disable share, and this is package name that is visible.
I need Activity result to then notify that Image is shared or not.
What happens here it starts the Hyves app, but I get full white screen, and then the Hyves app times out.
So, Can I use Bitmap in intent, and is it OK to setPackage or should I setClass?
Tnx
Maybe you can not put the bitmap directly in the intent.
First convert the bitmap into a byte array than send another side and convert into bitmap
//convert bitmap to bytearray
public static byte[] getBitmapAsByteArray(Bitmap bitmap, boolean type) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (type) {
bitmap.compress(CompressFormat.PNG, 0, outputStream);
} else {
bitmap.compress(CompressFormat.JPEG, 0, outputStream);
}
return outputStream.toByteArray();
}
//convert bitmap to bytearray
public static Bitmap getBitmap(byte[] imgByte){
Bitmap bm = BitmapFactory.decodeByteArray(imgByte, 0, imgByte.length);
return bm;
}
//than intent
Intent hyvesIntent = new Intent(Intent.ACTION_SEND);
hyvesIntent.setPackage("com.hyves.android.application");
hyvesIntent.setType("image/jpeg");
hyvesIntent.putExtra("image", getBitmapAsByteArray(image,true));
startActivityForResult(hyvesIntent, 666);
I hope that is right way to put image