4

I'm having a problem with the Android Camera API. I was debugging because

camera=Camera.open() 

always returned null, while permissions were configured in android.Manifest, and the rear camera was available.

So I checked for the availability and the number of cameras Android found:

Context context = getContext();
boolean b = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
int count = getNumberOfCameras();
camera = getCameraInstance();

Boolean b (which checks if the device has a camera) returns true, as expected. But meanwhile, count (which gets the number of available cameras) returns 0.

My java class:

package com.example.wouter.zytholog;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;

import java.io.IOException;
import java.util.List;

import static android.hardware.Camera.*;

/**
 * Created by wouter on 3/04/2018.
 */

    public class CameraFragment extends Fragment implements SurfaceHolder.Callback {
        static Camera camera = null;
        PictureCallback mCallback;

        Button mCaptureBtn;
        SurfaceHolder mHolder;
        SurfaceView mView;

        final int CAMERA_REQUEST_CODE = 1;
        public static CameraFragment newInstance(){
            CameraFragment fragment = new CameraFragment();
            return fragment;
        }

        @Nullable
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_camera, container, false);

            mView = view.findViewById(R.id.surfaceView);
            mHolder = mView.getHolder();

            if(ActivityCompat.checkSelfPermission(getContext(),android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED){
                ActivityCompat.requestPermissions(getActivity(), new String[] {android.Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
            }

            else{
                mHolder.addCallback(this);
                mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }

            mCaptureBtn = view.findViewById(R.id.capture);
            mCaptureBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    capture();
                }
            });

            mCallback = new PictureCallback() {
                @Override
                public void onPictureTaken(byte[] bytes, Camera camera) {
                    Intent i = new Intent(getActivity(), showBeerActivity.class);
                    i.putExtra("capture", bytes);
                    startActivity(i);
                    return;
                }
            };
            Context context = getContext();
            boolean b = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
            int count = getNumberOfCameras();
            camera = getCameraInstance();

            return view;
        }

        private void capture() {
            camera.takePicture(null,null,mCallback);
        }

        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {



        }

        private Camera getCameraInstance() {
            Camera c = null;
            try{
                c= open();
            }
            catch(Exception e){
            }
            return c; //returns null if camera is not available
        }

        @Override
        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

        }

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

        }

        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            switch(requestCode){
                case CAMERA_REQUEST_CODE:{
                    if(grantResults.length >0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
                        mHolder.addCallback(this);
                        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
                    }else{
                        Toast.makeText(getContext(), "Please give us permission to the camera", Toast.LENGTH_LONG).show();
                    }
                    break;
                }
            }
        }
    }

Android.Manifest:

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

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

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

    <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=".LogoScreenActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".MainActivity" />
        <activity android:name=".LoginOrRegisterActivity" />
        <activity android:name=".LoginActivity" />
        <activity android:name=".RegisterActivity" />
        <activity android:name=".showBeerActivity"></activity>
    </application>

</manifest>
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • 2
    https://stackoverflow.com/questions/32635704/android-permission-doesnt-work-even-if-i-have-declared-it – CommonsWare May 03 '18 at 12:08
  • 1
    Don't hide the exception in `getCameraInstance()` : `try{c= open();}catch(Exception e){ }`. This should explain the problem. PS: this is called before you accept the permission for the camera... – AxelH May 03 '18 at 12:17
  • 1
    Thanks for the help! The problem was I never released the camera in my code, and that's why after a first run the camera wasn't available – Wouter Standaert May 03 '18 at 16:47

2 Answers2

1
private CameraManager mManager;
private String[] mCameraIds;
mManager = (CameraManager)getSystemService(Context.CAMERA_SERVICE);
mCameraIds = mManager.getCameraIdList();
Igor
  • 2,039
  • 23
  • 27
  • While this code may help with the question, it is better to include some context, explaining how it works and when to use it. Code-only answers tend to be less useful in the long run. See [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer) for some more info. – Klaus Gütter Jun 12 '20 at 12:00
-1

getnumberofcameras is static method try use it as

count =Camera.getNumberOfCameras ();
  • Already done, he import the static method with `import static android.hardware.Camera.*;` so `getNumberOfCameras()` calls `Camera` static method. – AxelH May 03 '18 at 12:25