I am trying to use the built-in camera application to take a photo and view it through an ImageView.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_photo);
addButtonListeners();
startCamera();
}
private void startCamera() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, PHOTO_TAKEN);
}
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (requestCode == PHOTO_TAKEN) {
Bundle extras = intent.getExtras();
photo = (Bitmap) extras.get("data");
if (photo != null) {
ImageView image = (ImageView) findViewById(R.id.image_background);
image.setImageBitmap(photo);
} else {
Toast.makeText(this, R.string.unable_to_read_photo, Toast.LENGTH_LONG)
.show();
}
}
}
When holding the phone in portrait position this code works just fine, however when I take the picture in landscape it breaks, any ideas why or how to solve this?
Question in not defined with enough details to answer it for sure, but my guess would be the same as Shani Goriwal .
It looks like problems with configuration changes event - which happens each time orientation is changed (from landscape to portrait).
Try to add to AndroidManifest of your app following lines:
android:configChanges="orientation|screenSize"
(more details: http://developer.android.com/guide/topics/resources/runtime-changes.html)
I found a tutorial that explains how to appropriately use the in built camera. Here is the link.
I am relativly new on android but from what I have read is the every time the display rotates android creates a new instance of some sort. So you have to save the instance of the rotation and this is done with the following code:
/**
* Here we store the file url as it will be null after returning from camera
* app
*/
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save file url in bundle as it will be null on scren orientation
// changes
outState.putParcelable("file_uri", fileUri);
}
/*
* Here we restore the fileUri again
*/
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// get the file url
fileUri = savedInstanceState.getParcelable("file_uri");
}
If you click on the link you should go to bullet number 11. Avoiding NullPointerException after taking camera picture. The real hero here is Ravi Tamada who does an excellent tutorial on using the camera. I recommend reading the whole tutorial.
Again I am new at this so if there is any corrections on what I have wrote here please correct.
Related
i am trying to open the camera and set a path to which the camera picture should be saved as shown in the following line:
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.mFileImgPath))
the problem i have is, if i took the picture while the camera in the portrait mode then 'onActivityResult' will be called normally and when i check 'mFileImgPath' it wil be not null. But when i use the same code and take a picture
in the landscape mode, then 'onActivityResult' will be called but always 'mFileImgPath' is null.
to invstigate further, i used the debugger and 'mFileImgPath' is always null if i tried to take a picture in the Lanscape mode. pleae have a look at the screen shot of the debugger
please let me know why the 'mFileImgPath' is always null in landscape mode? and how to olve it
code
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
this.mFileImgPath = new File(App.instance.getOutDir() + "/" + new Date().getTime());
Log.e(TAG, "mFileImgPath" + mFileImgPath);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.mFileImgPath));
debugger
as shown in the screen shot, the 'mFileImgPath' is null and when i click steo over the debugger skips the if-condition
This is known issue when working with inbuilt camera. In order to fix this you have to retain the uri via onSaveInstanceState() and onRestoreInstanceState().
Before your declare the startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE) , declare intent.putExtra(..) so:
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
Now put these 2 methods in your activity
/* Storing the file url as it'll be null after returning from camera app */
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// save file url in bundle as it will be null on scren orientation changes
outState.putParcelable("file_uri", fileUri);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// get the file url
fileUri = savedInstanceState.getParcelable("file_uri");
}
Do not try to access Intent in onActivityResult(int requestCode, int resultCode, Intent data) , the parameter data is most likely going to be null.
Your activity can be killed when the camera app is up. Activities not on fore ground can at any time be killed by Android.
You should #overide onSaveInstanceState and save the value of the path variable there. Then retrieve the value in onRestoreInstanceState.
My application is a portrait locked application. The application structure is based on one activity and multiple fragments. I am using support v4 fragments for this and fragments has nesting also. While I am trying to take pictures from the camera, for my profile update fragment. The camera app is open and I can capture and save the image. the image is getting in the onActivityResult() successfully.
But randomly the application orientation is getting distorted and its automatically change to landscape.Because of that, the current fragment state is missing. I locked the orientation from Manifest file as android: screenOrientation="portrait for my activity. This issue is mainly getting in Custom android phone (Samsung, HTC etc). I required a directional guideline, whether I need to create a custom camera or any alternate fix for this issue.
My Camera call method from my fragment is given below:
private void callCamera() {
try {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_SCREEN_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}catch (Exception e){
e.printStackTrace();
}
}
And I am getting the result in onActivityResult() of my Fragment as like this
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if( requestCode == CAMERA_REQUEST && resultCode == mActivity.RESULT_OK){
/**
* For Default Camera callback
*
*/
Bitmap image = (Bitmap) data.getExtras().get("data");
if(image != null){
AppUtility.mCapturedImage = image;
mIvProfileImg.setImageBitmap(image);
}
}
}
Simple solution will be handle it in onSaveInstanceState method.you cannot control camera intent rotation.setting your rotation to portrait and take picture in landscape mode it rotates your activity forcefully it loses its state.
I have an activity which the first thing it does is send a camera intent. I want the user to take a picture and then I will use it to do something. My problem is that If the user changes the rotation while taking the picture the app keeps on looping inside the camera until he finishes the entire process while staying in a single device orientation.
Here is the code:
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
_dateTextView = FindViewById<TextView> (Resource.Id.DateLabel);
ViewModel.RecomendDishViewModel.RecomendationSent += RecomendationSent;
if (IsThereAnAppToTakePictures())
{
CreateDirectoryForPictures();
var imageButton = FindViewById<ImageButton> (Resource.Id.TakeImageWaterMark);
_imageView = FindViewById<ImageView> (Resource.Id.UserDishImage);
imageButton.Click += TakePictureClicked;
if(_bitmap != null)
{
_imageView.RecycleBitmap ();
_imageView.SetImageBitmap(_bitmap);
}
}
_dateTextView.Click += DateLabelClicked;
TakePictureClicked ()
}
protected void TakePictureClicked ()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
_file = new Java.IO.File(_dir, String.Format("myPhoto_{0}.jpg", Guid.NewGuid()));
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(_file));
StartActivityForResult(intent, 0);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
// make it available in the gallery
Intent mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
Uri contentUri = Uri.FromFile(_file);
mediaScanIntent.SetData(contentUri);
SendBroadcast(mediaScanIntent);
// display in ImageView. We will resize the bitmap to fit the display
// Loading the full sized image will consume to much memory
// and cause the application to crash.
_bitmap = _file.Path.LoadAndResizeBitmap (518, 388);
if(_bitmap != null)
{
MemoryStream stream = new MemoryStream();
_bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
byte[] bitmapData = stream.ToArray();
ViewModel.RecomendDishViewModel.ImageData = bitmapData;
if(_imageView == null)
{
return;
}
_imageView.RecycleBitmap ();
_imageView.SetImageBitmap(_bitmap);
}
_file.Dispose ();
_dir.Dispose ();
}
My problem is that the activity gets recreated and then launches the camera app again. I have tried many things (this is the clean version) but nothing worked perfectly...
Any ideas?
This might not be exactly the solution you were looking for, but you could try simply locking screen rotation during the activity.
You can set this in the Android Manifest like so:
<activity android:name="MyActivity"
android:screenOrientation="portrait">
...
</activity>
This will keep the activity from redrawing when the device is rotated. Obviously you can replace "portrait" with "landscape" if you feel that a landscape layout would be more appropriate for your activity.
I'd recommend saving the state of the Activity like a Question before that I gave advice on.
Sadly, I'd failed. : )
Save State
To add to Slack Shots answer your really need to understand what is going on within the activity life cycle you either need to lock the orientation of your app and prevent changes or the better way (save state) or handle the orientation changes directly.
http://developer.android.com/training/basics/activity-lifecycle/recreating.html
Ok, so I have looked around a lot for this but I can't seem to find anyone else that's had this problem.
I am making a simple application just to test out working with the camera. Everything works up until I actually press the button to capture the image. When I do, instead of freezing and asking for confirmation that this is the picture I want, the confirmation button come up at the bottom, but the live feed from the camera keeps going.
I am using the most basic way of sending an intent to ask android to take a picture so I don't know why this is happening.
Here is the code:
private static final int IMAGE_CAPTURE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
addCaptureButtonListener();
}
private void addCaptureButtonListener() {
Button capture = (Button) findViewById(R.id.captureButton);
capture.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, IMAGE_CAPTURE);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(resultCode == RESULT_OK) {
if(requestCode == IMAGE_CAPTURE) {
Toast.makeText(this, "Image Successfully Taken", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
The camera feature depends vastly on the device you are using you may be using the correct method but sometimes it's the hardware issue. Also Please post the code, cross check if everything is fine from this example .
Capture Image from Camera and Display in Activity
try testing it on some other device if it works fine then look for the documentation of the bug for the device.
Edit
The problem is with the S4 it conflicts between the capture image resolution and the Preview image resolution the similar issues have been reported here too
Samsung Galaxy S4 , Image gets corrupted while taking from camera
Samsung galaxy S4 image capture Issue
your code is perfect it's just that the resolution camera clicks the image is not supported for the preview by the same device.
I am making a program that takes a picture and then shows it's thumbnail.
When using the emulator all goes well and the discard button deletes the photo.
But on a real device the camera intent saves the image at the imageUri variable and a second one that is named like if I had just opened up the camera and took a picture by itself.
private static final int CAMERA_PIC_REQUEST = 1337;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera);
//start camera
values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "New Picture");
values.put(MediaStore.Images.Media.DESCRIPTION,"From your Camera");
imageUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
image = (ImageView) findViewById(R.id.ImageView01);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, CAMERA_PIC_REQUEST);
//save the image buttons
Button save = (Button) findViewById(R.id.Button01);
Button close = (Button) findViewById(R.id.Button02);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) {
try{
thumbnail = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri);
image.setImageBitmap(thumbnail);
}
catch(Exception e){
e.printStackTrace();
}
}
else{
finish();
}
}
public void myClickHandler(View view) {
switch (view.getId()) {
case R.id.Button01:
finish();
break;
case R.id.Button02:
dicard();
}
}
private void dicard(){
getContentResolver().delete(imageUri, null, null);
finish();
}
Some Android phones store the original photo in the gallery, and a thumbnail only in your location. It doesn't matter what you did with the original request. I have two different HTC phones doing it, and a slew of other brands not doing it.
I solved this another way. I ran a query of every item in the gallery and loaded the BucketIDs to an array. I do this when my app starts the camera app. When the camera app returns, I make the same query (with items recently added to save time). I compare this to my original list and find the new BucketID. Next, I compare the size of this image with the file I explicitly set as the output. If it's bigger, I copy it, replacing what I had. Then I delete the file and remove it from the gallery.
Pain in the you-know-what!
[EDIT] I had to change this around again when I discovered a phone that didn't keep unique bucket IDs... See my post in the link following this answer for more.