I try to take and save photo in my app.
I wrote in manifest the fileprovider and path for him:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="mypacage.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/path" />
</provider>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="my_images" path="images"/>
</paths>
In my activity I call Fragment Dialog (cameraOrChoosePhoto Dialog) which have a button, next make intent for opening camera and other actions for create file for photo::
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.dialog_camera:
Uri uri = generateUriPhoto();
if(uri!=null) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
getActivity().startActivityForResult(cameraIntent, SubItemDetail.CAMERA_RESULT);
} else dismiss();
break;
case R.id.dialog_choose_photo:
break;
}
}
private Uri generateUriPhoto() {
file = createNameFile();
uri = null;
if (file != null) {
String aut = getActivity().getPackageName()+".fileprovider";
uri = getUriForFile(getActivity(), aut, file);
getActivity().grantUriPermission(getActivity().getPackageName(), uri,
Intent.FLAG_GRANT_READ_URI_PERMISSION |
Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
return uri;
}
public File getFile() {
return file;
}
public Uri getUri() { // onActivityResult
return uri;
}
private File createNameFile() {
directory = new File(getActivity().getFilesDir(), "images");
if (!directory.exists()) {
directory.mkdirs();
}
String name = "photo_" + System.currentTimeMillis();
File file = null;
try {
file = File.createTempFile(
name, /* prefix */
".jpg", /* suffix */
directory /* directory */
);
} catch (IOException e) {
e.printStackTrace();
dismiss();
}
return file;
}
Next on my activity:
.........
private Uri uri
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
CameraOrChoosePhotoDialog cameraOrChoosePhotoDialog = (CameraOrChoosePhotoDialog) getFragmentManager().findFragmentByTag("camera");
uri = cameraOrChoosePhotoDialog.getUri();// get uri from dialogfargment
if (resultCode == RESULT_OK) {
if (requestCode == CAMERA_RESULT) {
image.setImageURI(uri);
addPicToGallery(); // try to put photo in gallery
cameraOrChoosePhotoDialog.dismiss(); // close dialog
}
}
}
private void addPicToGallery() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uri));
mediaScanIntent.setData(uri));
sendBroadcast(mediaScanIntent);
}
but the photo does not appear in the gallery
Try to convert the captured file into the image format such as .jpeg, .png etc. and then store it into the device local storage or SD card.
Replace your
private void addPicToGallery() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uri));
mediaScanIntent.setData(uri));
sendBroadcast(mediaScanIntent);
}
with
private void addPicToGallery() {
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uri));
mediaScanIntent.setData(Uri.fromFile(file)));
sendBroadcast(mediaScanIntent);
}
somehow initial uri from FileProvider is different from uri you get from actual file :)
Related
I have a project witch have permission to camera and storage.
When the user click in some buttons the camera will be open by intent and take picture then saved it in the device to add it to firebase storage.
This operation was successful on most devices, but in Redmi A8(Android 10 , MIUI 12.0.1) it
was failed , the camera open then the application stop , maybe it failed to save the picture or failed to get it in ActicityResult.
Who I can solve it ?
Note: This is a part of methods in my code.
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) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(getActivity(),
"com.apps.android.fileprovider", photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
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,
".jpg",
storageDir
);
currentPhotoPath = image.getAbsolutePath();
return image;
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File f = new File(currentPhotoPath);
//showImage.setImageURI(Uri.fromFile(f));
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
getActivity().sendBroadcast(mediaScanIntent);
uploadImageToFirebase(f.getName(), contentUri);
}
}
}
private void uploadImageToFirebase(String name, Uri contentUri) {
final StorageReference image = storageReference.child("pictures/" + name);
image.putFile(contentUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
image.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference().child("Shifts").child(empId+"").
child(shiftKey).child(shiftImageType).setValue(uri+"");
alertDialog.dismiss();
}
});
startActivity(new Intent(getActivity() , MainActivity.class));
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getActivity(), e.getMessage()+"", Toast.LENGTH_SHORT).show();
}
});
}
I am trying to allow users to select an image from camera and gallery and update an image view with the selected image. I am successful in doing so if a user selects a picture from their gallery, however if they choose to take a picture with their camera I keep getting a null value. I am unsure as to why, I have all the necessary permission in my manifest file such as write and from read external storage.
//Creates popup and allows user to select book image from gallery or camera.
public void selectImageMenu(final View v) {
PopupMenu popup = new PopupMenu(v.getContext(), v);
popup.getMenuInflater().inflate(R.menu.gallery_menu, popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.openCamera:
openCamera();
return true;
case R.id.openGallery:
openGallery();
return true;
default:
return true;
}
}
});
popup.show();
}
//checks permission and if it's granted allows user the choice of choosing an image from gallery or camera
public void uploadImagePost(View view) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
} else {
selectImageMenu(view);
}
}
//opens camera to allow user to take a picture.
public void openCamera() {
Intent takePicture = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePicture, 0);//zero can be replaced with any action code
}
//opens gallery to allow user to choose a book image
public void openGallery() {
Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(pickPhoto, 1);//one can be replaced with any action code
}
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
switch (requestCode) {
case 0:
if (resultCode == RESULT_OK) {
selectedImageUri = imageReturnedIntent.getData();
Glide
.with(CreatePostActivity.this)
.load(selectedImageUri)
.placeholder(R.drawable.bookshelf)
.into(bookImage);
}
break;
case 1:
if (resultCode == RESULT_OK) {
selectedImageUri = imageReturnedIntent.getData();
Glide
.with(CreatePostActivity.this)
.load(selectedImageUri)
.placeholder(R.drawable.bookshelf)
.fitCenter()
.into(bookImage);
break;
}
}
}
try this in your code
case 0:
if (resultCode == RESULT_OK) {
Bundle extras = imageReturnedIntent.getExtras();
bitmap = (Bitmap)extras.get("data");
bookImage.setImageBitmap(bitmap);
}
there is another approach which is, store image into external file directory before you load image.
check this
btnCamera.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
File pictureFile = null;
pictureFile = getPictureFile();
if (pictureFile != null) {
Uri photoURI = FileProvider.getUriForFile(activity,
"com.xyx.yourproject",pictureFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(cameraIntent,CAMERA_REQUESTCODE);
}
}
dialog.dismiss();
}
});
to save to location and fetch the path of the image
private File getPictureFile() {
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String pictureFile = "pic_" + timeStamp;
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = null;
try {
image = File.createTempFile(pictureFile, ".jpg", storageDir);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(activity,
"Photo file can't be created, please try again",
Toast.LENGTH_SHORT).show();
}
pictureFilePath = image.getAbsolutePath();
return image;
}
and at last, in onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUESTCODE && resultCode == RESULT_OK) {
File imgFile = new File(pictureFilePath);
/** use imgFile to print into your image view---code to print the image*/
} else if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK) {
/**-------your code*/
}
}
and for getting permission to access a local file storage directory, in your manifest file add these
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.xyz.yourpath"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/paths" />
</provider>
you have to create a resource file 'paths' specifying your external-path in res/xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="yourfiles"
path="Android/data/com.xyz.yourpackagename/files/Pictures" />
</paths>
now the images will be stored to an external path so you can use the file path to print the image into the image view
To get proper image from camera you have to provide File that camera app can write to:
static final int REQUEST_TAKE_PHOTO = 1;
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) {
// Error occurred while creating the File
...
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
And then on activity result with REQUEST_TAKE_PHOTO just read file that you created with createImageFile or thumbnail Bitmap object that will be in returned as extras 'data' field
You can find all answers here: https://developer.android.com/training/camera/photobasics#java
I'm trying to take a picture, save it on the internal storage and then show it in a imageview (cause i can't access internal storage and look for the image).
Taking the picture seems to work but loading the image to the imageview with the uri isn't working
(the uri returned by the intent is: "file:/data/user/0/com.packagename/filesfoldername/filename"). imageview stays empty.
private static String date = new SimpleDateFormat("ddMMyyy").format(new Date());
private File sessionDirectory=null;
private ImageView imgView;
private Uri HelpUri;
#override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode)
{
case REQUEST_IMAGE_CAPTURE:
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK) {
Toast.makeText(this, "Image Saved!", Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Uri= " + HelpUri, Toast.LENGTH_LONG).show();
}
else
Toast.makeText(this, "Error Taking Photo!", Toast.LENGTH_SHORT).show();
break;
}
}
//Method creates an Intent to the camera - Capture an Image and save it//
private void openCamera(String Pose) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
File ImageFile = null;
try {
ImageFile = createImageFile(Pose);
} catch (IOException ex) {
//Something for errors..
}
if (ImageFile != null) {
Uri ImageURI = android.net.Uri.parse(ImageFile.toURI().toString());
HelpUri = ImageURI;
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, ImageURI);
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
else
Toast.makeText(this, "Problem Accessing Internal Storage", Toast.LENGTH_SHORT).show();
}
}
//Methods returns a File for the image file created on the internal storage//
private File createImageFile(String Pose) throws IOException {
if(sessionDirectory==null)
createSessionFolder();
if(sessionDirectory!=null) { //Succeed creating/finding the session directory
return File.createTempFile(
Pose, /* prefix */
".jpg", /* suffix */
sessionDirectory /* directory */
);
}
else
return null;
}
//Method creates the session directory - update the field if existed, creates it if not//
private void createSessionFolder() {
sessionDirectory = new File(getFilesDir()+"Session_"+date);
if (!sessionDirectory.exists())
if(!sessionDirectory.mkdirs()) //Tried to create the directory buy failed
sessionDirectory = null;
}
I would be greatfull if anyone can help.
Thank you very much
private static final int REQUEST_IMAGE_CAPTURE = 1;
private String picture_directory = "/picturedir/";
public void openCamera(Context context) {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(context.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
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri urifromFile = FileProvider.getUriForFile(context,
BuildConfig.APPLICATION_ID + ".provider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
urifromFile);
context.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 = "JPEG_" + timeStamp + "_";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES+picture_directory);
storageDir.mkdirs();
image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return image;
}
Add provider path to res/xml folder. And declare it on AndroidManifest.xml. More information on here File Provider
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.package"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
Also do not forget to get permission from user.
public void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
I have went through several documentation and stacks, however I'm not quite sure how do I implement this...
And help or sample codes would really help me understand more.
Here are the sets of codes that runs the camera and it's working perfectly fine, my next question is, how do I let it automatically saved into phone gallery?
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
tvCameraTiles = (TextView) findViewById(R.id.tvCameraTiles);
tvCameraTiles.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dispatchTakePictureIntent();
}
});
}
private void dispatchTakePictureIntent()
{
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null)
{
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK)
{
//Get Camera Image File Data
// Bundle extras = data.getExtras();
// Bitmap imageBitmap = (Bitmap) extras.get("data");
// mImageView.setImageBitmap(imageBitmap);
}
}
have you read this https://developer.android.com/training/camera/photobasics.html ?
Especially the part:
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);
}
You don't seem to save the photo in the external storage, so it should work.
EDIT: I tried to make a really basic application following the documentation with the method galleryAddPic.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button photoButton = (Button) findViewById(R.id.photobutton);
photoButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
dispatchTakePictureIntent();
}
});
}
static final int REQUEST_IMAGE_CAPTURE = 1;
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
//Bundle extras = data.getExtras();
//Bitmap imageBitmap = (Bitmap) extras.get("data");
//mImageView.setImageBitmap(imageBitmap);
galleryAddPic();
}
}
String mCurrentPhotoPath;
private File createImageFile() throws IOException {
File storageDir = Environment.getExternalStorageDirectory();
File image = File.createTempFile(
"example", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
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) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
}
}
}
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);
}
This is working for me! I take a picture using the camera app, and then it's showed in the gallery app.
I modified the code regarding the FileProvider part, now it passes the Uri with the help of the method Uri.fromFile(photoFile). I save the photo in a different position too, check the code in the method createImageFile for this one.
In the Android Studio emulator is working fine, let me know about you.
I tried out Rex B code snippet, but ended up getting a error on Android Studio.
android.os.FileUriExposedException: file:///storage/emulated/0/example6941495009290613124.jpg exposed beyond app through ClipData.Item.getUri()
If anyone got this error, I found a simple fix
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
I added these two lines to the onClick method
Button photoButton = (Button) findViewById(R.id.photobutton);
photoButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
dispatchTakePictureIntent();
}
});
}
I know this is old post, but I'm sure someone will come by this one day.
First the file will be created and the ByteStream will be written on the file and saved. you don't do anything for this file to be present in the gallery. This will automatically refreshed by gallery.
I have experimented for past 1 week with most of the stackoverflow threads but couldn't find a comprehensive solution, but all the threads helped me. Here is the working code which I have tested in Android 11,12 and 13(Google Pixex 6a)
AndroidManifest.xml will have the following
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/provider_paths"/>
</provider>
This what I have mentioned in provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
call the below method on onclick event
dispatchTakePictureIntent();
In onActivityResult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch(requestCode) {
case STApplication.SHOW_TAKEPICTURE:
//Uri selectedImage=null;
if (resultCode == Activity.RESULT_OK) {
try{
//Bundle extras = data.getExtras();
Bitmap imageBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), OldURI);
//galleryAddPic();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
try {
saveImageInAndroidApi29AndAbove(imageBitmap);
} catch (Exception e) {
//show error to user that operatoin failed
}
} else {
saveImageInAndroidApi28AndBelow(imageBitmap);
}
btnPicture.setText(getString(R.string.picture_taken));
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
}
Then finally include all the below methods and variables inside your activity class
String currentPhotoPath;
Uri ImageURI;
public static final int SHOW_TAKEPICTURE = 99;
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) {
// Error occurred while creating the File
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
BuildConfig.APPLICATION_ID + ".provider",
photoFile);
ImageURI=photoURI;
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, SHOW_TAKEPICTURE);
}
}
}
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, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = image.getAbsolutePath();
return image;
}
private boolean saveImageInAndroidApi28AndBelow(Bitmap bitmap) {
OutputStream fos;
String imagesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).toString();
File image = new File(imagesDir, "IMG_" + System.currentTimeMillis() + ".png");
try {
fos = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.PNG, 95, fos);
Objects.requireNonNull(fos).close();
} catch (IOException e) {
e.printStackTrace();
//isSuccess = false;
return false;
}
//isSuccess = true;
return true;
}
#NonNull
public Uri saveImageInAndroidApi29AndAbove(#NonNull final Bitmap bitmap) throws IOException {
final ContentValues values = new ContentValues();
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "IMG_" + System.currentTimeMillis());
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
}
final ContentResolver resolver = getApplicationContext().getContentResolver();
Uri uri = null;
try {
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
uri = resolver.insert(contentUri, values);
if (uri == null) {
//isSuccess = false;
throw new IOException("Failed to create new MediaStore record.");
}
try (final OutputStream stream = resolver.openOutputStream(uri)) {
if (stream == null) {
//isSuccess = false;
throw new IOException("Failed to open output stream.");
}
if (!bitmap.compress(Bitmap.CompressFormat.PNG, 95, stream)) {
//isSuccess = false;
throw new IOException("Failed to save bitmap.");
}
}
//isSuccess = true;
return uri;
} catch (IOException e) {
if (uri != null) {
resolver.delete(uri, null, null);
}
throw e;
}
}
I have a problem with "capture image with camera", and store it into Firebase. I think that the code is right, because it worked with "select image from gallery". The app stoped after capturing the image, and it didn't store it into the database. I think that it is a problem for android M and N (Android 6 and 7). There is also the error in logcat.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK){
mPregresDialog.setMessage("Uploading...");
mPregresDialog.show();
Uri uri = data.getData();
StorageReference filepath = mStorage.child("Photo").child(uri.getLastPathSegment());
filepath.putFile(uri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
mPregresDialog.dismiss();
Toast.makeText(MainActivity.this, "Upload Done", Toast.LENGTH_LONG).show();
}
});
}}
logcat:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getLastPathSegment()' on a null object reference
The problem is that your Uri does not get the image as it should so you need to create your own Uri for your image you capture.
You need to go to android documentation: https://developer.android.com/training/camera/photobasics.html#TaskPhotoView
For your app, you can also just copy and paste this code in your main activity:
String mCurrentPhotoPath;
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, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = 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) {
// Error occurred while creating the File...
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.android.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, CAMERA_REQUEST_CODE);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
storage = FirebaseStorage.getInstance().getReference();
b_gallery = (Button) findViewById(R.id.b_gallery);
b_capture = (Button) findViewById(R.id.b_capture);
iv_image = (ImageView) findViewById(R.id.iv_image);
progressDialog = new ProgressDialog(this);
b_capture.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
dispatchTakePictureIntent();
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK){
progressDialog.setMessage("Uploading...");
progressDialog.show();
Uri uri = data.getData();
StorageReference filepath = storage.child("Photos").child(uri.getLastPathSegment());
filepath.putFile(photoURI).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(MainActivity.this, "Upload Successful!", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(MainActivity.this, "Upload Failed!", Toast.LENGTH_SHORT).show();
}
});
}
}
}
And make sure you follow the documentation and have added the provider in your AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_paths"></meta-data>
</provider>
And the res/xml/file_paths.xml (you just make a directory under "res" folder and name it xml, then you create a resource file and name it file_paths.xml); then delete all the code inside it (it'll have some lines) and paste the following:
<?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/com.serjardovic.firebasesandbox/files/Pictures" />
</paths>
Make sure you CHANGE the com.serjardovic.firebasesandbox to your own package name!