java 带摄像头的 Surface View 无法在 Android API 23(Android 6+)上运行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34789083/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 23:20:59  来源:igfitidea点击:

Surface View with Camera not functioning on Android API 23 (android 6+)

javaandroidandroid-studiocamera

提问by mmsergi

I want to make a background with the camera on a SurfaceView, and I succeed at android API lower than 23. Altough im previously requesting camera permission in app on API 23, the following error still appearing on my Nexus 5 with Android 6:

我想在 SurfaceView 上使用相机制作背景,并且我在低于 23 的 android API 上取得了成功。尽管我之前在 API 23 上的应用程序中请求相机权限,但以下错误仍然出现在我的 Nexus 5 和 Android 6 上:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)' on a null object reference at com.package.name.CameraPreview.surfaceCreated(CameraPreview.java:31)

java.lang.NullPointerException:尝试在 com.package.name.CameraPreview.surfaceCreated(CameraPreview.java:31) 的空对象引用上调用虚拟方法“void android.hardware.Camera.setPreviewDisplay(android.view.SurfaceHolder)”

My code is:

我的代码是:

import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;

/** A basic Camera preview class */
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 activity_hologram where to draw the preview.
        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.startPreview();
            mCamera.setDisplayOrientation(90);
        } catch (IOException e) {
            Log.d("", "Error setting activity_hologram preview: " + e.getMessage());
        }
    }

    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
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            mCamera.setPreviewDisplay(mHolder);
            mCamera.startPreview();

        } catch (Exception e){
            Log.d("", "Error starting activity_hologram preview: " + e.getMessage());
        }
    }

}

The error jumps at mCamera.setPreviewDisplay(holder);

错误跳转到 mCamera.setPreviewDisplay(holder);

My main activity code:

我的主要活动代码:

public class MainActivity extends AppCompatActivity {

private static Context mContext;

private Camera mCamera;
private CameraPreview mPreview;

private FrameLayout layout;

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

    layout = (FrameLayout) findViewById(R.id.camera_preview);

    mCamera = getCameraInstance();
    mPreview = new CameraPreview(this, mCamera);
    layout.addView(mPreview);
}


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

}

My manifest got:

我的清单有:

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

Any ideas to resolve this problem on Android 6?

在 Android 6 上解决此问题的任何想法?

Thanks for your time, cheers.

谢谢你的时间,干杯。

回答by Rahul Sainani

Building up on @Fildor's answer which pointed me in the right direction. The camera object is null. In API 23 and above, go into app info -> permissions and enable the camera permission to successfully get the camera object.

以@Fildor 的回答为基础,为我指明了正确的方向。相机对象为空。在 API 23 及以上版本中,进入 app info -> permissions 并启用相机权限以成功获取相机对象。

回答by Fildor

I marked the problematic place in comment:

我在评论中标记了有问题的地方:

public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open(); // attempt to get a Camera instance
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
// >>> HERE is your problem! Do not swallow exceptions silently!
    }
    return c; // returns null if activity_hologram is unavailable
}

It looks like getCameraInstancereturns null. That could have two reasons:

看起来像getCameraInstance返回空值。这可能有两个原因:

  1. Camera.Open()returns null
  2. There is an exception which you won't be aware of, because you just silently swallow it and move on.
  1. Camera.Open()回报 null
  2. 有一个你不会意识到的例外,因为你只是默默地吞下它并继续前进。

Another Point:

另一点:

This class was deprecated in API level 21.
We recommend using the new android.hardware.camera2 API for new applications.

此类在 API 级别 21 中已弃用。
我们建议对新应用程序使用新的 android.hardware.camera2 API。

From Android Developer Site

来自Android 开发者网站

回答by Ashish Batra

to Solve the issue Go to Application Manager. Select your App and go to permissions Tab , and turn on the required permission. the App will run perfectly after that.

解决问题 转到应用程序管理器。选择您的应用程序并转到权限选项卡,然后打开所需的权限。之后应用程序将完美运行。

To Fix the issue at Runtime:- check the Link
https://developer.android.com/training/permissions/requesting.html

要在运行时修复问题:- 检查链接
https://developer.android.com/training/permissions/requesting.html

回答by vishal dharankar

This api still works on newer versions of Android , tested on 6.0.1 only issue is add Camera permission and ask user to grant it explicitly .

这个 api 仍然适用于较新版本的 Android,在 6.0.1 上测试唯一的问题是添加相机权限并要求用户明确授予它。