4

I referred to Grafika's CameraCaptureActivity to record video while simultaneously displaying the camera preview.

The changes I have made to the code (that is relevant) is -

The user clicks a button to launch PreferencesActivity, selects the preferred camera resolution (which stores the width and height values) and clicks the "Back" button to return to the CameraCaptureActivity.

In the openCamera method- Instead of hard coding width and height I am picking the values from SharedPreferences

The AspectFrameLayout's attribute is set this way android:background="@android:color/holo_blue_bright". So the preview is matching the size of the AspectFrameLayout

This problem occurs mostly when the size is being changed from a bigger resolution to a smaller one.

In smaller screens (HTC One M7 / Xperia SP) Distorted camera preview in HTC

In larger screens (Samsung Galaxy Tab S / Nexus 9) - Distorted camera preview in Samsung Tab S

I have noticed that this happens because onSurfaceChanged gets called twice. The first time it is with wrong values for width and height and the second time it is with the correct values.

However, the layout looks fine if I leave the activity and come back to it without making any changes. (Like going to PreferencesActivity and clicking "Back" without changing the resolution.)

I have set the following in AndroidManifest.xml -

<activity android:name=".activity.camera.CameraCaptureActivity"
 android:launchMode="singleInstance"
 android:screenOrientation="landscape"
 android:theme="@android:style/Theme.Holo.Light.NoActionBar">
</activity>

EDIT: This issue occurs with only the preview. The recorded video is sized correctly.

EDIT 2: This is my layout.xml

    <RelativeLayout xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cameracapturescreen_rootparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
tools:context="com.myapp.CameraCaptureActivity">

<com.myapp.activity.camera.PreviewFrameLayout
    android:id="@+id/surfaceview_framelayout"
    android:layout_width="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_centerVertical="true"
    android:background="@android:color/holo_blue_bright"
    android:layout_height="wrap_content">

    <android.opengl.GLSurfaceView
        android:id="@+id/cameraPreview_surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="left"/>

</com.myapp.activity.camera.PreviewFrameLayout>

I am sure I am passing the correct values to set the width and height of the view because the preview is set correctly if I leave the activity and come back to it without making any changes. (Like going to another activity and clicking "Back" to return to CameraCaptureActivity.)

ForeverNoob
  • 141
  • 1
  • 14

2 Answers2

1

Use this to open camera

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);    
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI); 
startActivityForResult(i, CAMERA_RESULT);

Here is the MyFileContentProvider class

public class MyFileContentProvider extends ContentProvider {

 public static final Uri CONTENT_URI = Uri.parse("content://com.algorithmapps.dmsimagesave/");

 private static final HashMap<String, String> MIME_TYPES = new         HashMap<String, String>();

 static {

  MIME_TYPES.put(".jpg", "image/jpeg");

  MIME_TYPES.put(".jpeg", "image/jpeg");

 }

 @Override

 public boolean onCreate() {

  try {

   File mFile = new File(getContext().getFilesDir(), "newImage.jpg");

   if(!mFile.exists()) {

mFile.createNewFile();

   }

   getContext().getContentResolver().notifyChange(CONTENT_URI, null);

   return (true);

  } catch (Exception e) {

   e.printStackTrace();

   return false;

  }

 }

 @Override

 public String getType(Uri uri) {

  String path = uri.toString();

  for (String extension : MIME_TYPES.keySet()) {

   if (path.endsWith(extension)) {

    return (MIME_TYPES.get(extension));

   }

  }

  return (null);

 }

 @Override

 public ParcelFileDescriptor openFile(Uri uri, String mode)

 throws FileNotFoundException {

  File f = new File(getContext().getFilesDir(), "newImage.jpg");

  if (f.exists()) {

   return (ParcelFileDescriptor.open(f,

     ParcelFileDescriptor.MODE_READ_WRITE));

  }

  throw new FileNotFoundException(uri.getPath());

 }

 @Override

 public Cursor query(Uri url, String[] projection, String selection,

   String[] selectionArgs, String sort) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public Uri insert(Uri uri, ContentValues initialValues) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public int update(Uri uri, ContentValues values, String where,

   String[] whereArgs) {

  throw new RuntimeException("Operation not supported");

 }

 @Override

 public int delete(Uri uri, String where, String[] whereArgs) {

  throw new RuntimeException("Operation not supported");

 }

} 

In onActivityResultMethod get image like this

 if (resultCode == RESULT_OK && requestCode == CAMERA_RESULT) {

       File out = new File(getFilesDir(), "newImage.jpg");

         if(!out.exists()) {

                Toast.makeText(getBaseContext(),

                  "Error while capturing image", Toast.LENGTH_LONG)

                  .show();


       }             
          originalBitmap = BitmapFactory.decodeFile(out.getAbsolutePath());   
    }

than resize bitmap using this code,here i am resizing for 200 width * 200 height

BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;

Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, 200, 200, false);

This method wont let your resized image Distorted. Hope it helps.

1

I am not clear with what you are trying to say if the problem is with the preview .. then you can use the following code in your open camera method

add this thing code in your openCamera() method , i just checked with this ... hope this helps

    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
        mCamera.setDisplayOrientation(90);
    } else {
        mCamera.setDisplayOrientation(180);
    }

Add this code in your handleSetSurfaceTexture() method

    if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
        mCamera.setDisplayOrientation(90);
     } else {
        mCamera.setDisplayOrientation(180);
    }
          Camera.Parameters parms = mCamera.getParameters();

          CameraUtils.choosePreviewSize(parms, mCameraPreviewWidth, mCameraPreviewHeight);

          // Give the camera a hint that we're recording video.  This   can have a big
          // impact on frame rate.
          parms.setRecordingHint(true);
          mCamera.setParameters(parms);

and this part of code in your onPause()

InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(((EditText)findViewById(R.id.username)).getWindowToken(), 0);

if(imm.isAcceptingText()) {
Intent intent = new Intent(this, CameraCaptureActivity.class);
startActivity(intent);
}
Preethi Rao
  • 5,117
  • 1
  • 16
  • 29
  • Yes, this code is already there and the issue is with the preview. The recorded video is fine. Like I said in the question, `onSurfaceChanged` gets called twice and the first time is with arbitrary values for the Height and Width of the surface. That is causing the Surface width and height to be set to the first set of wrong (and lower) values. – ForeverNoob Mar 31 '15 at 03:45
  • @ShreyaBS i dont think that will cause the problem cause second time it will be called with proper values, we had the same issue once we got our preview rotated , it was the issue with the opengl part... try checking Texture2dProgram class . – Preethi Rao Apr 01 '15 at 05:17
  • and also check in camerasurfacehandler onDrawframe method.. In this check with fullScreen object – Preethi Rao Apr 01 '15 at 05:18
  • Yes, I get this issue if the orientation changes. I checked the FullScreen object in OnDrawFrame, it is getting the correct width and height values. I am not sure what to check in the Texture2DProgram class. I am not using any shader. The only program type I am using is "TEXTURE_EXT" What should I modify? – ForeverNoob Apr 06 '15 at 07:01
  • @ShreyaBS if the orientation doesn't change then everything is proper ? – Preethi Rao Apr 06 '15 at 07:11
  • Sorry for the late response. This code is still not working. Here are the logs I got after using your modifications - onSurfaceChanged() 1148x646 ; onSurfaceChanged() 2560x1440 ; handleSetSurfaceTexture() 1920X1080 ; And the preview seems to be about half the screen's width and height. I am using Samsung Galaxy Tab S. No changes in the issue I am having. – ForeverNoob Apr 13 '15 at 07:48
  • then the issue is with your layout .... you are passing parameter in dp only right ? – Preethi Rao Apr 13 '15 at 07:51
  • or you should pass the layout height and width as match parent – Preethi Rao Apr 13 '15 at 07:52
  • And the code flipped the preview over vertically. It's upside down. – ForeverNoob Apr 13 '15 at 08:04
  • that is rotation problem..according to the degree rotate the camera – Preethi Rao Apr 13 '15 at 08:05
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/75088/discussion-between-shreya-bs-and-preethi-rao). – ForeverNoob Apr 13 '15 at 08:24
  • 1
    Yes! This issue was happening because the previous screen had the Soft Keyboard still open while launching the CameraCaptureActivity. Closing it corrects the Preview size. Thank you. – ForeverNoob Apr 16 '15 at 09:28