使用自定义相机使用不同的Android设备会遇到很多问题

时间:2015-07-27 07:28:46

标签: java android camera

我在我的Zenfone 2,三星Galaxy S3,Nexus 7(2012)上使用自定义相机(包括后置摄像头和前置摄像头,甚至拍摄照片和录制视频),没有问题。

但是当尝试使用其他设备时,例如:Oppo,Sony Xperia M4,三星Galaxy S6。有一些问题:

  • Oppo:在我的应用程序中打开相机时发生崩溃,而默认的Oppo相机正常。

  • Sony xperia M4&三星galaxy S6:无法切换到前置摄像头。甚至,它挂了一段时间。但是,索尼和三星的默认相机都可以。

我的应用程序设置了以下代码以使用相机功能:

<uses-permission android:name = "android.permission.CAMERA" />

<activity
        android:windowSoftInputMode = "adjustPan"
        android:name = "ui.activity.camera.CustomCamera"
        android:configChanges = "orientation|screenSize|keyboardHidden"
        android:screenOrientation = "portrait" />

CustomCamera.java - 主要类

public class CustomCamera extends FragmentActivity {

/**
 * Single ton section
 */
public static singleton.Camera camera = singleton.Camera.getInstance();

/**
 * String section
 */
public static int current_orientation = 0;

/**
 * View section
 */
public static Camera mCamera;
public static Camera.CameraInfo mCameraInfo =
        new Camera.CameraInfo();

/**
 * A safe way to get an instance of the Camera object.
 */
public static Camera getCameraInstance(int camera_id) {
    Camera c = null;
    try {
        c = Camera.open(camera_id); // attempt to get a Camera instance
    } catch (Exception e) {
        // Camera is not available (in use or does not exist)
        e.printStackTrace();
    }

    return c; // returns null if mCamera is unavailable
}

/** OnCreate method **/
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_custom_camera);

    // Should initialize new Camera after released
    mCamera = null;
    initialCamera();
}

@Override
protected void onDestroy() {
    super.onDestroy();

    // Should release camera before go to the other page
    // Because it need release for the other camera apps using camera,
    // If it not release, current app will not allow the other app use
    releaseCamera();
}

@Override
public void onPause() {
    super.onPause();

    // Should release camera before go to the other page
    // Because it need release for the other camera apps using camera,
    // If it not release, current app will not allow the other app use
    if (CameraPreviewFragment.IS_RECORDING_VIDEO) {
        CustomCamera.mCamera.stopPreview();

        // release camera
        releaseCamera();
    }
}

@Override
protected void onResume() {
    super.onResume();

    // Re-initialize if camera already released after resume from background
    if (mCamera == null) {
        // Initialize camera again
        initialCamera();
    }
}

/**
 * Initial methods
 */

private void initialCamera() {
    // Back Camera
    mCamera = getCameraInstance(0);

    // Set Camera Display Orientation
    CameraPreviewFragment.setCameraDisplayOrientation(
            this, define.Camera.CAMERA_BACK);

    // Get orientation listener
    new OrientationEventListener(this) {
        @Override
        public void onOrientationChanged(int orientation) {
            getCurrentOrientation(orientation);
        }
    }.enable();
}

/**
 * Basic methods
 */

private int getCurrentOrientation(int orientation) {
    orientation = (orientation + 45) / 90 * 90;
    this.current_orientation = orientation % 360;

    return current_orientation;
}

public static void releaseCamera() {
    // Should release camera before go to the other page
    if (mCamera != null) {
        mCamera.release();
        mCamera = null;
    }
}

CameraPreview.java - 相机表面类

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;

public CameraPreview(Context context, Camera camera) {
    super(context);
    mCamera = camera;

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = getHolder();
    mHolder.addCallback(this);
    // deprecated setting, but required on Android versions prior to 3.0
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, now tell the mCamera where to draw the preview.
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // empty. Take care of releasing the Camera preview in your activity.
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // If your preview can change or rotate, take care of those events here.
    // Make sure to stop the preview before resizing or reformatting it.

    if (mHolder.getSurface() == null) {
        // preview surface does not exist
        return;
    }

    // stop preview before making changes
    try {
        mCamera.stopPreview();
    } catch (Exception e) {
        // ignore: tried to stop a non-existent preview
        e.printStackTrace();
    }

    // start preview with new settings
    try {
        // set preview size and make any resize, rotate or
        // reformatting changes here
        Camera.Parameters parameters = mCamera.getParameters();

        // Set the popular preview size & picture size
        // to apply for all android devices : Back camera only
        // If for Front camera, it will use default if not suitable
        for (Camera.Size size : parameters.getSupportedPictureSizes()) {
            if (1600 <= size.width & size.width <= 1920) {
                parameters.setPreviewSize(size.width, size.height);
                parameters.setPictureSize(size.width, size.height);
                break;
            }
        }

        // Set parameters for camera
        try {
            CustomCamera.mCamera.setParameters(parameters);
        } catch (Exception e) {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(mHolder);
                mCamera.startPreview();
            }
        }

        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (RuntimeException e) {
        e.printStackTrace();
    }
}
}

CameraPreviewFragment.java - 加载自定义相机预览的类

 @Override

 public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View v = getLayoutInflater(savedInstanceState).inflate(
            R.layout.fragment_camera_preview, container, false);

    /**
     * Add Camera Preview into Layout
     */
    // Create our Preview view and set it as the content of our activity.
    mCameraPreview = new CameraPreview(getActivity(), CustomCamera.mCamera);
    mFlCameraPreview.addView(mCameraPreview);

    return v;
}

public void onClick(View v) {
switch (v.getId()) {
    case R.id.ibtn_switch_back_or_front_camera:
            /**
             * Should reset camera for camera get new setting
             */

            // Switch between Front Camera & Back Camera
            current_camera_id = switchCurrentCameraID();

            refreshCameraPreview(getActivity(), current_camera_id);

            // Should remove view parent before add child
            Utils.removeViewParent(mCameraPreview);

            /**
             * Add Camera Preview into Layout
             */
            // Create our Preview view and set it as the content of our activity.
            mCameraPreview = new CameraPreview(getActivity(), CustomCamera.mCamera);
            mFlCameraPreview.addView(mCameraPreview);
            break;
}
}

// for the Preview - from http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)
// note, if orientation is locked to landscape this is only called when setting up the activity, and will always have the same orientation
public static void setCameraDisplayOrientation(Activity activity, int camera_id) {
    CustomCamera.mCameraInfo = new Camera.CameraInfo();
    Camera.getCameraInfo(camera_id, CustomCamera.mCameraInfo);
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
    }

    int result;
    if (CustomCamera.mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        result = (CustomCamera.mCameraInfo.orientation + degrees) % 360;
        result = (360 - result) % 360;  // compensate the mirror
    } else {
        result = (CustomCamera.mCameraInfo.orientation - degrees + 360) % 360;
    }

    if (CustomCamera.mCamera != null)
        CustomCamera.mCamera.setDisplayOrientation(result);
}

activity_custom_camera.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/LinearLayout__Vertical_MatchParent">

<FrameLayout
    android:id="@+id/fl_custom_camera"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1" />

</LinearLayout>

fragment_camera_preview.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
style="@style/FrameLayout_"
>

<FrameLayout
    android:id="@+id/fl_camera_preview"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />

</FrameLayout>

我想要的是我的应用程序中的自定义相机如何更适合流行的Android设备,如Instagram,Camera 360 ......

另一件事,我没有使用<uses-feature android:name="android.hardware.camera" />这个会帮我解决什么事情?它会减少支持的Android设备可以从Play商店下载我的应用程序吗?

知道的人,

请帮助我,

谢谢,

0 个答案:

没有答案