Regardless of whether I use an emulated camera or use my webcam as the emulated device's camera, I cannot save photos. My code sets up a new file to save the photo, the camera activity pops up, but after I take the picture, hitting the 'save' or 'accept picture' button doesn't do anything. The only way I can return to my app's activity it by hitting cancel. This code works when I run it on my Galaxy S3, but not an emulated Nexus device. When I set up the device in AVD Manager, I always make sure to enable to set both cameras to either emulated or webcam0, whichever I am using, and I make sure to have an SD card (even though I save to internal memory) and internal storage sufficient for photos. In my manifest, I declare android.permission.INTERNET, android.permission.WRITE_EXTERNAL_STORAGE, and android.permission.CAMERA. Any ideas?
Here's my code where I start the camera intent:
private void dispatchTakePictureIntent(int position) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile(position);
} catch (IOException ex) {
Log.v("photo", "photoFile failed.");
}
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
Log.v("tag", "photoFile was equal to null.");
}
}
}
Found a solution! The emulated camera wasn't returning because I used a bad directory (selected in createImageFile above) for saving the File. I started using the directory returned by Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) and that solved the problem.
Related
I am currently working on small part of my graduation work. I have to test out, how you can get the location of the user without the location permission.
One way is that the user gets asked to take a picture and when the Camera application has the permission to get the location, you can read out the EXIF-Data from the picture which was taken by the user.
I tested it out on multiple real devices (2x Android 9, 1x Android 6, 1x Android 7.1) and it works on these devices.
But if I use the emulator (The camera has the location permisson, location service is turned on, camera is tagging the location to the image) the Android EXIF interface can't read out any EXIF data.
If I take manually a photo with the Camera app and look at the details of the photo in the gallery, the location is saved.
Does anyone have experience with this issue?
EDIT:
The most important code:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
ex.printStackTrace();
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.readoutexifwithoutpermissions",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private void readOutImageData() {
Log.i(TAG, currentPhotoPath);
try {
ExifInterface exif = new ExifInterface(currentPhotoPath);
File file = new File(currentPhotoPath);
Log.i(TAG, "size of file: " + file.length());
Log.i(TAG, "reading out something..." + exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
this.txtLatitude.setText(exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE));
this.txtLongitude.setText(exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE));
} catch (IOException e) {
e.printStackTrace();
}
}
private File createImageFile() throws IOException {
String imageFileName = "JPEG_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName,
".jpg",
storageDir
);
currentPhotoPath = image.getAbsolutePath();
return image;
}
SOLUTION:
I don't know why, but when you are using the Camera via Intent no additional information gets stored. If you are installing another camera app like Open Camera, it is working. (Only happens in the emulator)
The location is most certainly saved as meta info in the media store and not in exif header of jpg.
Download jpg to pc and inspect there exif to see.
You can query the media store for the location too. You dont need the location permission but need another special permission then. Well on Android Q.
I have an Android 8 device where the camera app already behaved that way.
Terrible to loose all info when you use the file somewhere else or make a backup.
I am trying to take photo using IMAGE_CAPTURE intent and show this photo on the screen immediately. What I do:
File photoFile = createImageFile();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(intent, REQUEST_CAMERA);
Create image file method:
private File createImageFile() {
File dir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File photoFile = null;
try {
photoFile = File.createTempFile("photo", ".jpg", dir);
mPhotoPath = photoFile.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
}
return photoFile;
}
When onActivityResult is called I execute:
Bitmap photo = BitmapFactory.decodeFile(mPhotoPath);
mPhoto.setImageBitmap(photo);
Here is a problem. Apparently IMAGE_CAPTURE activity saves image to a file in background and my onActivityResult gets executed before image is saved. Because of this my photo == null. Although it works if I put breakpoint before BitmapFactory.decodeFile call. I fixed it with an ugly hack:
while (photo == null) {
photo = BitmapFactory.decodeFile(mPhotoPath);
}
So, am I doing something wrong? Why it works this way?
I am testing on Marshmallow Nexus 5.
Apparently IMAGE_CAPTURE activity saves image to a file in background and my onActivityResult gets executed before image is saved
I would consider that to be a bug in the specific camera app that is handling your request. There are hundreds, if not thousands, of such camera apps, and bugs like this are somewhat common.
I fixed it with an ugly hack
Busy loops like that are never a good idea. Among other things, it will freeze your UI if done in the main application thread, and it will seriously chew up CPU even if done on a background thread.
I would try a FileObserver to watch for when the file is closed, to be more event-driven. If, for whatever reason, you can't get that to work:
make sure you are doing your watch-for-the-file logic in a background thread
add reasonable SystemClock.sleep() periods between tries (e.g., 50ms)
when I crete TAKE PHOTO implicit intent, a intent chooser window appear properly. Unfortunatelly, it shows package names instead of application names. Any idea what I doing wrong? Thanks.
Everything is working (intent, camera app, image returned to onActivityResult, ...).
If there is only one camera app - no choose is shown and camera app is called directly (correct).
Camera application which I have installed are: default android camera, Google Camera.
Tested on 3 different samsung phones.
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Log.e(PoiDetailGalleryFragment.class.getSimpleName(), "Error occurred while creating the File", ex);
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri fileUri = Uri.fromFile(photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, REQUEST_PHOTO_CAPTURE);
}
}
}
I suppose this issue is linked with the Samsung devices, they don't show application name but the package name only.
the Google Nexus devices behave differently, they show the application name and the package name together.
I do not know how to open saved image and display it into gridView.
I make an intent to take a photo:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null && file != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
And file is saved in /data/data/package/files/...
But when I tried to open file and create a bitmap it always return null.
try {
is = this.getContentResolver().openInputStream(Uri.fromFile(f));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Bitmap bitmap = BitmapFactory.decodeStream(is);}
even if I use decodeFile method() I still have a null bitmap.
Files exist in data/data/ ... I checked it.
My question is: how can I get dispaly taken image?
Actually you can't store Pictures caught on camera directly on your app memory, you should write it to sdcard and copy it to your space and delete the original. Because camera is a another app that has no privillege to write on your apps storage space. You can check that if you have root permissions.
If you specify your app memory for camera intent it will always return NULL
You can read this for WORLD_WRITEABLE
I would like to capture an image from the camera and save it to the private app cache directory. I realize that I have to give the camera app permission to write to my private directory, so I added the FLAG_GRANT_WRITE_URI_PERMISSION flag.
What's happening is, that the camera app opens, I can take the picture, but when i click on the OK button, nothing happens. The camera app stays open. No log output. I guess it's because of a permission problem.
private void getCameraImage() {
try {
mTmpFile = File.createTempFile("tmp", ".jpg", getCacheDir());
Uri imgUri = Uri.fromFile(mTmpFile);
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// i.setData(imgUri); // if uncommented, i get an ActivityNotFound Exception
startActivityForResult(i, REQUEST_CAMERA);
} catch (IOException e) {
Log.e(TAG, "getCameraImage()", e);
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
Any insights, on how I could correct that?
Edit:
When I change the directory to the public SD card, then it works fine.
mTmpFile = File.createTempFile("tmp", ".jpg", Environment.getExternalStorageDirectory());
Thanks
Simon
Instead of passing the Uri to store the picture you can use http://developer.android.com/reference/android/hardware/Camera.html#takePicture(android.hardware.Camera.ShutterCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback, android.hardware.Camera.PictureCallback)
and get the content in your app memory. From there you will be able to do anything you want.
Do not forget that camera applications are using also the gallery and the gallery app is not allowed to check your private directory.