I'm developing an Android App that uses an Intent to open the in-built camera, and take a photo that then should be saved to storage and be sent to a different intent that crops it.
I've run the app a few times but can't see any of the photos being saved anywhere in storage. I started debugging the code and found that it was skipping out on the commands in the OnActivityResult method because the resultCode parameter was always going back as 0.
Out of curiosity I manually changed this to the required value of -1, and the code then skipped out on the next if statement because data.getExtras() (data being the Intent parameter) was returning null, even though I had been adding an extra in the code that triggered the Camera Activity.
I can't quite figure out what's happening here. I'd assume the image is saving somehow because no exception is being thrown, but don't see what might be causing the empty values of resultCode and data.
My code is shown below. If anyone can give me a point in the right direction, that would be a massive help!
Thanks,
Mark
public void onClick(DialogInterface dialogInterface, int i) {
if (optionItems[i].equals(OPTION_CAMERA)) {
//intent to open device camera
Intent cameraIntent =
new Intent(
MediaStore.ACTION_IMAGE_CAPTURE
);
//create 'Spond' folder inside photo directory
//target folder for image to be saved
File imagesFolder =
new File(
Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES),
getString(R.string.app_name)
);
//create directory if it doesn't already exist
imagesFolder.mkdirs(); //bool return value not needed
//create file with unique id
File image = createFileAtUniquePath(imagesFolder);
//use authority for AndroidManifest to create permission
//to get uri from temporary file in app
String fileProviderAuthority = getApplicationContext().getPackageName() +
getString(R.string.authorities_fileprovider);
Uri uriSavedImage = FileProvider.getUriForFile(
getApplicationContext(),
fileProviderAuthority,
image
);
//pass URI to intent so it will be available in activity result
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
//grant read/write permissions with file
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
startActivityForResult(cameraIntent, REQUEST_CAMERA);
The OnActivityResult code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_CAMERA) {
if (data.getExtras() != null) {
newAccountPhotoUri = (Uri) data.getExtras().get(MediaStore.EXTRA_OUTPUT);
newAccountPhotoFileName = getFileNameFromURI(newAccountPhotoUri);
if (!newAccountPhotoFileName.equals("")) {
appAccountPhotoChanged = true;
//send image to be cropped
cropImage(newAccountPhotoUri);
}
}
}
//...
}
Related
I am trying to fetch a file this way:
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
String[] mimetypes = {"application/pdf"};
chooseFileIntent.setType("*/*");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(activity
.getApplicationContext().getPackageManager()) != null) {
chooseFileIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
activity.startActivityForResult(chooseFileIntent, Uploader.PDF);
}
Then in onActivityResult :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath(), the file name I'm expecting is my_file.pdf, but instead I'm getting this :
/document/acc=1;doc=28
So what to do? Thanks for your help.
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using ACTION_GET_CONTENT. (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If getScheme() of the Uri returns file, your original algorithm will work
If getScheme() of the Uri returns content, use DocumentFile.fromSingleUri() to create a DocumentFile, then call getName() on that DocumentFile — this should return a "display name" which should be recognizable to the user
To get the real name and to avoid getting a name that looks like "image: 4431" or even just a number, you can write code as recommended by CommonsWare.
The following is an example of a code that selects a single pdf file, prints its name and path to the log, and then sends the file by email using its uri.
private static final int FILEPICKER_RESULT_CODE = 1;
private static final int SEND_EMAIL_RESULT_CODE = 2;
private Uri fileUri;
private void chooseFile() {
Intent fileChooser = new Intent(Intent.ACTION_GET_CONTENT);
fileChooser.setType("application/pdf");
startActivityForResult(Intent.createChooser(fileChooser, "Choose one pdf file"), FILEPICKER_RESULT_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILEPICKER_RESULT_CODE) {
if (resultCode == RESULT_OK) {
fileUri = data != null ? data.getData() : null;
if (fileUri != null) {
DocumentFile d = DocumentFile.fromSingleUri(this, fileUri);
if (d != null) {
Log.d("TAG", "file name: " + d.getName());
Log.d("TAG", "file path: " + d.getUri().getPath());
sendEmail(fileUri);
}
}
}
}
}
private void sendEmail(Uri path) {
String email = "example#gmail.com";
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "PDF file");
String[] to = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, "This is the pdf file...");
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."), SEND_EMAIL_RESULT_CODE);
}
hope it helps.
I am trying to fetch a file this way:
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
String[] mimetypes = {"application/pdf"};
chooseFileIntent.setType("*/*");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(activity
.getApplicationContext().getPackageManager()) != null) {
chooseFileIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
activity.startActivityForResult(chooseFileIntent, Uploader.PDF);
}
Then in onActivityResult :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath(), the file name I'm expecting is my_file.pdf, but instead I'm getting this :
/document/acc=1;doc=28
So what to do? Thanks for your help.
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using ACTION_GET_CONTENT. (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If getScheme() of the Uri returns file, your original algorithm will work
If getScheme() of the Uri returns content, use DocumentFile.fromSingleUri() to create a DocumentFile, then call getName() on that DocumentFile — this should return a "display name" which should be recognizable to the user
To get the real name and to avoid getting a name that looks like "image: 4431" or even just a number, you can write code as recommended by CommonsWare.
The following is an example of a code that selects a single pdf file, prints its name and path to the log, and then sends the file by email using its uri.
private static final int FILEPICKER_RESULT_CODE = 1;
private static final int SEND_EMAIL_RESULT_CODE = 2;
private Uri fileUri;
private void chooseFile() {
Intent fileChooser = new Intent(Intent.ACTION_GET_CONTENT);
fileChooser.setType("application/pdf");
startActivityForResult(Intent.createChooser(fileChooser, "Choose one pdf file"), FILEPICKER_RESULT_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILEPICKER_RESULT_CODE) {
if (resultCode == RESULT_OK) {
fileUri = data != null ? data.getData() : null;
if (fileUri != null) {
DocumentFile d = DocumentFile.fromSingleUri(this, fileUri);
if (d != null) {
Log.d("TAG", "file name: " + d.getName());
Log.d("TAG", "file path: " + d.getUri().getPath());
sendEmail(fileUri);
}
}
}
}
}
private void sendEmail(Uri path) {
String email = "example#gmail.com";
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "PDF file");
String[] to = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, "This is the pdf file...");
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."), SEND_EMAIL_RESULT_CODE);
}
hope it helps.
I am trying to fetch a file this way:
final Intent chooseFileIntent = new Intent(Intent.ACTION_GET_CONTENT);
String[] mimetypes = {"application/pdf"};
chooseFileIntent.setType("*/*");
chooseFileIntent.addCategory(Intent.CATEGORY_OPENABLE);
if (chooseFileIntent.resolveActivity(activity
.getApplicationContext().getPackageManager()) != null) {
chooseFileIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
activity.startActivityForResult(chooseFileIntent, Uploader.PDF);
}
Then in onActivityResult :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath(), the file name I'm expecting is my_file.pdf, but instead I'm getting this :
/document/acc=1;doc=28
So what to do? Thanks for your help.
I am trying to fetch a file
Not with that code. That code is asking the user to pick a piece of content. This may or may not be a file.
According to many threads I'm supposed to fetch the file name from the intent with data.getData().getPath()
That was never correct, though it tended to work on older versions of Android.
So what to do?
Well, that depends.
If you wish to only accept files, integrate a file chooser library instead of using ACTION_GET_CONTENT. (UPDATE 2019-04-06: since Android Q is banning most filesystem access, this solution is no longer practical)
If you are willing to allow the user to pick a piece of content using ACTION_GET_CONTENT, please understand that it does not have to be a file and it does not have to have something that resembles a filename. The closest that you will get:
If getScheme() of the Uri returns file, your original algorithm will work
If getScheme() of the Uri returns content, use DocumentFile.fromSingleUri() to create a DocumentFile, then call getName() on that DocumentFile — this should return a "display name" which should be recognizable to the user
To get the real name and to avoid getting a name that looks like "image: 4431" or even just a number, you can write code as recommended by CommonsWare.
The following is an example of a code that selects a single pdf file, prints its name and path to the log, and then sends the file by email using its uri.
private static final int FILEPICKER_RESULT_CODE = 1;
private static final int SEND_EMAIL_RESULT_CODE = 2;
private Uri fileUri;
private void chooseFile() {
Intent fileChooser = new Intent(Intent.ACTION_GET_CONTENT);
fileChooser.setType("application/pdf");
startActivityForResult(Intent.createChooser(fileChooser, "Choose one pdf file"), FILEPICKER_RESULT_CODE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILEPICKER_RESULT_CODE) {
if (resultCode == RESULT_OK) {
fileUri = data != null ? data.getData() : null;
if (fileUri != null) {
DocumentFile d = DocumentFile.fromSingleUri(this, fileUri);
if (d != null) {
Log.d("TAG", "file name: " + d.getName());
Log.d("TAG", "file path: " + d.getUri().getPath());
sendEmail(fileUri);
}
}
}
}
}
private void sendEmail(Uri path) {
String email = "example#gmail.com";
Intent intent = new Intent(android.content.Intent.ACTION_SEND);
intent.setType("application/octet-stream");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "PDF file");
String[] to = { email };
intent.putExtra(Intent.EXTRA_EMAIL, to);
intent.putExtra(Intent.EXTRA_TEXT, "This is the pdf file...");
intent.putExtra(Intent.EXTRA_STREAM, path);
startActivityForResult(Intent.createChooser(intent, "Send mail..."), SEND_EMAIL_RESULT_CODE);
}
hope it helps.
I am developing android app and my app have button to take camera. Previously i had fallen into a state where return data in onActivityResult after taking picture being null. This is camera expected behaviour whereby if we put EXTRA_OUTPUT in intent , it would return null. For that reason , I did null checking code and it went fine .
Now again after a few days and i tested . I still fallen into same issue again. But this time data is not null. data has empty intent such as intent and data.getData() become null.I fixed this by checking data.getData() == null and it works again. I don't why it is like that. Just curious about what was going on. For that reason i have to re-upload to production again. :-(
//camera intent
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra("requestCode", Constants.REQUEST_IMAGE_CAPTURE);
Intent chooseImageIntent = new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
chooseImageIntent.setType("image/* video/*");
chooseImageIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
chooseImageIntent.putExtra("requestCode", Constants.REQUEST_CHOOSE_FROM);
//app can use camera
if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {
//add output file path which camera will save image to
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Helpers.getOutputMediaFileUri());
//create choose
Intent chooser = Intent.createChooser(chooseImageIntent, "Select From");
//add take camera intent as first intent
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS,new Intent[]{takePictureIntent});
//open up dialog
((Activity) mContext).startActivityForResult(chooser, Constants.REQUEST_CHOOSE_FROM);
} else {
((Activity) mContext).startActivityForResult(chooseImageIntent, Constants.REQUEST_IMAGE_GALLERY);
}
EDITED
I know I how to fix the problem. What i don't understand is return data must be null if i put in EXTRA_OUTPUT. Mostly importantly the code I implemented few weeks back , i am quite sure that data return null and suddenly it is non null value again.
Actually the camera intent doesnot return the data in intent because after getting image it kill the activity.
so try this
void opencameraForPicture(int requestCode, Uri fileUri) {
checkPermissionForMarshMello(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE);
Intent intent = new Intent(Constants.CAMERA_INTERNAL_CLASS);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
/* start activity for result pass intent as argument and request code */
startActivityForResult(intent, requestCode);
}
/**
* This method set the path for the captured image from camera for adding
* the new picture in the list
*/
private Uri getOutputMediaFile() {
File mediaStorageDir = new File(
Environment.getExternalStorageDirectory(), "."
+ Constants.CONTAINER);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists()) {
mediaStorageDir.mkdirs();
}
File mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + System.currentTimeMillis() + ".png");
Uri uri = null;
if (mediaFile != null) {
uri = Uri.fromFile(mediaFile);
}
return uri;
}
in #Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String imagePath = fileUri.getPath();
//you can decode this path as bitmap
}
im build some apps that call camera activity..
im just to take picture from my apps and send it to web server..
but i can't get my image path..
im always getting NullException Error when try to get image path..
here's my code when calling camera activity :
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
this.startActivityForResult(camera, PICTURE_RESULT);
and this is code for activity result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICTURE_RESULT){
if (resultCode == Activity.RESULT_OK) {
takePicture(data);
} else if (resultCode == Activity.RESULT_CANCELED) {
}
}
}
protected void takePicture(Intent data) {
Bundle b = data.getExtras();
pic = (Bitmap) b.get("data");
if (pic != null) {
imagePicture.setImageBitmap(pic);
}
}
is there something wrong with my code?
Thanks
Ok, I see your problem. You're not setting the path to begin with. Please look at this doc.
http://developer.android.com/reference/android/provider/MediaStore.html#ACTION_IMAGE_CAPTURE
So you see, when you call ACTION_IMAGE_CAPTURE you are not passing it the extra EXTRA_OUTPUT that tells the application where the picture is going to be stored. This EXTRA_OUTPUT is the path to the file.
So right under where you make the intent do this:
Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
URI pictureUri = Uri.fromFile(new File(<path to your file>));
camera.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);