Reputation: 5341
I am using intent to launch camera:
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
getParent().startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
and using:
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
photoImage.setImageBitmap(thumbnail);
photoImage.setVisibility(View.VISIBLE);
But it is only a thumbnail, how do I get the full bitmap? I know I can use my own Activity and use:
Camera.PictureCallback()
But is there anyway to do it using Intent?
Thanks!
edit:
I also tried:
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Uri uri = data.getData();
imageView.setImageURI(uri);
}
It works for photo selected from gallery, but for camera intent, data.getData() returns null.
Upvotes: 67
Views: 100205
Reputation: 6617
Ok time to pay back.
So you have your permissions in the manifest:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And you also have your provider metadata:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
One missed detail is (android:authorities applicationId) - you need to add this to your own app package name.
So you have xml
file under res
folder as we mentioned on manifest
and under it u have created file_paths
with:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path
name="my_images"
path="Pictures" />
</paths>
We are done with copy paste part 1. Now on our activity above onCreate(savedInstanceState: Bundle?)
define these beauties
val REQUEST_IMAGE_CAPTURE = 1
lateinit var currentPhotoPath: String
var cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
You might like to have a look at original resource but missing details as usual Android Developers : link
An other missing detail is packageName + ".fileprovider",
be careful u need to give your own package name if u already have method.
// org android developers
private fun dispatchTakePictureIntent() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
// Ensure that there's a camera activity to handle the intent
takePictureIntent.resolveActivity(packageManager)?.also {
// Create the File where the photo should go
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
ex.message
null
}
// Continue only if the File was successfully created
photoFile?.also {
val photoURI: Uri = FileProvider.getUriForFile(
this,
packageName + ".fileprovider",
it
)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
}
createImageFile
function
// org android developers
@Throws(IOException::class)
private fun createImageFile(): File {
// Create an image file name
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val storageDir: File = this!!.getExternalFilesDir(Environment.DIRECTORY_PICTURES)!!
return File.createTempFile(
"JPEG_${timeStamp}_", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
).apply {
// Save a file: path for use with ACTION_VIEW intents
currentPhotoPath = absolutePath
}
}
Testing.
Call your dispatchTakePictureIntent()
method with onClick event, make sure permissions are permitted
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {
var mBitmap_org = MediaStore.Images.Media.getBitmap(
this.getContentResolver(),
//Uri.parse(currentPhotoPath)
Uri.fromFile(File(currentPhotoPath))
);
//mImg_display?.setImageBitmap(mBitmap_org)
}
}
Don't check data we will get it through imagePath. If u are checking Uri.parse(currentPhotoPath)
make sure it's Uri.fromFile(File(currentPhotoPath))
Now you have your bitmap, time to spend other hours/days how to resize decode, save.
There is also a method to save token image, maybe you could help me to see where should I put it, if I need token image to be save on gallery
// org android developers
private fun galleryAddPic() {
Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE).also { mediaScanIntent ->
val f = File(currentPhotoPath)
mediaScanIntent.data = Uri.fromFile(f)
sendBroadcast(mediaScanIntent)
}
}
Upvotes: 2
Reputation: 158
API Level 29
I tried the accepted answer, but both Environment.getExternalStorageDirectory()
used in the accepted answer and Environment.getExternalStoragePublicDirectory()
used in a subsequent answer are deprecated in API level 29. So is the MediaStore.Images.Media.DATA
used in the third answer deprecated in API level 29. The following code (in Kotlin) stores the full image in MediaStore
as shown in this stackoverflow answer to a different question and doesn't rely on the FileProvider
:
var imageUri: Uri? = null
fun takePhoto(view: View?) {
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, "myimage.jpg")
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
startActivityForResult(intent, TAKE_PHOTO_REQUEST)
}
Upvotes: 1
Reputation: 16363
To get full sized camera image you should point camera to save picture in temporary file, like:
private URI mImageUri;
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
File photo;
try
{
// place where to store camera taken picture
photo = this.createTemporaryFile("picture", ".jpg");
photo.delete();
}
catch(Exception e)
{
Log.v(TAG, "Can't create file to take picture!");
Toast.makeText(activity, "Please check SD card! Image shot is impossible!", 10000);
return false;
}
mImageUri = Uri.fromFile(photo);
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
//start camera intent
activity.startActivityForResult(this, intent, MenuShootImage);
private File createTemporaryFile(String part, String ext) throws Exception
{
File tempDir= Environment.getExternalStorageDirectory();
tempDir=new File(tempDir.getAbsolutePath()+"/.temp/");
if(!tempDir.exists())
{
tempDir.mkdirs();
}
return File.createTempFile(part, ext, tempDir);
}
Then after image capture intent finished to work - just grab your picture from imageUri
using following code:
public void grabImage(ImageView imageView)
{
this.getContentResolver().notifyChange(mImageUri, null);
ContentResolver cr = this.getContentResolver();
Bitmap bitmap;
try
{
bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, mImageUri);
imageView.setImageBitmap(bitmap);
}
catch (Exception e)
{
Toast.makeText(this, "Failed to load", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Failed to load", e);
}
}
//called after camera intent finished
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
{
//MenuShootImage is user defined menu option to shoot image
if(requestCode==MenuShootImage && resultCode==RESULT_OK)
{
ImageView imageView;
//... some code to inflate/create/find appropriate ImageView to place grabbed image
this.grabImage(imageView);
}
super.onActivityResult(requestCode, resultCode, intent);
}
P.S. Code need to be revised with respect to new security restriction applied in Android M - FileProvider: mImageUri
has to be packed with FileProvider
Upvotes: 110
Reputation: 28875
Don't use onActivityResult
's data. It took me many hours to test different solutions. A camera saves a picture (even if you don't set permissions for camera and card reading in AndroidManifest), but then onActivityResult
returns data == null
and MediaStore
returns wrong path. In these solutions you simply get last gallery image, not your photo.
private Uri photoUri;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
...
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_RESULT) {
if (resultCode == RESULT_OK) {
if (photoUri != null) {
image.setImageURI(photoUri);
}
}
}
}
private void showCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getContext().getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
photoUri = null;
if (file != null) {
photoUri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
startActivityForResult(intent, CAMERA_REQUEST);
}
}
}
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
// File storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
return File.createTempFile(timeStamp, ".jpg", storageDir);
}
Upvotes: 2
Reputation: 157
To capture maximum picture size from camera, i hope these simple steps will be quite useful
public static Camera mCamera;
Camera.Parameters parameters = mCamera.getParameters();
parameters.getSupportedPictureSizes();
List<Camera.Size> supportedSizes = parameters.getSupportedPictureSizes();
mSizePicture1 = supportedSizes.get(0);
int cameraSize = supportedSizes.size();
mSizePicture2 = supportedSizes.get(cameraSize - 1);
if (mSizePicture1.height < mSizePicture2.height)
mSizePicture = supportedSizes.get(cameraSize - 1);
else
mSizePicture = supportedSizes.get(0);
parameters.setPictureSize(mSizePicture.width, mSizePicture.height);
Here, the supported size of the each mobile is taken, from that which size is maximum that is fixed as picture size to capture.
Upvotes: 0
Reputation: 514
I also used the answer from Vicky but I had to save the uri to a bundle to avoid loss of it on orientation change. So if you don't get a result from your intent after tilting the device it might be because your uri did not survive the orientation change.
static final int CAMERA_CAPTURE_REQUEST = 1;
static final String ARG_CURRENT_PIC_URI = "CURRENT_PIC_URI";
String pictureImagePath = folderName + "/" + imageFileName;
File file = new File(Environment.getExternalStorageDirectory(), pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);
mCurrentPicUri = outputFileUri.getPath();
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, CAMERA_CAPTURE_REQUEST);
Activity Result code:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_CAPTURE_REQUEST && resultCode == Activity.RESULT_OK)
{
File imgFile = new File(mCurrentPicUri);
// do something with your image
// delete uri
mCurrentPicUri = "";
}
}
save the uri to the bundle:
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save uri to bundle
outState.putString(ARG_CURRENT_PIC_URI, mCurrentPicUri);
}
retrieve it from your saved bundle during on create:
if (bundle.containsKey(ARG_CURRENT_PIC_URI))
mCurrentPicUri = bundle.getString(ARG_CURRENT_PIC_URI);
Upvotes: 2
Reputation: 15046
Even though this is an old question and it has an accepted answer,
I would like to share my solution.
In this case you don't have to create a temporary file.
Additionally we creating a chooser which offers to user both: take a picture with the camera or pick an existing one from a gallery.
Intent galleryIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Intent chooser = new Intent(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INTENT, galleryIntent);
chooser.putExtra(Intent.EXTRA_TITLE, getString(R.string.chooseaction));
Intent[] intentArray = {cameraIntent};
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray);
startActivityForResult(chooser, RESULT_LOAD_IMAGE);
and here we retrieving results:
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// todo use appropriate resultCode in your case
if (requestCode == RESULT_LOAD_IMAGE && resultCode == FragmentActivity.RESULT_OK) {
if (data.getData() != null) {
// this case will occur in case of picking image from the Gallery,
// but not when taking picture with a camera
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), data.getData());
// do whatever you want with the Bitmap ....
} catch (IOException e) {
e.printStackTrace();
}
} else {
// this case will occur when taking a picture with a camera
Bitmap bitmap = null;
Cursor cursor = getActivity().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_ADDED,
MediaStore.Images.ImageColumns.ORIENTATION}, MediaStore.Images.Media.DATE_ADDED,
null, "date_added DESC");
if (cursor != null && cursor.moveToFirst()) {
Uri uri = Uri.parse(cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)));
String photoPath = uri.toString();
cursor.close();
if (photoPath != null) {
bitmap = BitmapFactory.decodeFile(photoPath);
}
}
if (bitmap == null) {
// for safety reasons you can
// use thumbnail if not retrieved full sized image
bitmap = (Bitmap) data.getExtras().get("data");
}
// do whatever you want with the Bitmap ....
}
super.onActivityResult(requestCode, resultCode, data);
}
}
Upvotes: 6
Reputation: 5136
Open Camera and save image into some specific directory
private String pictureImagePath = "";
private void openBackCamera() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = timeStamp + ".jpg";
File storageDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
pictureImagePath = storageDir.getAbsolutePath() + "/" + imageFileName;
File file = new File(pictureImagePath);
Uri outputFileUri = Uri.fromFile(file);
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(cameraIntent, 1);
}
Handle Image
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
File imgFile = new File(pictureImagePath);
if(imgFile.exists()){
Bitmap myBitmap = BitmapFactory.decodeFile(imgFile.getAbsolutePath());
ImageView myImage = (ImageView) findViewById(R.id.imageviewTest);
myImage.setImageBitmap(myBitmap);
}
}
}
Upvotes: 44