Android: Capture and store pictures - android

I'm following this tutorial on taking pictures, displaying thumbnails and storing the full pictures on local public storage available to my application only.
The problem: EACCESS (Permission denied) when trying to access local storage for my application
11-12 10:36:30.765 3746-3746/com.test.example.photo W/System.err﹕ java.io.IOException: open failed: EACCES (Permission denied)
11-12 10:36:30.765 3746-3746/com.test.example.photo W/System.err﹕ at java.io.File.createNewFile(File.java:948)
11-12 10:36:30.765 3746-3746/com.test.example.photo W/System.err﹕ at java.io.File.createTempFile(File.java:1013)
I've looked at this question but it appears to be outdated as none of the solutions work any more today. This question also provides no working solutions. Other results and solutions I've seen and tried seem only vaguely related.
My manifest permissions
</application>
<!-- PERMISSIONS -->
<permission
android:name="android.hardware.Camera.any"
android:required="true" />
<permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:required="true" />
<!-- android:maxSdkVersion="18" seemingly does nothing-->
</manifest>
The method that crashes
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
//THIS IS WHERE IT CRASHES
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
I am using an i9250 Galaxy Nexus 3 phone to run the examples, since my emulator doesn't have a camera and automatically GONEs the elements. My target SDK is 16 and I have updated my both my build tools and Android Studio to the latest versions.
I feel like I'm missing something obvious here, since taking pictures is so common in applications and I can't imagine it not working for everyone, but I'm stuck and I'd appreciate your guidance. I am quite new to android, the literature I'm primarily using is Beginning Android 4 Game Programming, Beginning Android 4 and Pro Android 4.
Thank you for your time!

Thanks for the help everyone, it works now!
Apparently I was using the SD card storage which required permissions as explained in permission vs uses-permisson instead of local sandboxed storage which requires no permissions starting from API level 19.
SD card access, requires write permission: Environment.getExternalStoragePublicDirectory
Sandboxed local storage for your app: getExternalFilesDir
I use this code for API level 16, it should require minimal effort to implement and change but if you encounter problems, leave a message and I'll try to help or clarify.
Most of the explanation is in the code as commentary
//OnClick hook, requires implements View.OnClickListener to work
public void takePicture(View v) {
dispatchTakePictureIntent();
}
private void dispatchTakePictureIntent() {
//Create intent to capture an image from the camera
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the directory File where the photo should go, do NOT try to create the image file itself
File photoFile = null;
try {
//mCurrentPhotoPath is a File outside of the methods, so all methods know the last directory for the last picture taken
mCurrentPhotoPath = createImageFile();
photoFile = mCurrentPhotoPath;
} catch (IOException ex) {
// Error occurred while creating the File
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
//photoFile MUST be a directory or the camera will hang on an internal
//error and will refuse to store the picture,
//resulting in not being able to to click accept
//MediaStore will automatically store a jpeg for you in the specific directory and add the filename to the path
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
//unique name, can be pretty much whatever you want
imageId = generateImageId();
//Get file.jpg as bitmap from MediaStore's returned File object
Bitmap imageBitmap = BitmapFactory.decodeFile(mCurrentPhotoPath.getAbsolutePath());
//resize it to fit the screen
imageBitmap = Bitmap.createScaledBitmap(imageBitmap,300,300,false);
//Some ImageView in your layout.xml
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageBitmap(imageBitmap);
Bitmap thumbnail = makeThumbnail(mCurrentPhotoPath);
ImageView thumbnail = (ImageView)findViewById(R.id.thumbnail);
thumbnail.setImageBitmap(imageBitmap);
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
//completely optional subdirectory structure
storageDir = new File(storageDir, "custom_directory");
return storageDir;
}
private Bitmap makeThumbnail(File currentPhotoPath) {
// Get the dimensions of the View, I strongly recommend creating a <dimens> resource for dip scaled pixels
int targetW = 45;
int targetH = 80;
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(currentPhotoPath.getAbsolutePath(), bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(currentPhotoPath.getAbsolutePath(), bmOptions);
return bitmap;
}
private long generateImageId() {
return Calendar.getInstance().getTimeInMillis();
}
Android 5.0, API 21, will use the Camera2 API where all of this will be hidden far away, from what I understand. You can read about it here

try this:
private File getDir() {
File sdDir = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return new File(sdDir, "Your_photo_dir_here");
}
then:
File pictureFileDir = getDir();
if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {
Log.d("TAG", "Can't create directory to save image.");
return;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
String date = dateFormat.format(new Date());
String photoFile = "myphoto_" + date + ".jpg";
String filename = pictureFileDir.getPath() + File.separator + photoFile;
File pictureFile = new File(filename);
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (Exception error) {
Log.d("TAG", "File" + filename + "not saved: "
+ error.getMessage());
}

Instead of permission tag use uses-permission
Add this in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Related

FileProvider path creation and BitmapFactory.decodefile problems in Android

I am trying to use BitmapFactory.decodefile() in order to create a scaled down
version of a camera photo and set it to an imageview in my framelayout.
Am following the following instructions from Android Developers:
https://developer.android.com/training/camera/photobasics.html
In these instructions, files are created and stored inside a fileprovider which holds some meta-data file formatted in xml. Somehow, BitmapFactory.decodefile() can't seem to access this file which stores a picture whose content uri resides inside the fileprovider.
The fileprovider is created inside the androidmanifest file as follows:
<provider
android:authorities="mypackagename.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false" android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths" >
</meta-data>
</provider>
the file_paths xml file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/mypackagename/files/Pictures/" />
</paths>
The file name for where the picture will reside is generated via this method:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(imageFileName,".jpg",storageDir);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
Log.d("absolute",""+image.getAbsolutePath());
return image;
}
The code starts an intent in order to take a picture with startactivityforresult() like this:
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (i.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile (this,"mypackagename.fileprovider",photoFile);
i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(i,TAKE_PICTURE);
}
}
Now, onActivityForResult() method starts, but if I set my if statement like this
if(requestCode == TAKE_PICTURE && resultCode == RESULT_OK)
it doesn't work. I don't know why.
From reading the android reference documents on fileprovider class, I see that
I must open the photoUri which is passed as an extra in my intent.
According to the docs, I must open It with ContentResolver.openFileDescriptor which will return a ParcelFileDescriptor. Somehow, this is where the picture the camera just took resides. Somehow I need to access the file name from this ParcelFileDescriptor object and pass it to BitmapFactory.decodefile in order to scale down the picture-bitmap and set it on my imageview. I don't know how to go about this
When trying to scale the picture-bitmap I have the following code that returns -1, meaning that "according to the android reference docs for BitmapFactory class" "there was a problem decoding the file". I don't know why there would be a problem. Here's the code that returns -1:
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
Both photoW and photoH return -1. Remember that the variable mCurrentPhotoPath was initialized inside the method CreateImageFile() , all the way at the top of this question.
I've also tried,
BitmapFactory.decodeFile(photoFile.getAbsolutePath(), bmOptions);
But still the same result, actually mCurrentPhotoPath and photoFile.getAbsolutePath() are equal strings.
I think that somehow the fileprovider with its meta-data xml file are somehow hiding the file path from BitmapFactory.decodefile().
The picture is taken when I test the app and is also stored inside my phone picture gallery.
Please provide any advice or suggestions since I need to proceed with the tess-two library and perform OCR with the pictures from the camera.
Thanks for your suggestions
I have faced exactly the same problem and this is how I dealed with it: first of all set i.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); as suggested above, before launching the camera. Then, DO NOT use the BitmapFactory.decodeFile() method as it only works with the file:/// type of Uris retrieved using Uri.fromFile(), but not with the content:// type of Uris retrieved using FileProvider.getUriForFile() which is the required way for APIs >= 24.
Instead, use a ContentResolver to open an InputStream and decode the image as follows:
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
ContentResolver cr = getActivity().getContentResolver();
InputStream input = null;
InputStream input1 = null;
try {
input = cr.openInputStream(photoUri);
BitmapFactory.decodeStream(input, null, bmOptions);
if (input != null) {
input.close();
}
} catch (Exception e) {
e.printStackTrace();
}
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
try {
input1 = cr.openInputStream(photoUri);
Bitmap takenImage = BitmapFactory.decodeStream(input1);
if (input1 != null) {
input1.close();
}
} catch (Exception e) {
e.printStackTrace();
}
Note, that in order to obtain the Bitmap, you have to open a 2nd input stream, since the first one cannot be reused.
I ended here, because I was looking for a way to get Bitmap from an Uri of an image in internal storage, written with FileProvider.
(Followed this answer to write image to internal storage: https://stackoverflow.com/a/30172792/529663)
I was able to get back a readable Bitmap image using GrAndroidDeveloper's answer. Here's how:
ContentResolver cr = getApplicationContext().getContentResolver();
InputStream is = cr.openInputStream(uri);
Bitmap image = BitmapFactory.decodeStream(is);
if (is != null) is.close();
This is useful for the official facebook share, which needs a Bitmap.

In Android, How to get image without saving image file

thank you for your appreciation in advance.
I am coding in next contidion.
a. use internal camera app(I use Intent and other app to take pickture).
b. get image without saving into file.
In my app, user take pickture of a credit card and send to server. Credit card image file is not necessary and saving image into file is not good for security.
Is it possible?
If it is impossible, is there anything else?
a. opening jpg file, editing all pixel into black
b. use https://github.com/Morxander/ZeroFill
Whitch method is properable?
Short answer is NO.
You can't get an photo from default camera app without saving it into image.
What you can do is use Camera API to take photo inside your app, not using 3rd party default system photo app.
Look here full Source.
Request this permission on the AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
On your Activity, start by defining this:
static final int REQUEST_IMAGE_CAPTURE = 1;
private Bitmap mImageBitmap;
private String mCurrentPhotoPath;
private ImageView mImageView;
Then fire this Intent in an onClick:
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
Log.i(TAG, "IOException");
}
// Continue only if the File was successfully created
if (photoFile != null) {
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
}
}
Add the following support method:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
return image;
}
Then receive the result:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
try {
mImageBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath));
mImageView.setImageBitmap(mImageBitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
What made it work is the MediaStore.Images.Media.getBitmap(this.getContentResolver(), Uri.parse(mCurrentPhotoPath)), which is different from the code from developer.android.com. The original code gave me a FileNotFoundException.

Error: open failed: ENOENT (No such file or directory)

I was trying to create a file to save pictures from the camera, it turns out that I can't create the file.
But I really can't find the mistake. Can you have a look at it and give me some advice?
private File createImageFile(){
File imageFile=null;
String stamp=new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File dir= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String imageFileName="JPEG_"+stamp+"_";
try {
imageFile=File.createTempFile(imageFileName,".jpg",dir);
} catch (IOException e) {
Log.d("YJW",e.getMessage());
}
return imageFile;
}
And I have added the permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
The method always gives such mistakes:
open failed: ENOENT (No such file or directory)
The Pictures directory might not exist yet. It's not guaranteed to be there.
In the API documentation for getExternalStoragePublicDirectory(), the code ensures the directory exists using mkdirs:
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
try {
// Make sure the Pictures directory exists.
path.mkdirs();
...so it may be as simple as adding that path.mkdirs() to your existing code before you createTempFile.
when a user picks a file from the gallery, there is no guarantee that the file that was picked was added or edited by some other app. So, if the user picks on a file that let’s say belongs to another app we would run into the permission issues. A quick fix for that is to add this code in the AndroidManifest.xml file:
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Note: For Android 11 refer Scope storage Enforcement Policy https://developer.android.com/about/versions/11/privacy/storage
Replace:
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES)
With:
private File createImageFile() throws IOException {
// Create an image file name
make sure you call:
mkdirs() // and not mkdir()
Here's the code that should work for you:
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = new File(Environment.getExternalStorageDirectory().toString(), "whatever_directory_existing_or_not/sub_dir_if_needed/");
storageDir.mkdirs(); // make sure you call mkdirs() and not mkdir()
File image = File.createTempFile(
imageFileName, // prefix
".jpg", // suffix
storageDir // directory
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "file:" + image.getAbsolutePath();
Log.e("our file", image.toString());
return image;
}
I had a bad experience following the example given in Android Studio Documentation and I found out that there are many others experiencing the same about this particular topic here in stackoverflow, that is because even if we set
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
the problem persists in some devices.
My experience was that the example worked when I tried it in debug mode, after that 3 more tests it so happened that my SD suddenly was corrupted, but I don't think it has to do with their example (funny). I bought a new SD card and tried it again, only to realize that still both release and debug mode did the same error log: directory does not exist ENOENT. Finally, I had to create the directories myself whick will contain the captured pictures from my phone's camera. And I was right, it works just perfect.
I hope this helps you and others out there searching for answers.
A quick fix for that is to add this code in the AndroidManifest.xml file:
<manifest ... >
<application android:requestLegacyExternalStorage="true" ... >
...
</application>
</manifest>
Note: Applicable for API level 29 or Higher
I used the contentResolver with the URI and it worked for me. Saw it in another SO post which i can't find.
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) {
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
hope it helps....
I have solved like this:
public Intent getImageCaptureIntent(File mFile) {
Intent mIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri photoURI = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".provider", mFile);
mIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
// The tip is this code below
List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(mIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
return mIntent;
}
If you are using kotlin then use below function.
you have to provide a path for storing image, a Bitmap (in this case a image) and if you want to decrease the quality of the image then provide %age i.e 50%.
fun cacheLocally(localPath: String, bitmap: Bitmap, quality: Int = 100) {
val file = File(localPath)
file.createNewFile()
val ostream = FileOutputStream(file)
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, ostream)
ostream.flush()
ostream.close()
}
hope it will work.
Try this:
private File createImageFile() throws IOException {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName="JPEG_"+stamp+".jpg";
File photo = new File(Environment.getExternalStorageDirectory(), imageFileName);
return photo;
}
File dirPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File imageFile = new File(dirPath, "YourPicture.jpg");
try {
if(!dirPath.isDirectory()) {
dirPath.mkdirs();
}
imageFile.createNewFile();
} catch(Exception e) {
e.printStackTrace();
}
I got same error while saving Bitmap to External Directory and found a helpful trick
private void save(Bitmap bitmap) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
String imageFileName = timeStamp + ".png";
String path = MediaStore.Images.Media.insertImage(activity.getContentResolver(), bitmap, imageFileName, null);
Uri uriimage = Uri.parse(path);
// you made it, make fun
}
But this have a drawback i.e. you cant change the Directory it always save images to Pictures directory but if you got it fixed fill free to edit my code:
Haa-ha-ha {I can't use emojis with my keyboard}, Good Day
Following are fixes i found
first add these two lines in your AndroidManifest file
Than add the below line just after setContentView method
ActivityCompat.requestPermissions(FullImageActivity.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_CODE);
and for saving the images in gallery use the below code
private void SaveImageToGallery() {
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
FileOutputStream outputStream = null;
File file = Environment.getExternalStorageDirectory();
File dir = new File(file.getAbsolutePath()+"/folderName");
dir.mkdirs();
String filename = String.format("%d.jpg",System.currentTimeMillis());
File outfile = new File(dir,filename);
try{
outputStream = new FileOutputStream(outfile);
bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
outputStream.flush();
outputStream.close();
}catch(Exception e){
Log.d("SavingError", "SaveImageToGallery: "+e.getMessage());
}
Toast.makeText(this, "Image saved in folderName folder", Toast.LENGTH_SHORT).show();
}

Get all gallery images on Nexus 4

I am developing a simple gallery app in which I search for folders which contains images and then show images of that particular folder. First I am using Environment.getExternalStorageDirectory() and then recursively search for folders having images. It is working fine simulator and devices. When my client installed app on Nexus 4, nothing is being loaded. I have seen some posts which says that Nexus series don't have any external SD slot. I don't have Nexus 4 for debugging and client is also non-technical. He can troubleshoot on his own to find the cause of problem. Can anybody help in this regard? I think the problem is in Environment.getExternalStorageDirectory() call which is not applicable in Nexus. Any idea how I can tackle this issue?
Here is the code snipped I am using:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File cacheDir = null;
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
cacheDir=new File(android.os.Environment.getExternalStorageDirectory().getAbsolutePath(), "MyImages");
}
else {
cacheDir = getCacheDir();
}
if(!cacheDir.exists()) {
cacheDir.mkdir();
}
// File storageDir = Environment.getExternalStoragePublicDirectory(
// Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
cacheDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = "" + image.getAbsolutePath();
return image;
}
public void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
And here the permissions I have added manifest:
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
Thanks!
I think you should give a try to the MediaStore.Images component. Load the images using a cursor. See documentation: http://developer.android.com/reference/android/provider/MediaStore.html

Trouble with adding file path to the MediaStore.ACTION_IMAGE_CAPTURE intent

I am adding a photo from the phones camera to a Fragment. I am including the file path to where I would like the pic to get saved in the camera intent(MediaStore.ACTION_IMAGE_CAPTURE).
My problem is that after launching the camera and taking the pic the I am not able to get back to my app. The screen stays in the part where the user gets the option to accept the pic or take another one. The phone doesn't hang or crash and I am able to get back to my app by hitting the back button, but when I get back to the app it is without the pic.
I hope I have made my problem clear, if not let me know and I will try to explain better. I have attached (what I think) are the relevant bits of code.Let me know if you need to see anymore of the code.
Launching the camera intent:
void takePic()
{
if(isExternalStorageWritable() && isExternalStorageReadable())
{
Log.w("Rakshak", "in the take pic");
File file = getPicStoragePath();
Uri uriSavedImage=Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(intent, CAMERA_IMAGE_ACTIVITY_REQUEST_CODE);
}
}
public File getPicStoragePath() {
Log.w("Rakshak", "in the get pic file");
File root = android.os.Environment.getExternalStorageDirectory();
File dir = new File (root.getAbsolutePath() + File.separator +"YAN");
if(!dir.exists())
dir.mkdirs();
File file = new File(dir,getPicName());
return file;
}
public String getPicName()
{
Log.w("Rakshak", "in the get pic name");
if(title.getText().toString().trim().length() == 0)
{
Log.w("Rakshak", "no title");
Calendar cal=Calendar.getInstance();//get an instance of the calendar
return String.format("%1$te %1$tB %1$tY,%1$tI:%1$tM:%1$tS %1$Tp",cal);// get the data/time when the note was created
}
else
{
return title.getText().toString().trim();
}
}
I have these permissions in the manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
The relavent bits from the onActivityResult:
case CAMERA_IMAGE_ACTIVITY_REQUEST_CODE:
Log.w("Rakshak", "in the camera case");
myBitmap = data.getExtras().getParcelable("data");
photo.setVisibility(View.VISIBLE);
photo.setImageBitmap(myBitmap);
update_pic = true;
return;
There are no error messages in the LogCat. And I could not find anything of note in there.
I get the pic inserted onto the image view just fine if I dont add a file path to the camera intent. It is only when I add the file path that the stays in the "accept pic" bit of the camera.
Your getPicStoragePath() might be the issue. Try something like this:
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}

Categories

Resources