Android Camera : data intent returns null - android

I have an android application which contains multiple activities.
In one of them I'm using a button which will call the device camera :
public void onClick(View view) {
Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(photoIntent, IMAGE_CAPTURE);
}
In the same activity I call the OnActivityResult method for the image result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK) {
Bitmap image = (Bitmap) data.getExtras().get("data");
ImageView imageview = (ImageView) findViewById(R.id.pic);
imageview.setImageBitmap(image);
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "CANCELED ", Toast.LENGTH_LONG).show();
}
}
}
The problem is that the intent data is null and the OnActivityResult method turns directly to the (resultCode == RESULT_CANCELED) and the application returns to the previous avtivity.
How can I fix this issue and after calling the camera, the application returns to the current activity which contains an ImageView which will contains the picture taken?
Thanks

The default Android camera application returns a non-null intent only when passing back a thumbnail in the returned Intent. If you pass EXTRA_OUTPUT with a URI to write to, it will return a null intent and the picture is in the URI that you passed in.
You can verify this by looking at the camera app's source code on GitHub:
https://github.com/android/platform_packages_apps_camera/blob/gingerbread-release/src/com/android/camera/Camera.java#L1186
Bundle newExtras = new Bundle();
if (mCropValue.equals("circle")) {
newExtras.putString("circleCrop", "true");
}
if (mSaveUri != null) {
newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
} else {
newExtras.putBoolean("return-data", true);
}
I would guess that you're either passing in EXTRA_OUTPUT somehow, or the camera app on your phone works differently.

I found an easy answer. it works!!
private void openCameraForResult(int requestCode){
Intent photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.parse("file:///sdcard/photo.jpg");
photo.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(photo,requestCode);
}
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "photo.jpg");
Uri uri = Uri.fromFile(file);
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmap = cropAndScale(bitmap, 300); // if you mind scaling
profileImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if you would like to crop and scale this image
public static Bitmap cropAndScale (Bitmap source, int scale){
int factor = source.getHeight() <= source.getWidth() ? source.getHeight(): source.getWidth();
int longer = source.getHeight() >= source.getWidth() ? source.getHeight(): source.getWidth();
int x = source.getHeight() >= source.getWidth() ?0:(longer-factor)/2;
int y = source.getHeight() <= source.getWidth() ?0:(longer-factor)/2;
source = Bitmap.createBitmap(source, x, y, factor, factor);
source = Bitmap.createScaledBitmap(source, scale, scale, false);
return source;
}

I´ve had experienced this problem, the intent is not null but the information sent via this intent is not received in onActionActivit()
This is a better solution using getContentResolver() :
private Uri imageUri;
private ImageView myImageView;
private Bitmap thumbnail;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
...
myImageview = (ImageView) findViewById(R.id.pic);
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "MyPicture");
values.put(MediaStore.Images.Media.DESCRIPTION, "Photo taken on " + System.currentTimeMillis());
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICTURE_RESULT);
}
the onActivityResult() get a bitmap stored by getContentResolver() :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_TAKE_PHOTO && resultCode == RESULT_OK) {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
myImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Check my example in github:
https://github.com/Jorgesys/TakePicture

Simple working camera app avoiding the null intent problem
- all changed code included in this reply; close to android tutorial
I've been spending plenty of time on this issue, so I decided to create an account and share my outcomes with you.
The official android tutorial "Taking Photos Simply" turned out to not quite hold what it promised.
The code provided there did not work on my device: a Samsung Galaxy S4 Mini GT-I9195 running android version 4.4.2 / KitKat / API Level 19.
I figured out that the main problem was the following line in the method invoked when capturing the photo (dispatchTakePictureIntent in the tutorial):
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
It resulted in the intent subsequently catched by onActivityResult being null.
To solve this problem, I pulled much inspiration out of earlier replies here and some helpful posts on github (mostly this one by deepwinter - big thanks to him; you might want to check out his reply on a closely related post as well).
Following these pleasant pieces of advice, I chose the strategy of deleting the mentioned putExtra line and doing the corresponding thing of getting back the taken picture from the camera within the onActivityResult() method instead.
The decisive lines of code to get back the bitmap associated with the picture are:
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
I created an exemplary app which just has the ability to take a picture, save it on the SD card and display it.
I think this might be helpful to people in the same situation as me when I stumbled on this issue, since the current help suggestions mostly refer to rather extensive github posts which do the thing in question but aren't too easy to oversee for newbies like me.
With respect to the file system Android Studio creates per default when creating a new project, I just had to change three files for my purpose:
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.simpleworkingcameraapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="takePicAndDisplayIt"
android:text="Take a pic and display it." />
<ImageView
android:id="#+id/image1"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
MainActivity.java :
package com.example.android.simpleworkingcameraapp;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ImageView image;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image1);
}
// copied from the android development pages; just added a Toast to show the storage location
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").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();
Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show();
return image;
}
public void takePicAndDisplayIt(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
}
#Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) {
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
image.setImageBitmap(bitmap);
}
}
}
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.simpleworkingcameraapp">
<!--only added paragraph-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph -->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note that the solution I found for the problem also led to a simplification of the android manifest file: the changes suggested by the android tutorial in terms of adding a provider are no longer needed since I am not making use of any in my java code. Hence, only few standard lines -mostly regarding permissions- had to be added to the manifest file.
It might additionally be valuable to point out that Android Studio's autoimport may not be capable of handling java.text.SimpleDateFormat and java.util.Date. I had to import both of them manually.

Probably because you had something like this?
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = CommonUtilities.getTBCameraOutputMediaFileUri();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, 2);
However you must not put the extra output into the intent, because then the data goes into the URI instead of the data variable. For that reason, you have to take the two lines in the middle out, so that you have
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 2);
That´s what caused the problem for me, hope that helped.

To Access the Camera and take pictures and set ImageView on Android
You have to use Uri file = Uri.fromFile(getOutputMediaFile()); for marshmallow.
Use below link to get path
https://androidkennel.org/android-camera-access-tutorial/

Kotlin code that works for me:
private fun takePhotoFromCamera() {
val intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA)
}
And get Result :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
val photo: Bitmap? = MediaStore.Images.Media.getBitmap(this.contentResolver, Uri.parse( data!!.dataString) )
// Do something here : set image to an ImageView or save it ..
imgV_pic.imageBitmap = photo
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "Camera , RESULT_CANCELED ")
}
}
}
and don't forget to declare request code:
companion object {
const val PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA = 300
}

After much try and study, I was able to figure it out. First, the variable data from Intent will always be null so, therefore, checking for !null will crash your app so long you are passing a URI to startActivityForResult.Follow the example below.
I will be using Kotlin.
Open the camera intent
fun addBathroomPhoto(){
addbathroomphoto.setOnClickListener{
request_capture_image=2
var takePictureIntent:Intent?
takePictureIntent =Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(takePictureIntent.resolveActivity(activity?.getPackageManager()) != null){
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
null
}
if (photoFile != null) {
val photoURI: Uri = FileProvider.getUriForFile(
activity!!,
"ogavenue.ng.hotelroomkeeping.fileprovider",photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
photoURI);
startActivityForResult(takePictureIntent,
request_capture_image);
}
}
}
}`
Create the createImageFile().But you MUST make the imageFilePath variable global. Example on how to create it is on Android official documentation and pretty straightforward
Get Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1 && resultCode == RESULT_OK) {
add_room_photo_txt.text=""
var myBitmap=BitmapFactory.decodeFile(imageFilePath)
addroomphoto.setImageBitmap(myBitmap)
var file=File(imageFilePath)
var fis=FileInputStream(file)
var bm = BitmapFactory.decodeStream(fis);
roomphoto=getBytesFromBitmap(bm) }}
The getBytesFromBitmap method
fun getBytesFromBitmap(bitmap:Bitmap):ByteArray{
var stream=ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
I hope this helps.

I used contentResolver to create the path and it worked.
var values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "MyPicture")
values.put(
MediaStore.Images.Media.DESCRIPTION,
"Photo taken on " + System.currentTimeMillis()
)
cameraUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, cameraUri);
startActivityForResult(cameraIntent, REQUEST_CODE)

it still occurs even now 2022, i fix it as follow:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // android7.0
photoUri= FileProvider.getUriForFile(
MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
} else {
photoUri = Uri.fromFile(new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
}
,oh...just add a viriable(photoUri) to your activity! then
filePathCallback.onReceiveValue(new Uri[]{ photoUri });

The following code works for me:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 2);
And here is the result:
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
{
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if(resultCode == RESULT_OK)
{
Uri selectedImage = imageReturnedIntent.getData();
ImageView photo = (ImageView) findViewById(R.id.add_contact_label_photo);
Bitmap mBitmap = null;
try
{
mBitmap = Media.getBitmap(this.getContentResolver(), selectedImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

Related

activityForResult has no extras, trying to start camera [duplicate]

I have an android application which contains multiple activities.
In one of them I'm using a button which will call the device camera :
public void onClick(View view) {
Intent photoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(photoIntent, IMAGE_CAPTURE);
}
In the same activity I call the OnActivityResult method for the image result :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == IMAGE_CAPTURE) {
if (resultCode == RESULT_OK) {
Bitmap image = (Bitmap) data.getExtras().get("data");
ImageView imageview = (ImageView) findViewById(R.id.pic);
imageview.setImageBitmap(image);
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "CANCELED ", Toast.LENGTH_LONG).show();
}
}
}
The problem is that the intent data is null and the OnActivityResult method turns directly to the (resultCode == RESULT_CANCELED) and the application returns to the previous avtivity.
How can I fix this issue and after calling the camera, the application returns to the current activity which contains an ImageView which will contains the picture taken?
Thanks
The default Android camera application returns a non-null intent only when passing back a thumbnail in the returned Intent. If you pass EXTRA_OUTPUT with a URI to write to, it will return a null intent and the picture is in the URI that you passed in.
You can verify this by looking at the camera app's source code on GitHub:
https://github.com/android/platform_packages_apps_camera/blob/gingerbread-release/src/com/android/camera/Camera.java#L1186
Bundle newExtras = new Bundle();
if (mCropValue.equals("circle")) {
newExtras.putString("circleCrop", "true");
}
if (mSaveUri != null) {
newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
} else {
newExtras.putBoolean("return-data", true);
}
I would guess that you're either passing in EXTRA_OUTPUT somehow, or the camera app on your phone works differently.
I found an easy answer. it works!!
private void openCameraForResult(int requestCode){
Intent photo = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = Uri.parse("file:///sdcard/photo.jpg");
photo.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(photo,requestCode);
}
if (requestCode == CAMERA_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
File file = new File(Environment.getExternalStorageDirectory().getPath(), "photo.jpg");
Uri uri = Uri.fromFile(file);
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
bitmap = cropAndScale(bitmap, 300); // if you mind scaling
profileImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if you would like to crop and scale this image
public static Bitmap cropAndScale (Bitmap source, int scale){
int factor = source.getHeight() <= source.getWidth() ? source.getHeight(): source.getWidth();
int longer = source.getHeight() >= source.getWidth() ? source.getHeight(): source.getWidth();
int x = source.getHeight() >= source.getWidth() ?0:(longer-factor)/2;
int y = source.getHeight() <= source.getWidth() ?0:(longer-factor)/2;
source = Bitmap.createBitmap(source, x, y, factor, factor);
source = Bitmap.createScaledBitmap(source, scale, scale, false);
return source;
}
I´ve had experienced this problem, the intent is not null but the information sent via this intent is not received in onActionActivit()
This is a better solution using getContentResolver() :
private Uri imageUri;
private ImageView myImageView;
private Bitmap thumbnail;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
...
...
myImageview = (ImageView) findViewById(R.id.pic);
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "MyPicture");
values.put(MediaStore.Images.Media.DESCRIPTION, "Photo taken on " + System.currentTimeMillis());
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, PICTURE_RESULT);
}
the onActivityResult() get a bitmap stored by getContentResolver() :
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_TAKE_PHOTO && resultCode == RESULT_OK) {
Bitmap bitmap;
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
myImageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Check my example in github:
https://github.com/Jorgesys/TakePicture
Simple working camera app avoiding the null intent problem
- all changed code included in this reply; close to android tutorial
I've been spending plenty of time on this issue, so I decided to create an account and share my outcomes with you.
The official android tutorial "Taking Photos Simply" turned out to not quite hold what it promised.
The code provided there did not work on my device: a Samsung Galaxy S4 Mini GT-I9195 running android version 4.4.2 / KitKat / API Level 19.
I figured out that the main problem was the following line in the method invoked when capturing the photo (dispatchTakePictureIntent in the tutorial):
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
It resulted in the intent subsequently catched by onActivityResult being null.
To solve this problem, I pulled much inspiration out of earlier replies here and some helpful posts on github (mostly this one by deepwinter - big thanks to him; you might want to check out his reply on a closely related post as well).
Following these pleasant pieces of advice, I chose the strategy of deleting the mentioned putExtra line and doing the corresponding thing of getting back the taken picture from the camera within the onActivityResult() method instead.
The decisive lines of code to get back the bitmap associated with the picture are:
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
I created an exemplary app which just has the ability to take a picture, save it on the SD card and display it.
I think this might be helpful to people in the same situation as me when I stumbled on this issue, since the current help suggestions mostly refer to rather extensive github posts which do the thing in question but aren't too easy to oversee for newbies like me.
With respect to the file system Android Studio creates per default when creating a new project, I just had to change three files for my purpose:
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.android.simpleworkingcameraapp.MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="takePicAndDisplayIt"
android:text="Take a pic and display it." />
<ImageView
android:id="#+id/image1"
android:layout_width="match_parent"
android:layout_height="200dp" />
</LinearLayout>
MainActivity.java :
package com.example.android.simpleworkingcameraapp;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.Image;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MainActivity extends AppCompatActivity {
private ImageView image;
static final int REQUEST_TAKE_PHOTO = 1;
String mCurrentPhotoPath;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = (ImageView) findViewById(R.id.image1);
}
// copied from the android development pages; just added a Toast to show the storage location
private File createImageFile() throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmm").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();
Toast.makeText(this, mCurrentPhotoPath, Toast.LENGTH_LONG).show();
return image;
}
public void takePicAndDisplayIt(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
File file = null;
try {
file = createImageFile();
} catch (IOException ex) {
// Error occurred while creating the File
}
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
}
}
#Override
protected void onActivityResult(int requestCode, int resultcode, Intent intent) {
if (requestCode == REQUEST_TAKE_PHOTO && resultcode == RESULT_OK) {
Uri uri = intent.getData();
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);
} catch (IOException e) {
e.printStackTrace();
}
image.setImageBitmap(bitmap);
}
}
}
AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.simpleworkingcameraapp">
<!--only added paragraph-->
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- only crucial line to add; for me it still worked without the other lines in this paragraph -->
<uses-permission android:name="android.permission.CAMERA" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note that the solution I found for the problem also led to a simplification of the android manifest file: the changes suggested by the android tutorial in terms of adding a provider are no longer needed since I am not making use of any in my java code. Hence, only few standard lines -mostly regarding permissions- had to be added to the manifest file.
It might additionally be valuable to point out that Android Studio's autoimport may not be capable of handling java.text.SimpleDateFormat and java.util.Date. I had to import both of them manually.
Probably because you had something like this?
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Uri fileUri = CommonUtilities.getTBCameraOutputMediaFileUri();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(takePictureIntent, 2);
However you must not put the extra output into the intent, because then the data goes into the URI instead of the data variable. For that reason, you have to take the two lines in the middle out, so that you have
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 2);
That´s what caused the problem for me, hope that helped.
To Access the Camera and take pictures and set ImageView on Android
You have to use Uri file = Uri.fromFile(getOutputMediaFile()); for marshmallow.
Use below link to get path
https://androidkennel.org/android-camera-access-tutorial/
Kotlin code that works for me:
private fun takePhotoFromCamera() {
val intent = Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(intent, PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA)
}
And get Result :
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA) {
if (resultCode == Activity.RESULT_OK) {
val photo: Bitmap? = MediaStore.Images.Media.getBitmap(this.contentResolver, Uri.parse( data!!.dataString) )
// Do something here : set image to an ImageView or save it ..
imgV_pic.imageBitmap = photo
} else if (resultCode == Activity.RESULT_CANCELED) {
Log.i(TAG, "Camera , RESULT_CANCELED ")
}
}
}
and don't forget to declare request code:
companion object {
const val PERMISSIONS_REQUEST_TAKE_PICTURE_CAMERA = 300
}
After much try and study, I was able to figure it out. First, the variable data from Intent will always be null so, therefore, checking for !null will crash your app so long you are passing a URI to startActivityForResult.Follow the example below.
I will be using Kotlin.
Open the camera intent
fun addBathroomPhoto(){
addbathroomphoto.setOnClickListener{
request_capture_image=2
var takePictureIntent:Intent?
takePictureIntent =Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(takePictureIntent.resolveActivity(activity?.getPackageManager()) != null){
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
// Error occurred while creating the File
null
}
if (photoFile != null) {
val photoURI: Uri = FileProvider.getUriForFile(
activity!!,
"ogavenue.ng.hotelroomkeeping.fileprovider",photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
photoURI);
startActivityForResult(takePictureIntent,
request_capture_image);
}
}
}
}`
Create the createImageFile().But you MUST make the imageFilePath variable global. Example on how to create it is on Android official documentation and pretty straightforward
Get Intent
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1 && resultCode == RESULT_OK) {
add_room_photo_txt.text=""
var myBitmap=BitmapFactory.decodeFile(imageFilePath)
addroomphoto.setImageBitmap(myBitmap)
var file=File(imageFilePath)
var fis=FileInputStream(file)
var bm = BitmapFactory.decodeStream(fis);
roomphoto=getBytesFromBitmap(bm) }}
The getBytesFromBitmap method
fun getBytesFromBitmap(bitmap:Bitmap):ByteArray{
var stream=ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
return stream.toByteArray();
}
I hope this helps.
I used contentResolver to create the path and it worked.
var values = ContentValues()
values.put(MediaStore.Images.Media.TITLE, "MyPicture")
values.put(
MediaStore.Images.Media.DESCRIPTION,
"Photo taken on " + System.currentTimeMillis()
)
cameraUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraIntent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, cameraUri);
startActivityForResult(cameraIntent, REQUEST_CODE)
it still occurs even now 2022, i fix it as follow:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // android7.0
photoUri= FileProvider.getUriForFile(
MainActivity.this,
BuildConfig.APPLICATION_ID + ".provider",
new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
} else {
photoUri = Uri.fromFile(new File(mCameraFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
}
,oh...just add a viriable(photoUri) to your activity! then
filePathCallback.onReceiveValue(new Uri[]{ photoUri });
The following code works for me:
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, 2);
And here is the result:
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent)
{
super.onActivityResult(requestCode, resultCode, imageReturnedIntent);
if(resultCode == RESULT_OK)
{
Uri selectedImage = imageReturnedIntent.getData();
ImageView photo = (ImageView) findViewById(R.id.add_contact_label_photo);
Bitmap mBitmap = null;
try
{
mBitmap = Media.getBitmap(this.getContentResolver(), selectedImage);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

Bitmap of size zero saved from Camera App on cancel

I was following the android tutorial as follows from this official link
I wish to save the full Image. The problem is when the user enters the camera app takes a photo but decides to cancel it, android still saves the image with size zero. Any way to avoid this?
The code is as follows
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) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
Ok solved it using the name of the newly created file. When we create name of file we simply save the path of the file in a String variable say "Current Path"
And add the following code-
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == Activity.RESULT_CANCELED && requestCode == 0)
{
File file = new File(currentPath);
boolean delete = file.delete();
Log.i("delete",String.valueOf(delete));
}
}
I think you are doing something wrong in your code. You should post your code to get the proper assistance.
as far as I understand . You should override the onbackpressed function. you should close/release camera here. In this case I think the camera would not take and save picture.

How does "putExtra" work?

I'm following along on this example:
http://developer.android.com/training/camera/photobasics.html
If you Ctrl-F for this putExtra(MediaStore.EXTRA_OUTPUT it'll take you to a segment of code I'm unsure of. Further up in the app, they override onActivityResult and try to pull the image from this intent out of the activity result to display in the app, but when I was doing this the Intent arg in onActivityResult was null. I tried changing my putExtra to take "data" instead of MediaStore.EXTRA_OUTPUT and suddenly it works perfectly.
Can anyone explain what this tutorial is trying to get me to do?
So basically, the code in question:
static final int REQUEST_IMAGE_CAPTURE = 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) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
}
#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);
}
}
Intent data in onActivityResult is null, so it'd crash when i called getExtras. I changed dispatchTakePictureIntent to putExtra("data", Uri.fromFile(photoFile)); and it works.
I'm just confused if this is a blunder on Google's part and made a mistake in their tutorial, or if I did something wrong / don't understand? Only reason I thought to make this change is because it uses the string data when it calls extras.get("data"). So I don't even understand my solution :(
putExtra("NameOfExtra", object)
so they are getting an extra named "data" - the string is the NAME of the extra value that was previously put.

IMAGE_CAPTURE on resultActivity the file doesn't exist yet

This a rare case, i'm trying to capture an image from native camera activity on my samsung galaxy s3 and onActivityResult the file doesn't exist to read yet. If i disconnect the phone and connect again then the i can see the image on my explorer.
It likes that the camera activity writes the file with delay or something...
i have readed all questions and answers and other forums, but it is my problem; My code:
... onCreate
File file = new File( _path );
pathUri = Uri.fromFile( file );
...
protected void startCameraActivity()
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, pathUri);
startActivityForResult( intent, CAMERA_REQUEST_CODE );
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK)
{
// test if exits image
if((new File(_path)).exists())
... do something
}
... continue
if((new File(_path)).exists()) always retunrs FALSE, how is it possible?
Thans in advance
I have never seen this occur in my app. However, this could potentially be a workaround.
Note: Declare the Uri instance initialURI globally so you can use it throughout the Activity. You could also change the name to something that suits your naming convention.
In this, right before the Intent is triggered, I pass a specific path for the Image to be stored at along with the name for the File.
Intent getCameraImage = new Intent("android.media.action.IMAGE_CAPTURE");
File cameraFolder;
if (android.os.Environment.getExternalStorageState().equals
(android.os.Environment.MEDIA_MOUNTED))
cameraFolder = new File(android.os.Environment.getExternalStorageDirectory(),
"SOME_FOLDER_NAME/");
else
cameraFolder= StatusUpdate.this.getCacheDir();
if(!cameraFolder.exists())
cameraFolder.mkdirs();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
String timeStamp = dateFormat.format(new Date());
String imageFileName = "picture_" + timeStamp + ".jpg";
File photo = new File(Environment.getExternalStorageDirectory(),
"SOME_FOLDER_NAME/" + imageFileName);
getCameraImage.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
initialURI = Uri.fromFile(photo);
startActivityForResult(getCameraImage, ACTION_REQUEST_CAMERA);
And finally, in the onActivityResult():
Note: This I'm guessing should work. My application uses the Aviary SDK and the code for that differs vastly from the conventional work done in this method.
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST_CODE && resultCode == RESULT_OK) {
// USE EITHER THIS
imgView.setImageURI(initialURI);
// OR USE THIS
getContentResolver().notifyChange(initialURI, null);
ContentResolver cr = getContentResolver();
try {
// SET THE IMAGE FROM THE CAMERA TO THE IMAGEVIEW
Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(cr, initialURI);
// SET THE IMAGE USING THE BITMAP
imgvwSelectedImage.setImageBitmap(bitmap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
If you do not need the the Image stored on the SD-Card, you could delete it once you are done with it. This I am guessing (guessing because I have never experienced what the OP is facing problem with) this should do it for you.
Oh. Almost forgot. You will need to declare this permission in your Manifest file:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Android Camera Intent woes

Hope someone may give some pointers (or an out right answer)...
Simple app, take an image using the built-in camera app, save the image to a separate application. Be done.
Problem: The camera application saves the image in the default app location (/mnt/sdcard/external_sd/DCIM/Camera) as well as my custom path (in code below).
Both files are exactly the same except for the file name. The external_sd file (the one I want gone) is saved with dashes (-) vs my custom file path saved with underscores. File sizes are exactly the same.
How can I stop this double image issue?
Is there an extra intent option I'm missing?
Or am I doing this completely wrong, missing something?
I'm using a Galaxy S Vibrant.
Code snippet:
private static Uri _outputFileUri;
private static File _file;
private ImageView _image;
private SimpleDateFormat _simpleDateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
_takePicture = (Button) findViewById(R.id.takePicture);
_takePicture.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
startActivityForResult(_intent, CAMERA_ACTIVITY);
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Activity cancelled", Toast.LENGTH_LONG).show();
return;
}
switch (requestCode) {
case CAMERA_ACTIVITY:
if (resultCode == RESULT_OK) {
try{
Bitmap b = MediaStore.Images.Media.getBitmap(getContentResolver(), _outputFileUri);
_image.setImageBitmap(b);
_image.invalidate();
}
catch(Exception e){
e.printStackTrace();
}
}
break;
}
}
This is device-dependent behavior. My observation is that HTC devices do not have this duplication problem, but Samsung devices do.
Please remove the following lines:
_file = new File(Environment.getExternalStorageDirectory() +
"/Android/data/my own folder/files/",
_simpleDateFormat.format(new Date()).toString() +
".jpg");
_outputFileUri = Uri.fromFile(_file);
_intent.putExtra(MediaStore.EXTRA_OUTPUT, _outputFileUri);
Also update the code to get the image from intent:
Bitmap b = (Bitmap) data.getExtras().get("data");
_image.setImageBitmap(b);
_image.invalidate();
This way picture wouldn't be saved on sd card or default location.
I had the same problem and gave up. Sometime later I found out that I was not getting it anymore and I'm not sure what change I made to my code, but I think that it was MediaStore's fault (check my unsolved question: Weird camera Intent behavior)
As you already have the image URI, why don't you use it to set the ImageViews' bitmap?
// void setImageURI(Uri uri)
_image.setImageBitmap(_outputFileUri);
I had this issue and here is how i solved it :
File createImageFile() throws IOException{
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String filename = "IMG_"+timestamp+"_";
File image = File.createTempFile(filename,".jpg",mGalleryFolder );
if (image.length() == 0 ){
boolean delete = image.delete();
}
mLocation = image.getAbsolutePath();
return image;
}
It's not exactly solving but works for me ;)

Categories

Resources