Is there a way of looping through the default image gallery on an android device?
In my app I have managed to pass a selected picture from the default gallery to an imageView by this code:
public void onImageGalleryClicked(View v){
//Invoke image gallery using implicit intent
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
//Where is the image gallery stored
File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
//Get path of the image gallery as string
CurrentPicturePath = pictureDirectory.getPath();
//Get the URI-representation of the image directory path
Uri data = Uri.parse(CurrentPicturePath);
//Set the data and type to get all the images
photoPickerIntent.setDataAndType(data, "image/*");
//Invoke activity and wait for result
startActivityForResult(photoPickerIntent, IMAGE_GALLERY_REQUEST);
}
And showing the picture in in a viewcontroller by:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK){
if(requestCode == IMAGE_GALLERY_REQUEST){
//Address of the image on SD-card
Uri imageUri = data.getData();
//Declare a stream to read the image from SD-card
InputStream inputStream;
try {
inputStream = getContentResolver().openInputStream(imageUri);
//Get a bitmap
Bitmap image = BitmapFactory.decodeStream(inputStream);
imgPicture.setImageBitmap(image);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Unable to open image!", Toast.LENGTH_LONG).show();
}
}
}
}
Now I want to have a button in my app that finds the next picture in the default gallery.
I'd like a way to loop through the gallery to find my current picture (by path/name!?) to be able to select the next one (or previous)
There are billions of Android devices, spread across thousands of device models. These will have hundreds of different "default image gallery" apps, as those are usually written by device manufacturers. The user does not have to use any of those apps to satisfy your ACTION_PICK request.
There is no requirement of ACTION_PICK implementations to supply you with "next" or "forward" information.
Related
I am currently working on an activity that will let the user select an image from the gallery, and then put that image's URI into an SQLite database.
I have another activity where I take that URI and display it on an ImageView. I have this working perfectly on Lollipop and older. But anything newer it crashes when I pull up the activity that displays the image.
Here is the LOGCAT line of the crash:
Caused by: java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.MediaContentProvider from ProcessRecord{8193e94 13574:jeremy.com.wineofmine/u0a97} (pid=13574, uid=10097) that is not exported from uid 10044
This makes it seem like a permissions thing, but I am requesting the WRITE_EXTERNAL_STORAGE and READ_EXTERNAL STORAGE in the manifest, as well as requesting those permissions on run-time on the activity where it displays the image.
And here is the exact line where it's crashing (this is in the activity where it displays the image:)
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageURI);
And this is imageURI:
imageURI = Uri.parse(cursor.getString(cursor.getColumnIndexOrThrow(WineContract.WineEntry.COLUMN_WINE_IMAGE)));
//This code returns this: content://com.google.android.apps.photos.contentprovider/-1/1/content%3A%2F%2Fmedia%2Fexternal%2Fimages%2Fmedia%2F62/ACTUAL/860591124
Here is the code to the relevant bits.
This is the intent to open up the gallery:
Intent intentGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intentGallery, SELECT_IMAGE);
And this is the onActivityResult method. The main goal of this method is to set the imageThumbail ImageView as the thumbnail, and also to set "photoURI" as the selected image's URI.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//This is if they choose an image from the gallery
if (requestCode == SELECT_IMAGE && resultCode == RESULT_OK) {
if (requestCode == SELECT_IMAGE) {
// Get the url from data
Uri selectedImageUri = data.getData();
if (null != selectedImageUri) {
// Get the path from the Uri
String path = getPathFromURI(selectedImageUri);
Log.i("ADDACTIVITY", "Image Path : " + path);
bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImageUri);
} catch (IOException e) {
e.printStackTrace();
}
bitmapThumbnail = ThumbnailUtils.extractThumbnail(bitmap,175,175);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmapThumbnail.compress(Bitmap.CompressFormat.JPEG, 100, stream);
byteArray = stream.toByteArray();
// Set the image in ImageView
imageThumbnail.setImageBitmap(bitmapThumbnail);
//Setting photoURI (which gets put into the database) as the gallery's image URI
photoURI = data.getData();
}
}
}
}
Any pointers to what I could be doing wrong, would be great.
Having some trouble figuring out how to set the imageview to the picture I just captured with the camera. Would be a bonus if there was some way to display multiple captured pictures at once. Whenever I click the button, a previous image captured appears, then the camera opens, which isn't right. Id like the imageview to be blank, I click the button, take a picture, then that picture is displayed in the imageview. I believe that this line is out of place, but i'm unsure as to how/ where to move it. mimageView.setImageURI(outputFileUri);
public class cameraclass extends Activity {
int TAKE_PHOTO_CODE = 0;
public static int count = 0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
final ImageView mimageView;
mimageView = (ImageView) this.findViewById(R.id.image_from_camera);
// Here, we are making a folder named picFolder to store
// pics taken by the camera using this application.
final String dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/picFolder/";
File newdir = new File(dir);
newdir.mkdirs();
Button capture = (Button) findViewById(R.id.take_image_from_camera);
capture.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Here, the counter will be incremented each time, and the
// picture taken by camera will be stored as 1.jpg,2.jpg
// and likewise.
count++;
String file = dir+count+".jpg";
File newfile = new File(file);
try {
newfile.createNewFile();
}
catch (IOException e)
{
}
//Uri outputFileUri = Uri.fromFile(newfile);
Uri outputFileUri = FileProvider.getUriForFile(getApplicationContext() , "com.example.android.com220finalapp.provider", newfile);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, TAKE_PHOTO_CODE);
mimageView.setImageURI(outputFileUri);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK) {
Log.d("CameraDemo", "Pic saved");
}
}
}
I believe that this line is out of place, but i'm unsure as to how/ where to move it.
startActivityForResult() is asynchronous. Your photo will not have been taken by the time that method returns. You need to load the image into the ImageView in onActivityResult(), if you got a RESULT_OK response.
However, while setImageURI() may work, it has never been an especially good idea, as it will freeze your app for a while as it loads the photo. There are many image loading libraries for Android that will handle loading your ImageView asynchronously.
I want to be able to send a picture from one user to another in a messaging app like on whatsApp, but I am not sure how to do that. I am using android and parse as my DB. I tried googling and nothing seems to help, I am new on Android development. I would prefer to use it as I do with my texts , since when sending messages between users I am using parse as my database. Can someone please assist, I am able to select the image from galery and load it in an image view but I am not sure how to send it as I would with text. The code that should be under when the button "send" is clicked.
Below is the code that I have. Please have a look at it. I have been trying everything that I can think of but I am not getting anywhere.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
//Everything Okay
if (requestCode == LOAD_IMAGE_RESULTS) {
Uri pickedImage = data.getData();
InputStream inputStream;
try {
inputStream = getContentResolver().openInputStream(pickedImage);
Bitmap selectImage = BitmapFactory.decodeStream(inputStream);
sendPicture.setImageBitmap(selectImage);
selectImage = ((BitmapDrawable) sendPicture.getDrawable()).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
selectImage.compress(Bitmap.CompressFormat.PNG, 5, stream);
byte[] imageRec = stream.toByteArray();
final ParseObject imgMsgToBeSent = new ParseObject("SentImages");
final ParseFile fileRenamed;
//create parse file
fileRenamed = new ParseFile("SentImage.png", imageRec);
imgMsgToBeSent.put("receipientId", MessagingActivity.recipientId.toString());
imgMsgToBeSent.put("senderId", MessagingActivity.currentUserId.toString());
imgMsgToBeSent.put("imageReceived", fileRenamed);
sendImgBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (v.getId() == R.id.sendImageBtn) {
messageService.sendMessage(MessagingActivity.recipientId.toString(), fileRenamed.toString());
finish();
}
}
});
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Unable to load image",
Toast.LENGTH_LONG).show();
}
}
}
}
For Sharing Image after selected from Gallery ##
First get the image path and than send it via intent like this:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri Imageuri = Uri.fromFile(new File(image));
shareIntent.setType("image/");
shareIntent.putExtra(Intent.EXTRA_STREAM, Imageuri);
startActivity(Intent.createChooser(shareIntent, "ShareWia"));
for sharing image and text both just add one more settype and use put extra with text like this:
Intent shareIntent = new Intent(Intent.ACTION_SEND);
Uri Imageuri = Uri.fromFile(new File(image));
shareIntent.setType("image/");
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, text);
shareIntent.putExtra(Intent.EXTRA_STREAM, Imageuri);
startActivity(Intent.createChooser(shareIntent, "ShareWia"));
Sinch does not support attachments in IM
I take a picture in Android via
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, CAMERA_REQUEST);
and show / save it via
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
ImageView theImage = (ImageView) findViewById(R.id.preview);
theImage.setImageBitmap(photo);
// try to save its
try {
File testFile = new File(Environment.getExternalStorageDirectory(), "test.png");
testFile.createNewFile();
FileOutputStream out = new FileOutputStream(testFile);
photo.compress(Bitmap.CompressFormat.PNG, 90, out);
} catch (Exception e) {
e.printStackTrace();
}
This works fine, however the quality of the image is very bad. I do not know why, since I take the picture with 8 mega pixels.
Is there a way to do this without requiring the camera manually?
Take a closer look at this post: there are two ways to capture an image in Android. First one is designed for taking small and lightweight pictures - that's the approach you use, and the second one captures full-sized pictures and writes them to storage. The post describes both ways of accomplishing this task.
I am attempting to launch the built-in camera to take a picture, a picture that will have a name specified by the activity launching the camera. (code below)
When the camera returns, onActivityResult() goes straight to resultCode == Activity.RESULT_CANCELED. Any explanation for this and solutions would be greatly appreciated.
The camera indeed does take the image, I can see it in my sdcard with a file viewer, but its name is the stock one from the camera. How can I get the name of this taken image to be the one supplied by the activity?
Camera intent code
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File image = new File("Team image.jpg");
camera.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
camera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
camera.putExtra(MediaStore.Images.Media.TITLE, "Team image");
startActivityForResult(camera, PICTURE_RESULT);
activityresult code
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == PICTURE_RESULT){
if(resultCode == Activity.RESULT_OK) {
if(data!=null){
Bitmap image = BitmapFactory.decodeFile(data.getExtras().get(MediaStore.Images.Media.TITLE).toString());
grid.add(image);
images.addItem(image);
}
if(data==null){
Toast.makeText(Team_Viewer.this, "no data.", Toast.LENGTH_SHORT).show();
}
}
else if(resultCode == Activity.RESULT_CANCELED) {
Toast.makeText(Team_Viewer.this, "Picture could not be taken.", Toast.LENGTH_SHORT).show();
}
}
}
Have you mark the launch mode of your activity as "singleInstance"?
That may cause your first problem.
My camera goes normal when I remove the "singleInstance".
The two issues are likely related, having to do with the way you are creating the file reference that passes to the camera. If you want your image file to save to the SD Card, you need to create a file reference that includes a full-path to that location, not just a filename. For example, this code would save the image file on the SD card root:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File image = new File(Environment.getExternalStorageDirectory(),"TeamImage.jpg");
camera.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(image));
startActivityForResult(camera, PICTURE_RESULT);
I also changed your filename to not include a space; only because I'm not certain that the Camera application won't blow up on that piece also. Since the Camera is getting confused trying to open and write to your file location, that is likely why you always return with RESULT_CANCELED. You don't need the WRITE_EXTERNAL_STORAGE permission here, since the Camera app is doing the SD Card access.
One more note: I don't believe other MediaStore extras can be passed with this Intent. Typically, if you want metadata to be attached to your image, you have to insert the Uri reference with that metadata into the MediaStore ContentProvider prior to saving the image to disk.
Hope that helps!
Not sure what's wrong with your code, here's what works for me:
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
and
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case CAMERA_PIC_REQUEST:
Bitmap b = (Bitmap) data.getExtras().get("data");
if (b != null) {
updateThumbnail(b);
if (mBitmap != b) {
b.recycle();
}
}
break;
}
}