Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 为什么';Camera2 API是否在某些设备上工作?_Android_Android Camera_Android Camera2_Android Mediarecorder_Android Camerax - Fatal编程技术网

Android 为什么';Camera2 API是否在某些设备上工作?

Android 为什么';Camera2 API是否在某些设备上工作?,android,android-camera,android-camera2,android-mediarecorder,android-camerax,Android,Android Camera,Android Camera2,Android Mediarecorder,Android Camerax,我正在开发一个摄像头应用程序。我需要捕获视频并保存它们。我创建了一个使用Camera2API而不是CameraAPI的项目。然而,该应用程序在我的手机(棉花糖6.0)上不起作用,但在模拟器(安卓7.0)上起作用 我想创建一个在所有手机(Android 6.0到9.0)上都兼容的应用程序。 我怎样才能不撞车呢 我的代码(来自Youtube教程): 主要活动 package com.example.camera2video; import androidx.annotation.NonNull;

我正在开发一个摄像头应用程序。我需要捕获视频并保存它们。我创建了一个使用Camera2API而不是CameraAPI的项目。然而,该应用程序在我的手机(棉花糖6.0)上不起作用,但在模拟器(安卓7.0)上起作用

我想创建一个在所有手机(Android 6.0到9.0)上都兼容的应用程序。 我怎样才能不撞车呢

我的代码(来自Youtube教程):

主要活动

package com.example.camera2video;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Camera;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
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.params.StreamConfigurationMap;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    //************************************
    private static final int REQUEST_CAMERA_PERMISSION_RESULT = 0;
    private static final int REQUEST_EXTERNAL_STORAGE_PERMISSION_RESULT = 1;
    //************************************

    private TextureView mTextureView;
    private TextureView.SurfaceTextureListener mTextureViewSurface = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
            setupCamera(i, i1);
            connectCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {

        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {

        }
    };

    private CameraDevice mCameraDevice;
    private CameraDevice.StateCallback mCameraStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {

            mCameraDevice = cameraDevice;

            if(recordingStatus) {
                try {
                    createVideoFileName();
                    startRecord();
                    mMediaRecorder.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                startPreview();
            }

        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            cameraDevice.close();
            mCameraDevice = null;

        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {
            cameraDevice.close();
            mCameraDevice = null;
        }
    };

    private Handler mBackgroundHandler;
    private HandlerThread mBackgroundHandlerThread;

    private String mCameraID;
    private Size mPreviewSize;
    private CaptureRequest.Builder mCaptureRequestBuilder;

    private Button startButton;
    private Button stopButton;
    private boolean recordingStatus = false;

    //***************
    private File mVideoFolder;
    private String mVideoFileName;

    private int mTotalRotation;
    private Size mVideoSize;
    private MediaRecorder mMediaRecorder;
    //***************

    private static SparseIntArray ORIENTATIONS = new SparseIntArray();
    static {
        ORIENTATIONS.append(Surface.ROTATION_0, 0);
        ORIENTATIONS.append(Surface.ROTATION_90, 90);
        ORIENTATIONS.append(Surface.ROTATION_180, 180);
        ORIENTATIONS.append(Surface.ROTATION_270, 270);
    }

    private static class CompareSizeByArea implements Comparator<Size> {

        @Override
        public int compare(Size size, Size t1) {
            return Long.signum((long) size.getWidth() * (long) size.getHeight() / (long) t1.getWidth() * (long) t1.getHeight());
        }
    }



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

        mTextureView = findViewById(R.id.textureView);
        startButton = findViewById(R.id.startButton);
        startButton.setTextColor(Color.BLACK);

        //*******************
        createVideoFolder();
        mMediaRecorder = new MediaRecorder();
        //*******************

        startButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if(recordingStatus) {
                    recordingStatus = false;
                    startButton.setTextColor(Color.BLACK);
                    //****************************
                    mMediaRecorder.stop();
                    mMediaRecorder.reset();
                    //****************************
                    startPreview();
                } else {
                    //****************************
                    checkWriteStoragePermission();
                    //****************************
                }

            }
        });
    }

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

        startBackgroundThread();

        if(mTextureView.isAvailable()) {
            setupCamera(mTextureView.getWidth(), mTextureView.getHeight());
            connectCamera();
        } else {
            mTextureView.setSurfaceTextureListener(mTextureViewSurface);
        }
    }

    @Override
    protected void onPause() {
        cameraClose();
        stopBackgroundThread();

        super.onPause();
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);

        View decorView = getWindow().getDecorView();

        if(hasFocus) {
            decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if(requestCode == REQUEST_CAMERA_PERMISSION_RESULT) {
            if(grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "This APP requied to Camera permission.", Toast.LENGTH_SHORT).show();
            }
        }

        //************************************
        if(requestCode == REQUEST_EXTERNAL_STORAGE_PERMISSION_RESULT) {
            if(grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                recordingStatus = true;
                startButton.setTextColor(Color.RED);
                try {
                    createVideoFileName();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(this, "This APP needs External Write Permission.", Toast.LENGTH_SHORT).show();
            }
        }
        //**************************************


    }

    private void setupCamera(int width, int height) {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

        try {
            for(String cameraID : cameraManager.getCameraIdList()) {
                CameraCharacteristics cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraID);

                if(cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) {
                    continue;
                }

                StreamConfigurationMap streamConfigurationMap = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);


                int deviceOrientation = getWindowManager().getDefaultDisplay().getRotation();
                mTotalRotation = sensorToDeviceRotation(cameraCharacteristics, deviceOrientation);
                boolean swapRotation = mTotalRotation == 90 || mTotalRotation == 270;

                int rotatedWidth = width;
                int rotatedHeight = height;

                if(swapRotation) {
                    rotatedWidth = height;
                    rotatedHeight = width;
                }

                mPreviewSize = chooseOptimalSize(streamConfigurationMap.getOutputSizes(SurfaceTexture.class), rotatedWidth, rotatedHeight);
                mVideoSize = chooseOptimalSize(streamConfigurationMap.getOutputSizes(MediaRecorder.class), rotatedWidth, rotatedHeight);

                mCameraID = cameraID;
                return;

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

    private void connectCamera () {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if(ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                    cameraManager.openCamera(mCameraID, mCameraStateCallback, mBackgroundHandler);
                } else {
                    if(shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
                        Toast.makeText(this, "This APP requied access to Camera permission", Toast.LENGTH_SHORT).show();
                    }
                    requestPermissions(new String[] {Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION_RESULT);
                }
            } else {
                cameraManager.openCamera(mCameraID, mCameraStateCallback, mBackgroundHandler);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void startPreview () {
        SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
        surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

        Surface previewSurface = new Surface(surfaceTexture);
        try {
            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mCaptureRequestBuilder.addTarget(previewSurface);


            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {

                @Override
                public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                    try {
                        cameraCaptureSession.setRepeatingRequest(mCaptureRequestBuilder.build(), null, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                    Toast.makeText(MainActivity.this, "Unable to camera setup", Toast.LENGTH_SHORT).show();
                }
            }, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void cameraClose() {
        if(mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
    }

    private void startBackgroundThread () {
        mBackgroundHandlerThread = new HandlerThread("camera2video");
        mBackgroundHandlerThread.start();

        mBackgroundHandler = new Handler(mBackgroundHandlerThread.getLooper());
    }

    private void stopBackgroundThread () {
        mBackgroundHandlerThread.quitSafely();
        try {
            mBackgroundHandlerThread.join();
            mBackgroundHandlerThread = null;
            mBackgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static int sensorToDeviceRotation(CameraCharacteristics cameraCharacteristics, int deviceOrientation) {
        int sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        deviceOrientation = ORIENTATIONS.get(deviceOrientation);

        return (deviceOrientation + sensorOrientation + 360) % 360;
    }

    private static Size chooseOptimalSize (Size[] choices, int width, int height) {
        List<Size> bigEnough = new ArrayList<Size>();
        for(Size option:choices) {
            if(option.getHeight() == option.getWidth() * height / width && option.getWidth() >= width && option.getWidth() >= height) {
                bigEnough.add(option);
            }
        }

        if(bigEnough.size() > 0) {
            return Collections.min(bigEnough, new CompareSizeByArea());
        } else {
            return choices[0];
        }
    }

    //***********************
    private void createVideoFolder () {
        File videoFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
        mVideoFolder = new File(videoFile, "cam2video");
        if(!mVideoFolder.exists()) {
            mVideoFolder.mkdirs();
        }
    }

    private File createVideoFileName() throws IOException {
        String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String prepend = "VIDEO_"+timestamp+"_";
        File videoFile = File.createTempFile(prepend, ".mp4", mVideoFolder);
        mVideoFileName = videoFile.getAbsolutePath();

        return videoFile;

    }

    private void checkWriteStoragePermission() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            if(ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED) {
                recordingStatus = true;
                startButton.setTextColor(Color.RED);
                try {
                    createVideoFileName();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                startRecord();
                mMediaRecorder.start();
            } else {

                if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    Toast.makeText(this, "This APP needs Write Storage Permission", Toast.LENGTH_SHORT).show();
                }

                ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_EXTERNAL_STORAGE_PERMISSION_RESULT);
            }
        } else {
            recordingStatus = true;
            startButton.setTextColor(Color.RED);
            try {
                createVideoFileName();
            } catch (IOException e) {
                e.printStackTrace();
            }

            startRecord();
            mMediaRecorder.start();
        }
    }

    private void setupMediaRecorder () throws IOException {
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mMediaRecorder.setOutputFile(mVideoFileName);
        mMediaRecorder.setVideoEncodingBitRate(10000000);
        mMediaRecorder.setVideoFrameRate(30);
        mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setOrientationHint(mTotalRotation);
        mMediaRecorder.prepare();

    }

    private void startRecord() {
        try {
            setupMediaRecorder();
            SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
            surfaceTexture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
            Surface previewSurface = new Surface(surfaceTexture);
            Surface recordSurface = mMediaRecorder.getSurface();
            mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            mCaptureRequestBuilder.addTarget(previewSurface);
            mCaptureRequestBuilder.addTarget(recordSurface);
            mCameraDevice.createCaptureSession(Arrays.asList(previewSurface, recordSurface),
                    new CameraCaptureSession.StateCallback() {
                        @Override
                        public void onConfigured(CameraCaptureSession session) {
                            try {
                                session.setRepeatingRequest(
                                        mCaptureRequestBuilder.build(), null, null
                                );
                            } catch (CameraAccessException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onConfigureFailed(CameraCaptureSession session) {
                        }
                    }, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        //***********************
}
package com.example.camera2video;
导入androidx.annotation.NonNull;
导入androidx.appcompat.app.appcompat活动;
导入androidx.core.app.ActivityCompat;
导入androidx.core.content.ContextCompat;
导入android.Manifest;
导入android.content.Context;
导入android.content.pm.PackageManager;
导入android.graphics.Camera;
导入android.graphics.Color;
导入android.graphics.SurfaceTexture;
导入android.hardware.camera2.CameraAccessException;
导入android.hardware.camera2.CameraCaptureSession;
导入android.hardware.camera2.CameraCharacteristics;
导入android.hardware.camera2.CameraDevice;
导入android.hardware.camera2.CameraManager;
导入android.hardware.camera2.CaptureRequest;
导入android.hardware.camera2.params.StreamConfigurationMap;
导入android.media.MediaRecorder;
导入android.os.Build;
导入android.os.Bundle;
导入android.os.Environment;
导入android.os.Handler;
导入android.os.HandlerThread;
导入android.util.Size;
导入android.util.SparseIntArray;
导入android.view.Surface;
导入android.view.TextureView;
导入android.view.view;
导入android.widget.Button;
导入android.widget.Toast;
导入java.io.File;
导入java.io.IOException;
导入java.text.simpleDataFormat;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collection;
导入java.util.Collections;
导入java.util.Comparator;
导入java.util.Date;
导入java.util.List;
公共类MainActivity扩展了AppCompatActivity{
//************************************
私有静态最终int请求\摄像机\权限\结果=0;
私有静态最终整数请求\外部\存储\权限\结果=1;
//************************************
私有纹理视图mTextureView;
私有TextureView.SurfaceTextureRelistener mTextureViewSurface=新TextureView.SurfaceTextureRelistener(){
@凌驾
SurfaceTexture上的公共空心可用(SurfaceTexture SurfaceTexture,int i,int i1){
设置摄像机(i,i1);
连接摄像头();
}
@凌驾
表面结构尺寸更改的公共空隙(表面结构表面结构,int i,int i1){
}
@凌驾
公共布尔onSurfaceTextureDestroyed(SurfaceTexture SurfaceTexture){
返回false;
}
@凌驾
已更新SurfaceTexture上的公共空间(SurfaceTexture SurfaceTexture){
}
};
私人摄像设备;
private CameraDevice.StateCallback mCameraStateCallback=新建CameraDevice.StateCallback(){
@凌驾
打开的公共无效(@NonNull CameraDevice CameraDevice){
mCameraDevice=cameraDevice;
if(记录状态){
试一试{
createVideoFileName();
startRecord();
mMediaRecorder.start();
}捕获(IOE异常){
e、 printStackTrace();
}
}否则{
startPreview();
}
}
@凌驾
公共无效onDisconnected(@NonNull CameraDevice CameraDevice){
cameraDevice.close();
mCameraDevice=null;
}
@凌驾
公共无效onError(@NonNull CameraDevice CameraDevice,int i){
cameraDevice.close();
mCameraDevice=null;
}
};
私人处理程序mBackgroundHandler;
私有HandlerThread mBackgroundHandlerThread;
私人字符串mCameraID;
私人规模的mPreviewSize;
私有CaptureRequest.Builder mCaptureRequestBuilder;
私人按钮开始按钮;
私人按钮停止按钮;
私有布尔记录状态=false;
//***************
私人文件夹;
私有字符串文件名;
私人国际旋转;
私人规模;
专用媒体记录器;
//***************
专用静态SparseIntArray方向=新SparseIntArray();
静止的{
方向。附加(Surface.ROTATION_0,0);
方向。附加(Surface.ROTATION_90,90);
方向。附加(Surface.ROTATION_180,180);
方向。附加(Surface.ROTATION_270,270);
}
私有静态类CompareSizeByArea实现Comparator{
@凌驾
公共整数比较(大小,大小t1){
返回Long.signum((Long)size.getWidth()*(Long)size.getHeight()/(Long)t1.getWidth()*(Long)t1.getHeight());
}
}
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextureView=findviewbyd(R.id.textureView);
startButton=findViewById(R.id.startButton);
startButton.setTextColor(Color.BLACK);
//*******************
createVideoFolder();
mMediaRecorder=新的MediaRecorder();
//*******************
startButton.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图){
if(记录状态){
recordingStatus=false;
startButton.setTextColor(Color.BLACK);
//****************************
mMediaRecorder.stop();
mMediaRecorder.reset();
//****************************
startPreview();
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:gravity="center_horizontal">

    <TextureView
        android:id="@+id/textureView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></TextureView>

    <Button
        android:id="@+id/startButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="RECORD"
        android:textSize="22sp"
        android:padding="20dp"></Button>


</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.camera2video">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>