0

尝试将 Facebook Live api 与我的 android 应用程序一起使用。我正在使用 camera2 在我的直播活动中拉起摄像头,但出现此错误:

 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.hardware.camera2.CameraCaptureSession.abortCaptures()' on a null object reference
                                                                     at com.example.mapdemo.StreamingActivity$4.onClick(StreamingActivity.java:151)
                                                                     at android.view.View.performClick(View.java:6261)
                                                                     at android.widget.TextView.performClick(TextView.java:11157)
                                                                     at android.view.View$PerformClick.run(View.java:23748)
                                                                     at android.os.Handler.handleCallback(Handler.java:751)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)

我不确定为什么这是一个错误。这是错误所在行周围的代码...错误行以 mCaptureCameraSession.abortCaptures() 开头:

package com.example.mapdemo;

import android.content.pm.PackageManager;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.support.annotation.NonNull;
import android.support.v13.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

import com.facebook.AccessToken;
import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import com.facebook.HttpMethod;

import org.json.JSONException;

import java.util.ArrayList;

public class StreamingActivity extends AppCompatActivity  implements SurfaceHolder.Callback2 {

    private static final String TAG = "StreamingActivity";
    private static final String[] REQUEST_PERMISSIONS = new String[]{
            android.Manifest.permission.CAMERA,
            android.Manifest.permission.RECORD_AUDIO,
            android.Manifest.permission.WRITE_EXTERNAL_STORAGE
    };
    private static final int REQUEST_CODE_CAMERA = 1;

    private CameraManager mCameraManager;
    private VideoEncoderCore mVideoEncoderCore;
    private String mFrontCameraId, streamURL,name,surname;
    private CameraDevice mCameraDevice;
    private Handler mBackgroundHandler;
    private HandlerThread mBackgroundThread;
    private SurfaceView mSurfacView;
    private Button buttonRecord;
    private boolean isRecording = false;
    private ArrayList<Surface> mSurfaces;
    private CaptureRequest mCaptureRequestPreview;
    private StreamModel streamModel;
    private CaptureRequest mCaptureRequestRecord;
    private CameraCaptureSession mCameraCaptureSession;
    private CameraCaptureSession.StateCallback mCaptureSessionCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            mCameraCaptureSession = session;
            try {
                mCameraCaptureSession.setRepeatingRequest(
                        mCaptureRequestPreview,
                        new CameraCaptureSession.CaptureCallback() {},
                        mBackgroundHandler
                );
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Log.d(TAG, "fafea") ;
        }
    };
    private CameraDevice.StateCallback mCameraDeviceCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera;
//           mCameraDevice.createCaptureSession();
//
//            try {
//                mCameraManager.setTorchMode(mFrontCameraId, true);
//            } catch (CameraAccessException e) {
//                e.printStackTrace();
//            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {

        }

        @Override
        public void onError(@NonNull CameraDevice camera,  int error) {
            //@IntDef(value = {CameraDevice.StateCallback.ERROR_CAMERA_IN_USE, CameraDevice.StateCallback.ERROR_MAX_CAMERAS_IN_USE, CameraDevice.StateCallback.ERROR_CAMERA_DISABLED, CameraDevice.StateCallback.ERROR_CAMERA_DEVICE, CameraDevice.StateCallback.ERROR_CAMERA_SERVICE})
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_streaming);


        mSurfacView = (SurfaceView) findViewById(R.id.surfaceView);
        mSurfacView.getHolder().addCallback(StreamingActivity.this);
        streamModel = new StreamModel();
/**
 LoginManager.getInstance().logInWithPublishPermissions(
 this,
 Arrays.asList("publish_actions"));*/

        new GraphRequest(
                AccessToken.getCurrentAccessToken(), "/me/live_videos", null, HttpMethod.POST,
                new GraphRequest.Callback() {
                    public void onCompleted(GraphResponse response) {
                        //Gson mGson = new Gson();
                        //streamModel=mGson.fromJson(response.toString(),StreamModel.class);
                        try {
                            streamURL=response.getJSONObject().get("stream_url").toString();
                            Log.e(TAG,response.getJSONObject().get("stream_url").toString());
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
        ).executeAsync();

        buttonRecord =(Button) findViewById(R.id.buttonRecord);
        buttonRecord.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isRecording){
                    try {
                        mCameraCaptureSession.abortCaptures();
                        mCameraCaptureSession.setRepeatingRequest(
                                mCaptureRequestPreview,
                                new CameraCaptureSession.CaptureCallback() {},
                                mBackgroundHandler
                        );
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                    isRecording = false;
                    buttonRecord.setText("Play");
                }
                else{
                    isRecording = true;
                    try {
                        mCameraCaptureSession.abortCaptures();
                        mCameraCaptureSession.setRepeatingRequest(mCaptureRequestRecord, new CameraCaptureSession.CaptureCallback() {
                            @Override
                            public void onCaptureCompleted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, @NonNull TotalCaptureResult result) {
                                super.onCaptureCompleted(session, request, result);
                                mVideoEncoderCore.drainEncoder(false);
                            }

                            @Override
                            public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session, int sequenceId) {
                                super.onCaptureSequenceAborted(session, sequenceId);
                                mVideoEncoderCore.drainEncoder(true);
                            }
                        }, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                    buttonRecord.setText("Stop");
                }
            }
        });
        mCameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
        try {
            String[] cameraIds = mCameraManager.getCameraIdList();
            if (cameraIds.length != 0) {
                for (int i = 0; i < cameraIds.length; i++){
                    if (mCameraManager.getCameraCharacteristics(cameraIds[i]).get(CameraCharacteristics.LENS_FACING)
                            == CameraCharacteristics.LENS_FACING_FRONT){
                        mFrontCameraId = cameraIds[i];
                    }
                }
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mVideoEncoderCore != null) {
            mVideoEncoderCore.release();
        }
    }

    private void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }

    private void openCamera(){
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, REQUEST_PERMISSIONS, REQUEST_CODE_CAMERA);
            return;
        }
        try {
            mCameraManager.openCamera(mFrontCameraId, mCameraDeviceCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { // there were 2 different types pf activity compats to import
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        try {
            mCameraManager.openCamera(mFrontCameraId, mCameraDeviceCallback, mBackgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceRedrawNeeded(SurfaceHolder holder) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        startBackgroundThread();
        openCamera();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
/**
 private String getVideoFilePath(Context context) {
 return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/"
 + System.currentTimeMillis() + ".mp4";
 }
 */
/**
 public void createCaptureSession(){
 try {
 mVideoEncoderCore = new VideoEncoderCore(
 1280,
 720,
 4000000,
 streamURL
 );
 Surface previewSurface = mSurfacView.getHolder().getSurface();
 Surface encoderSurface = mVideoEncoderCore.getInputSurface();
 CaptureRequest.Builder captureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
 captureRequestBuilder.addTarget(previewSurface);
 mSurfaces = new ArrayList<>();
 mSurfaces.add(previewSurface);
 mSurfaces.add(encoderSurface);
 mCaptureRequestPreview = captureRequestBuilder.build();
 captureRequestBuilder.addTarget(encoderSurface);
 mCaptureRequestRecord = captureRequestBuilder.build();
 mCameraDevice.createCaptureSession(mSurfaces, mCaptureSessionCallback, mBackgroundHandler);
 } catch (CameraAccessException e) {
 e.printStackTrace();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 */



    }
4

1 回答 1

1

Camera2 API 有许多与之关联的异步任务——在后台运行以完成某些工作的任务,例如打开相机、关闭相机、获取焦点等。

这些任务使用回调来报告它们何时完成。

除此之外,活动或片段本身可能会在后台调用其他任务,这些任务也使用回调进行通信,并且还可能与相机交互 - 例如,相机通常会在活动或片段暂停事件期间关闭。

管理所有回调可能很棘手,并且可能存在竞争条件 - 您还可以在 Stackoverflow 上找到其他 Camera2 竞争条件问题和答案。

在您的情况下,错误告诉您 captureSession 对象为空。最可能的原因是因为它已被设置为 null,要么是由于竞争条件导致的无序回调,要么是因为您在完全完成之前无意中将其设置为 null 作为清理的一部分。

于 2017-08-02T07:13:20.320 回答