7

所以我正在开发一个与相机相关的项目,我一直在许多设备上进行测试,除了 Nexus 10 之外,所有设备都通过了测试。

我真的不知道发生了什么,网上也没有人谈论这个问题。

我能够在两个不同的 Nexus 10 (wifi) 设备上复制该问题。

这是我的活动代码:

public class MainActivity extends Activity {
    private static Camera mCamera;
    private static boolean mCameraOpen;
    private static ImageView mPreviewImageView;
    private SurfaceView mPreviewSurfaceView;
    private static boolean mPreviewRunning;
    private static Handler mHandler;
    private static int TESTS_COUNT = 0;
    private Camera.Parameters mCameraParameters;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mHandler = new Handler();
        mPreviewSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
        mPreviewImageView = (ImageView) findViewById(R.id.imageview);
        mPreviewSurfaceView.getHolder().addCallback(mCallback);

        TextView view = (TextView) findViewById(R.id.textview);
        view.setText("Format: " + String.valueOf(TESTS_COUNT));

    }

    @Override
    public void onResume(){
        super.onResume();
        if (mCamera == null){
            for (int i = 0; i < Camera.getNumberOfCameras(); i++){
                Camera.CameraInfo info = new Camera.CameraInfo();
                Camera.getCameraInfo(i, info);

                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){
                    mCamera = Camera.open(i);
                    Camera.Parameters params = mCamera.getParameters();
                    params.set("camera-id", 2);
                    List<Integer> formats = params.getSupportedPreviewFormats();
                    if (formats.size() > TESTS_COUNT) {
                        Log.e("Camera", "testing preview format at index: " + TESTS_COUNT);
                        params.setPreviewFormat(formats.get(TESTS_COUNT));
                        mCamera.setParameters(params);
                        mCameraOpen = true;
                        SurfaceHolder holder = mPreviewSurfaceView.getHolder();
                        if (holder != null && holder.getSurface() != null && holder.getSurface().isValid()) {
                            mCallback.surfaceCreated(holder);
                        }
                        mCameraParameters = params;
                        break;
                    } else {
                        finish();
                    }
                }

            }
        }
    }

    @Override
    public void onPause(){
        super.onPause();
        if (mPreviewRunning){
            mCamera.stopPreview();
            mCamera.setPreviewCallback(null);
            mPreviewRunning = false;
        }

        if (mCameraOpen){
            mCamera.release();
            mCamera = null;
            mCameraOpen = false;
        }
    }

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

    }

    private final SurfaceHolder.Callback mCallback =  new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
                if (mCameraOpen && mCamera != null){
                    try {
                        mCamera.setPreviewDisplay(surfaceHolder);
                        mCamera.setPreviewCallback(new Camera.PreviewCallback() {
                            private int count;
                            private int total;
                            @Override
                            public void onPreviewFrame(byte[] bytes, Camera camera) {
                                if (count == 15){
                                    Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
                                    // pWidth and pHeight define the size of the preview Frame
                                    ByteArrayOutputStream out = new ByteArrayOutputStream();

                                    // Alter the second parameter of this to the actual format you are receiving
                                    YuvImage yuv = new YuvImage(bytes, ImageFormat.NV21, previewSize.width, previewSize.height, null);

                                    // bWidth and bHeight define the size of the bitmap you wish the fill with the preview image
                                    yuv.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 50, out);
                                    byte[] bitmapBytes = out.toByteArray();
                                    final Bitmap bitmap= BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
                                    mHandler.post(new Runnable() {
                                        @Override
                                        public void run() {
                                            mPreviewImageView.setImageBitmap(bitmap);
                                        }
                                    });
                                    count = 0;
                                    total++;
                                    if (total > 5){
                                        TESTS_COUNT++;
                                        if (TESTS_COUNT == mCameraParameters.getSupportedPreviewSizes().size()) {
                                            finish();
                                            return;
                                        }
                                        Intent intent = new Intent( MainActivity.this, MainActivity.class);
                                        startActivity(intent);

                                    }

                                } else {
                                    count++;
                                }

                            }
                        });

                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder,  int format, int width, int height) {
            for (Camera.Size size : mCameraParameters.getSupportedPreviewSizes()){
                if (size.width == width && size.height == height){
                    if (mCameraOpen && mCamera != null && mPreviewRunning == false) {
                        mCameraParameters.setPreviewSize(width, height);
                        mCamera.setParameters(mCameraParameters);

                        mCamera.startPreview();

                        mPreviewRunning = true;
                        break;
                    }
                }
            }
            if (mPreviewRunning == false){
                Log.e("CameraPreview", "size not supported");
            }

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

        }
    };

}

我的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context=".MainActivity"
    android:orientation="vertical"
    android:weightSum="2">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello"/>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context=".MainActivity"
    android:orientation="horizontal"
    android:layout_weight="1"
    android:weightSum="2">
        <SurfaceView
            android:layout_width="640px"
            android:layout_height="480px"
            android:id="@+id/surfaceview"/>
        <ImageView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:id="@+id/imageview"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textview"
            android:textSize="40sp"/>
</LinearLayout>
</LinearLayout>

和清单:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

没有错误消息,屏幕只是黑屏

截屏

4

3 回答 3

6

潜在的问题是,“如何调试这个?” 与往常一样,答案是尽可能多地提出可以解释这些结果的假设,然后检验这些假设。

以下是一些假设(请考虑更多):

  • 它没有找到任何相机。
  • 它没有找到任何前置摄像头。
  • 它误解了相机参数。
  • 它设置mCallback得太晚了,即在需要之后。
  • 它没有找到有效的表面。
  • 它没有成功注册相机帧。
  • 它正在注册但未接收任何相机帧。
  • 它正在接收相机帧但无法显示它们,例如图像不是预期的格式,或者setImageBitmap(bitmap)Runnable 没有运行。
  • TESTS_COUNT没有做你想让它做的事情。

您可以通过日志记录来测试假设,但在大多数情况下,在调试器中单步执行并检查数据值(例如params.

如果您不熟悉调试器,现在是时候了!

于 2015-09-13T02:51:42.963 回答
1

请使用名为 CtsVerifier 的应用程序验证您的设备,该应用程序包含在 Android 开源项目中,并且是 Android 设备兼容性测试套件 (CTS) 的一部分。CTS Verifier 有一系列检查相机的测试。检查这个链接

如果前置摄像头在此应用程序中不起作用,您可以确定。那么你的设备可能已经损坏,或者 hal 层发生了一些损坏。如果是这种情况,您可能会尝试降级/升级您的 android 操作系统。如果不是,则可能是硬件损坏。

于 2015-09-20T17:44:45.440 回答
0

我使用 Lollipop 5.1 在 Nexus 10 上测试活动。我有时会注意到,当我旋转屏幕时,应用程序会崩溃。我解决了这个问题,修改了方法的开头surfaceChanged

@Override 
public void surfaceChanged(SurfaceHolder surfaceHolder,  int format, int width, int height)
{
  if (mCameraParameters==null) return;
  ...
}

此外,如果你想研究一个关于在 android 上使用相机硬件的工作示例,你可以参考项目android_instacam及其源代码。

于 2015-09-18T02:05:40.230 回答