表面视图未显示相机,尽管我已经授予权限

9
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_camera, container, false);
    cameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
    flipCamera = view.findViewById(R.id.flipCamera);
    flashCameraButton = view.findViewById(R.id.flash);
    captureImage = view.findViewById(R.id.captureImage);
    surfaceView = view.findViewById(R.id.surfaceView);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);
    flipCamera.setOnClickListener(this);
    captureImage.setOnClickListener(this);
    flashCameraButton.setOnClickListener(this);
    getActivity().getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

    if (Camera.getNumberOfCameras() > 1) {
        flipCamera.setVisibility(View.VISIBLE);
    }
    if (!getActivity().getBaseContext().getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA_FLASH)) {
        flashCameraButton.setVisibility(View.GONE);
    }


    return view;
}

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void surfaceCreated(SurfaceHolder holder) {

    if (!openCamera(Camera.CameraInfo.CAMERA_FACING_BACK)) {
        alertCameraDialog();
    }

}


private boolean openCamera(int id) {
    boolean result = false;
    cameraId = id;
    releaseCamera();
    try {
        camera = Camera.open(cameraId);
    } catch (Exception e) {
        e.printStackTrace();
    }
    if (camera != null) {
        try {
            setUpCamera(camera);
            camera.setErrorCallback(new Camera.ErrorCallback() {

                @Override
                public void onError(int error, Camera camera) {

                }
            });
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
            result = true;
        } catch (IOException e) {
            e.printStackTrace();
            result = false;
            releaseCamera();
        }
    }
    return result;
}

private void setUpCamera(Camera c) {
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    rotation = getActivity().getWindowManager().getDefaultDisplay().getRotation();
    int degree = 0;
    switch (rotation) {
        case Surface.ROTATION_0:
            degree = 0;
            break;
        case Surface.ROTATION_90:
            degree = 90;
            break;
        case Surface.ROTATION_180:
            degree = 180;
            break;
        case Surface.ROTATION_270:
            degree = 270;
            break;

        default:
            break;
    }

    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
        // frontFacing
        rotation = (info.orientation + degree) % 330;
        rotation = (360 - rotation) % 360;
    } else {
        // Back-facing
        rotation = (info.orientation - degree + 360) % 360;
    }
    c.setDisplayOrientation(rotation);
    Camera.Parameters params = c.getParameters();

    showFlashButton(params);

    List<String> focusModes = params.getSupportedFlashModes();
    if (focusModes != null) {
        if (focusModes
                .contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            params.setFlashMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        }
    }

    params.setRotation(rotation);
}

private void showFlashButton(Camera.Parameters params) {
    boolean showFlash = (getActivity().getPackageManager().hasSystemFeature(
            PackageManager.FEATURE_CAMERA_FLASH) && params.getFlashMode() != null)
            && params.getSupportedFlashModes() != null
            && params.getSupportedFocusModes().size() > 1;

    flashCameraButton.setVisibility(showFlash ? View.VISIBLE
            : View.INVISIBLE);

}

private void releaseCamera() {
    try {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.setErrorCallback(null);
            camera.stopPreview();
            camera.release();
            camera = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
        Log.e("error", e.toString());
        camera = null;
    }
}

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

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.flash:
            flashOnButton();
            break;
        case R.id.flipCamera:
            flipCamera();
            break;
        case R.id.captureImage:
            takeImage();
            break;

        default:
            break;
    }
}

private void takeImage() {
    camera.takePicture(null, null, new Camera.PictureCallback() {

        private File imageFile;

        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            try {
                // convert byte array into bitmap
                Bitmap loadedImage = null;
                Bitmap rotatedBitmap = null;
                loadedImage = BitmapFactory.decodeByteArray(data, 0, data.length);

                // rotate Image
                Matrix rotateMatrix = new Matrix();
                rotateMatrix.postRotate(rotation);
                rotatedBitmap = Bitmap.createBitmap(loadedImage, 0, 0,
                        loadedImage.getWidth(), loadedImage.getHeight(),
                        rotateMatrix, false);
                String state = Environment.getExternalStorageState();
                File folder = null;
                if (state.contains(Environment.MEDIA_MOUNTED)) {
                    folder = new File(Environment
                            .getExternalStorageDirectory() + "/Demo");
                } else {
                    folder = new File(Environment
                            .getExternalStorageDirectory() + "/Demo");
                }

                boolean success = true;
                if (!folder.exists()) {
                    success = folder.mkdirs();
                }
                if (success) {
                    java.util.Date date = new java.util.Date();
                    imageFile = new File(folder.getAbsolutePath()
                            + File.separator
                            + new Timestamp(date.getTime()).toString()
                            + "Image.jpg");

                    imageFile.createNewFile();
                    Toast.makeText(getActivity().getBaseContext(), "Image Saved", Toast.LENGTH_SHORT).show();
                    openCamera(cameraId);
                } else {
                    Toast.makeText(getActivity().getBaseContext(), "Image Not saved", Toast.LENGTH_SHORT).show();
                    return;
                }

                ByteArrayOutputStream ostream = new ByteArrayOutputStream();

                // save image into gallery
                rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, ostream);

                FileOutputStream fout = new FileOutputStream(imageFile);
                fout.write(ostream.toByteArray());
                fout.close();
                ContentValues values = new ContentValues();

                values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());
                values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
                values.put(MediaStore.MediaColumns.DATA, imageFile.getAbsolutePath());
                getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

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

        }
    });

}


private void flipCamera() {
    int id = (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK ? Camera.CameraInfo.CAMERA_FACING_FRONT
            : Camera.CameraInfo.CAMERA_FACING_BACK);
    if (!openCamera(id)) {
        alertCameraDialog();
    }
}

private void alertCameraDialog() {
    Toast.makeText(getActivity(), "Error to open camera", Toast.LENGTH_SHORT).show();
}


private void flashOnButton() {
    if (camera != null) {
        try {
            Camera.Parameters param = camera.getParameters();
            param.setFlashMode(!flashmode ? Camera.Parameters.FLASH_MODE_TORCH
                    : Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(param);
            flashmode = !flashmode;
        } catch (Exception e) {
            // TODO: handle exception
        }

    }
}

这是我的相机片段代码。当我在运行时授予权限时,surfaceview不会显示相机。它只会在onResume()或该片段中的任何按钮单击时显示相机。如何解决这个问题?如何设置当我点击权限允许按钮时,它会自动在surface view中显示相机。

6个回答

9

在 onCreate 方法中将 surfaceView 的可见性设置为 INVISIBLE。

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

    if (checkCameraHardware(this) == false) {
        showDialogForExit();
    }
    surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
    surfaceView.setVisibility(View.INVISIBLE);
    infoTextview = (TextView) findViewById(R.id.info_text);
    askForPermissions();
}

然后在将cameraSource与surfaceView绑定后,将surfaceView的可见性设置为VISIBLE。
        surfaceView.setVisibility(View.VISIBLE);

安卓有时候很不可预测... 不,它总是不可预测的。我们必须使用setVisibility函数来在用户授权后恢复预览。 - Sanket Bhangale

1
请使用这个类:

public class RunTimePermission extends Activity {

private Activity activity;
private ArrayList<PermissionBean> arrayListPermission;
private String[] arrayPermissions;
private RunTimePermissionListener runTimePermissionListener;

public RunTimePermission(Activity activity)
{
    this.activity = activity;
}

public class PermissionBean
{

    String permission;
    boolean isAccept;
}

public void requestPermission(String[] permissions, RunTimePermissionListener runTimePermissionListener)
{
    this.runTimePermissionListener = runTimePermissionListener;
    arrayListPermission = new ArrayList<PermissionBean>();


    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    {
        for (int i = 0; i < permissions.length; i++)
        {
            PermissionBean permissionBean = new PermissionBean();
            if (ContextCompat.checkSelfPermission(activity, permissions[i]) == PackageManager.PERMISSION_GRANTED)
            {
                permissionBean.isAccept = true;
            }
            else
            {
                permissionBean.isAccept = false;
                permissionBean.permission = permissions[i];
                arrayListPermission.add(permissionBean);
            }


        }

        if (arrayListPermission.size() <= 0)
        {
            runTimePermissionListener.permissionGranted();
            return;
        }
        arrayPermissions = new String[arrayListPermission.size()];
        for (int i = 0; i < arrayListPermission.size(); i++)
        {
            arrayPermissions[i] = arrayListPermission.get(i).permission;
        }
        activity.requestPermissions(arrayPermissions, 10);
    }
    else
    {
        if (runTimePermissionListener != null)
        {
            runTimePermissionListener.permissionGranted();
        }
    }
}

public interface RunTimePermissionListener
{

    void permissionGranted();

    void permissionDenied();
}

private void callSettingActivity()
{
    Intent intent = new Intent();
    intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
    Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
    intent.setData(uri);
    activity.startActivity(intent);

}

private void checkUpdate()
{
    boolean isGranted = true;
    int deniedCount = 0;
    for (int i = 0; i < arrayListPermission.size(); i++)
    {
        if (!arrayListPermission.get(i).isAccept)
        {
            isGranted = false;
            deniedCount++;
        }
    }

    if (isGranted)
    {
        if (runTimePermissionListener != null)
        {
            runTimePermissionListener.permissionGranted();
        }
    }
    else
    {
        if (runTimePermissionListener != null)
        {

            setAlertMessage();
            runTimePermissionListener.permissionDenied();
        }
    }
}

public void setAlertMessage()
{
    AlertDialog.Builder adb;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        adb = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Light_Dialog_Alert);
    } else {
        adb = new AlertDialog.Builder(activity);
    }

    adb.setTitle(activity.getResources().getString(R.string.app_name));
    String msg = "<p>Dear User, </p>" +
            "<p>Seems like you have <b>\"Denied\"</b> the minimum requirement permission to access more features of application.</p>" +
            "<p>You must have to <b>\"Allow\"</b> all permission. We will not share your data with anyone else.</p>" +
            "<p>Do you want to enable all requirement permission ?</p>" +
            "<p>Go To : Settings >> App > " + activity.getResources().getString(R.string.app_name) + " Permission : Allow ALL</p>";

    adb.setMessage(Html.fromHtml(msg));
    adb.setPositiveButton("Allow All", new AlertDialog.OnClickListener()
    {

        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            callSettingActivity();
            dialog.dismiss();
        }
    });

    adb.setNegativeButton("Remind Me Later", new AlertDialog.OnClickListener()
    {

        @Override
        public void onClick(DialogInterface dialog, int which)
        {
            dialog.dismiss();
        }
    });
    if (!((Activity) activity).isFinishing() && msg.length() > 0)
    {
        adb.show();
    }
    else
    {
        Log.v("log_tag", "either activity finish or message length is 0");
    }
}

private void updatePermissionResult(String permissions, int grantResults)
{

    for (int i = 0; i < arrayListPermission.size(); i++)
    {
        if (arrayListPermission.get(i).permission.equals(permissions))
        {
            if (grantResults == 0)
            {
                arrayListPermission.get(i).isAccept = true;
            }
            else
            {
                arrayListPermission.get(i).isAccept = false;
            }
            break;
        }
    }

}


public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
{
    for (int i = 0; i < permissions.length; i++)
    {
        updatePermissionResult(permissions[i], grantResults[i]);
    }
    checkUpdate();
}
}

将以下代码编写在您的activity的onCreate()方法中

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    runTimePermission = new RunTimePermission(this);
    runTimePermission.requestPermission(new String[]{Manifest.permission.CAMERA,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE
    }, new RunTimePermission.RunTimePermissionListener() {

        @Override
        public void permissionGranted() {
            // First we need to check availability of play services
            initControls();

            identifyOrientationEvents();

            //create a folder to get image
            folder = new File(Environment.getExternalStorageDirectory() + "/Media");
            if (!folder.exists()) {
                folder.mkdirs();
            }
            //capture image on callback
            captureImageCallback();
            //
            if (camera != null) {
                Camera.CameraInfo info = new Camera.CameraInfo();
                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    imgFlashOnOff.setVisibility(View.GONE);
                }
            }
        }

        @Override
        public void permissionDenied() {
        }
    });

那么将这段代码写在onCreate()之外

  @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (runTimePermission != null) {
        runTimePermission.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

1
抱歉回复晚了,但这可能对某些人有用。只需在您的onRequestPermissionsResult中调用启动相机方法,像这样:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    Utils.log(TAG, "onRequestPermissionsResult call");
    if (requestCode == REQUEST_CAMERA_PERMISSION) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            Utils.log(TAG, "Permission granted - show camera");
            if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                try {
                    cameraSource.start(surfaceView.getHolder());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

展示相机的默认方式可能如下所示:

surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                cameraSource.start(surfaceView.getHolder());
                Utils.log(TAG, "Check permission: granted - start camera");
            } else {
                Utils.log(TAG, "Check permission: restricted - request");
                requestPermissions(new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

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

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        cameraSource.stop();
    }
});

1

这对我有用:

在获取权限或显示任何对话框之前,将界面可见性设置为GONE

surfaceView.setVisibility(View.GONE);

然后在获取权限或关闭对话框后,将表面可见性设置为VISIBLE
surfaceView.setVisibility(View.VISIBLE);

0

在这里,您必须接收您的权限详细信息

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CAMERA_PERMISSION:
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    //Here call or Open your camera;
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }

获取更多信息:

链接1:https://developer.android.com/training/permissions/requesting.html

链接2:https://www.androidhive.info/2016/11/android-working-marshmallow-m-runtime-permissions/


在我添加了这个默认语句之后,问题仍未解决。 - Velayutham M
你的 onRequestPermissionsResult 方法被调用了吗?在给予权限之后... - Raja
我的问题是在我给予相机权限后,预览界面不显示相机。屏幕变成了黑色。只有当我点击翻转相机等按钮时,才会显示相机。我希望能够找到一种解决方案,使得当我给予权限时,预览界面可以自动显示相机。 - Velayutham M
@VelayuthamM 你找到解决问题的办法了吗?我也遇到了同样的问题。 - Anass Boukalane

0
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case REQUEST_CODE:
                for (int result : grantResults) {
                    if (result == PackageManager.PERMISSION_GRANTED) {
                        surfaceView.setVisibility(View.VISIBLE);    //   <----there u go
                        return;
                    } else {
                        if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,
                                Manifest.permission.CAMERA)) {

                        } else {
                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{Manifest.permission.CAMERA},
                                    CODE_REQUESTED_1);
                        }
                    }
                }

        }
    }

虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - Dharman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接