I am able to save a full-size photo from the camera at the specified location. However, the photo is being saved at 2 paths - one specified by code, second sd card DCIM folder.
Below is the code to get a full-size photo, it is in Activity and fileUri and mFilePath are class level variables.
private void openCamera() {
Intent takePictureIntent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
File photoFile = null;
try {
photoFile = createFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
fileUri = FileProvider.getUriForFile(context, AUTHORITY, photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
fileUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent,
REQUEST_IMAGE_CAPTURE);
}
}
}
private File createFile() throws IOException {
String state = Environment.getExternalStorageState();
File storageDir;
if (state.equalsIgnoreCase(Environment.MEDIA_MOUNTED)) {
storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
} else {
storageDir = getFilesDir();
}
if (!storageDir.exists()) {
storageDir.mkdirs();
}
File image = File.createTempFile(“app” + System.currentTimeMillis(),
".jpg", storageDir);
mFilePath = image.getAbsolutePath();
return image;
}
private void galleryAddPic() {
MediaScannerConnection.scanFile(this, new String[]{
mFilePath},
null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
galleryAddPic();
}
}
I am not sure is this device or platform specific. I am testing this on Moto G (2nd generation) and 5.0 Android OS. I have tried changing the storage setting for camera app but it always saves at 2 paths. I don't want it to get save at sd card DCIM folder. Has anyone faced such kind of issue? Any idea how to solve this?
Edit: I tried on Samsung's mobile which has 7.0 OS. There this behavior does not exist. Taken picture is getting save only at the specified path.
Related
I've written some code in a fragment to open the camera app and once a photo is taken, a photo is saved. I cannot get it to save a full size image, its saving a lower res version. Can anyone spot where I've gone wrong?
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();
mNewPhotoPath = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES) + "/" +
photoFile.getName();
} catch (IOException ex) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getContext(),
"com.example.mmackenz.myholidays.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
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 = getActivity().getExternalFilesDir(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;
}
This is what I have in my onActivityResult in case that is relevant:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
File newImage = new File(mNewPhotoPath);
images.add(newImage);
adapter.notifyDataSetChanged();
Photo newPhoto = new Photo(newImage.getAbsolutePath(), newImage.getName(), -1, -1);
DatabaseHandler db = DatabaseHandler.getInstance(getContext());
db.addPhoto(newImage.getAbsolutePath(), newImage.getName(), -1,-1);
}
}
It adds a new file to an array list which is displayed in a recycler view, and also info of the file in a Photos table.
Thanks
So, I have an app where I want to take a picture, store it to internal storage, and then be able to retrieve it later (presumably via its Uri). Here is what I have thus far:
This code is triggered when my custom camera button is pressed.
cameraButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Intent takePic = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File file = herp(MEDIA_TYPE_IMAGE);
if (file != null) {
fileUri = getOutputMediaFileUri(file);
Log.d("AddRecipeActivity", fileUri.toString());
takePic.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePic, CAMERA_REQUEST);
}
}
});
Next, I've defined two methods later on in the code(mostly taken from the android developer site):
/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(File file){
return Uri.fromFile(file);
}
/** Create a File for saving an image or video */
public File herp(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
Boolean a = false;
String externalDirectory= getFilesDir().getAbsolutePath();
File folder= new File(externalDirectory + "/NewFolder");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (!folder.exists()){
a = folder.mkdirs();
Log.d("AddRecipeActivity", String.valueOf(a));
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(folder.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else {
return null;
}
if(mediaFile == null){
Log.d("AddRecipeActivity", "Media file is null");
}
return mediaFile;
}
When I print my Uri (right before triggering the intent) I get the following output.
04-04 04:22:40.757 22402-22402/scissorkick.com.project2 D/AddRecipeActivity: file:///data/user/0/scissorkick.com.project2/files/NewFolder/IMG_20160404_042240.jpg
Also, when I check if the directory is made, the boolean is true.
When my camera intent's onActivityResult is run, however, the result code is 0.
Why might it fail at this point? I've defined the appropriate permissions in the manifest, and also request external storage write permissions during run time.
Edit: Added the onActivityResult:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == CAMERA_REQUEST){
Log.d("AddRecipe", String.valueOf(resultCode));
if(resultCode == RESULT_OK){
photo = (Bitmap) data.getExtras().get("data");
thumb = ThumbnailUtils.extractThumbnail(photo, 240, 240);
photoView.setImageBitmap(thumb);
//Toast.makeText(getApplicationContext(), "image saved to:\n" + data.getData(), Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(getApplicationContext(), "Fail", Toast.LENGTH_SHORT).show();
}
}
}
There's some nonsense code in the onActivityResult, but the point is that the resultCode = 0 and I don't know why.
In your final activity, put the below code
data.putExtra("uri", uri);//uri = your image uri
getActivity().setResult(""result_code", data);
getActivity().finish();
Then in your onActivityResult code you can get the uri like
Uri uri = data.getExtras().getParcelable("uri");
Then you can use this Uri value to retrieve your image.
There is how i take picture in my app!
When i press my own Image Button
static final int REQUEST_IMAGE_CAPTURE = 1;
static final int REQUEST_TAKE_PHOTO = 1
static final String STATE_PHOTO_PATH = "photoPath";
ImageButton photoButton = (ImageButton) this.findViewById(R.id.take_picture_button);
photoButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dispatchTakePictureIntent();
}
});
And here how manage and create/store the file with image
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;
}
//Create a new empty file for the photo, and with intent call the camera
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(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
// Error occurred while creating the File
Log.e("Error creating File", String.valueOf(e.getMessage()));
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
//I have the file so now call the Camera
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
private void openImageReader(String imagePath) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri imgUri = Uri.parse(imagePath);
intent.setDataAndType(imgUri, "image/*");
startActivity(intent);
}
In the ActivityResult i only save a record in DB, with the Path of the image so i can retrieve it back and read the photo stored like file.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
//Save the path of image in the DB
db.addCompito(new Compiti(activity_name, null, mCurrentPhotoPath));
refreshListView();
}
}
If you have some screen rotation don't forget to add something like
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putString(STATE_PHOTO_PATH, mCurrentPhotoPath);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentPhotoPath = savedInstanceState.getString(STATE_PHOTO_PATH);
}
WHY?
Because when the rotation change you can lose the file that you have created for the "new photo" and when you accept it and save it, your photopath is null and no image is created.
I have a problem, that when i have taken an image from camera, image not displaying in imageview.
I created the code by referring the following link
http://developer.android.com/training/camera/photobasics.html
I am posting my code, please have a look,
public void takeImage(View v) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "sample_" + 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();
galleryAddPic();
return image;
}
private void galleryAddPic() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
try {
if (requestCode == REQUEST_IMAGE_CAPTURE) {
Bundle extras = data.getExtras();
Bitmap imageBitmap = (Bitmap) extras.get("data");
mImageView.setImageBitmap(imageBitmap);
}
}catch (Exception e) {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG).show();
}
}
The image captured is storing in SDcard. But not showing in imageview.
Where i have gone wrong. I have tried a lot. But no result. Is there any way to solve this issue.
this works for me:
Bitmap myBitmap = BitmapFactory.decodeFile(imagePath);
image.setImageBitmap(myBitmap);
You don't need to create the temp file, just put the Uri in the intent. After the capture, check the file existence of that Uri. If it exists, capture has been done successfully.
I have read a lot of questions regarding this problem. Some are similar to what I am experiencing; I have tried the answers with no success. The code works on a HTC Android 4.2 and doesn't work on a Nexus 7 Android 4.4. I have modified the storage directory to work on android 4.4, so this isn't the problem.
The camera intent never returns if I use
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
and does return if I use
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
but it doesn't save the file.
Here is the full code.
Call the intent
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(manager) != null)
{
try
{
final File photoFile = createImageFile();
if (photoFile != null)
{
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
//takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoFile);
startActivityForResult(takePictureIntent, 1);
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
The file name
private File createImageFile() throws IOException
{
if (mStorageDirectory == null)
{
createInitialStorageDirectory();
setupFolders();
mScrollList.notifyDataSetInvalidated();
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "slide_" + timeStamp;
File storageDir = new File(mStorageDirectory);
File image = File.createTempFile(imageFileName, ".jpg", storageDir);
// image.setWritable(true, false);
// Save a path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
The callback function
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == -1)
{
}
}
The root directory plus the save directory
static String mBasePath = "/slides/";
private String getRootDirectory()
{
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state))
{
if (Build.VERSION.SDK_INT >= 19)
return mView.getContext().getFilesDir() + mBasePath;
else
return Environment.getExternalStorageDirectory() + "/Android/data/com.hdms.manager" + mBasePath;
//return Environment.getExternalStorageDirectory() + mBasePath;
}
return mBasePath;
}
Any thoughts would be appreciated.
In my case, it did not return because the output file was inside a folder which I have not created yet.
If it is the case for someone else, do this before starting anintent:
file.getParentFile().mkdirs();
So I have found a solution to my problem. If a file doesn't exist then the Camera Activity will not return. I guess the reason that it doesn't work on 4.4 is the change to the files system. I am not saving the image to the media gallery and loading the file back into my apps directory. The media file is then deleted. The reason that I don't leave it in the media directory, is when the app is deleted so will the images be deleted.
Here is the new code. First the intent call
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(manager) != null)
{
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION,"From your Camera");
Uri mImageUri = App.mApplication.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
mCurrentPhotoPath = mImageUri.getPath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(takePictureIntent, 1);
}
Then the callback.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == -1)
{
if (data != null)
mCurrentPhotoPath = String.valueOf(data.getData());
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = App.mApplication.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, filePathColumn, null, null, null);
if (cursor == null)
return;
// find the file in the media area
cursor.moveToLast();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
File source = new File(filePath);
cursor.close();
// create the destination file
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "slide_" + timeStamp;
File destination = new File(mStorageDirectory, imageFileName + ".jpg");
// copy the data
if (source.exists())
{
try
{
FileChannel src = new FileInputStream(source).getChannel();
FileChannel dst = new FileOutputStream(destination).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
source.delete();
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
In our scenario our app is able to launch the camera app either via a 'button' click or an 'imageview' click. When using the button route the camera app correctly returned to the calling Activity as expected, however when tapping the imageview the results were inconsistent - sometimes it would return and sometimes the back button had to be tapped several times.
Turns out the solution was my oversight: I was not removing the event handler for the imageview in the OnPause method - once I did then it worked perfectly.
I'm trying to write an app that will take a picture with the native Android Camera app and then display the picture I just took in a new activity. This is my take picture method.
private static 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;
}
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(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
int t =5;
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
This works; the camera app opens up and the image is saved. However, this is my display image method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String j = MainActivity.mCurrentPhotoPath;
Bitmap myBitmap = BitmapFactory.decodeFile(j);
ImageView myImage = new ImageView(this);
myImage.setImageBitmap(myBitmap);
setContentView(myImage);
}
Now I tested to see if the filename path was being recorded, and it was. String j does indeed have the path. But, the system cannot run the .decodeFile(String j) method; it says that no such file exists. What do I do to display the image?
If you are using the native camera, you will get the resulting picture in onActivityResult() given that you start the camera app using startActivityForResult(). You can then get a reference to the picture's path as follows (from the docs):
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Image captured and saved to fileUri specified in the Intent
Toast.makeText(this, "Image saved to:\n" +
data.getData(), Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
}
You can then pass this path to the new Activity via an Intent and decode the Bitmap accordingly.