1

I've tried to implement a preview for CameraX, but I've got two errors in my code, that I cannot solve:

  1. CameraSelector is not public in androidx.camera.core.CameraSelector. Cannot be accessed from outside package.

  2. Cannot resolve symbol 'previewView'

EDIT: I solved the problems, but I still don't get the preview. I did not mentioned before, but I inserted the permissions in the Android Manifest.

Here's my code:

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private ListenableFuture<ProcessCameraProvider> cameraProviderFuture;

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

        PreviewView previewView = (PreviewView) findViewById(R.id.previewView);

        cameraProviderFuture = ProcessCameraProvider.getInstance(this);

        cameraProviderFuture.addListener(() -> {
            try {
                ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
                Preview preview = new Preview.Builder().build();
                CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); 
                preview.setSurfaceProvider(previewView.createSurfaceProvider());     
                cameraProvider.unbindAll();
                cameraProvider.bindToLifecycle((LifecycleOwner)this, cameraSelector, preview);
            } catch (ExecutionException | InterruptedException e) {
                e.printStackTrace();
            }
        }, ContextCompat.getMainExecutor(this));

    }

}

Build.gradle (Module: app), inside dependencies section

def camerax_version = "1.0.0-beta07"
implementation "androidx.camera:camera-core:$camerax_version"
implementation "androidx.camera:camera-camera2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androidx.camera:camera-view:1.0.0-alpha14"

activity_main.xml

<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">

    <androidx.camera.view.PreviewView
        android:id="@+id/previewView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

I know that createSurfaceProvider() has been renamed to getSurfaceProvider() since Camera-View Version 1.0.0-alpha16, but when I try to call the last method Android Studio does not solve it.

And here's the logs (error)

2020-11-22 20:59:01.944 10830-10830/? E/Zygote: isWhitelistProcess - Process is Whitelisted
2020-11-22 20:59:01.945 10830-10830/? E/Zygote: accessInfo : 1
2020-11-22 20:59:03.214 10830-10885/com.android.unipi.camerademo E/Camera_APM :: [APM]APM's Thread is started
2020-11-22 20:59:03.216 10830-10885/com.android.unipi.camerademo E/Camera_APM :: [APM] This app is forground app
2020-11-22 20:59:03.223 10830-10872/com.android.unipi.camerademo E/SequentialExecutor: Exception while executing runnable androidx.camera.camera2.internal.-$$Lambda$Camera2CameraImpl$_NFNV64YCFFY0Tn3VRiyE3Ss3S0@5d0b8a
    java.lang.SecurityException: validateClientPermissionsLocked:1145: Caller "com.android.unipi.camerademo" (PID 10188, UID 10830) cannot open camera "0" without camera permission
        at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:855)
        at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:499)
        at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:670)
        at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:638)
        at androidx.camera.camera2.internal.compat.CameraManagerCompatApi28Impl.openCamera(CameraManagerCompatApi28Impl.java:70)
        at androidx.camera.camera2.internal.compat.CameraManagerCompat.openCamera(CameraManagerCompat.java:185)
        at androidx.camera.camera2.internal.Camera2CameraImpl.openCameraDevice(Camera2CameraImpl.java:871)
        at androidx.camera.camera2.internal.Camera2CameraImpl.openInternal(Camera2CameraImpl.java:236)
        at androidx.camera.camera2.internal.Camera2CameraImpl.tryAttachUseCases(Camera2CameraImpl.java:691)
        at androidx.camera.camera2.internal.Camera2CameraImpl.lambda$attachUseCases$10$Camera2CameraImpl(Camera2CameraImpl.java:649)
        at androidx.camera.camera2.internal.-$$Lambda$Camera2CameraImpl$_NFNV64YCFFY0Tn3VRiyE3Ss3S0.run(Unknown Source:4)
        at androidx.camera.core.impl.utils.executor.SequentialExecutor$QueueWorker.workOnQueue(SequentialExecutor.java:230)
        at androidx.camera.core.impl.utils.executor.SequentialExecutor$QueueWorker.run(SequentialExecutor.java:172)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: android.os.ServiceSpecificException: validateClientPermissionsLocked:1145: Caller "com.android.unipi.camerademo" (PID 10188, UID 10830) cannot open camera "0" without camera permission (code 1)
        at android.os.Parcel.createException(Parcel.java:1980)
        at android.os.Parcel.readException(Parcel.java:1934)
        at android.os.Parcel.readException(Parcel.java:1884)
        at android.hardware.ICameraService$Stub$Proxy.connectDevice(ICameraService.java:359)
        at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:463)
        at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:670) 
        at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:638) 
        at androidx.camera.camera2.internal.compat.CameraManagerCompatApi28Impl.openCamera(CameraManagerCompatApi28Impl.java:70) 
        at androidx.camera.camera2.internal.compat.CameraManagerCompat.openCamera(CameraManagerCompat.java:185) 
        at androidx.camera.camera2.internal.Camera2CameraImpl.openCameraDevice(Camera2CameraImpl.java:871) 
        at androidx.camera.camera2.internal.Camera2CameraImpl.openInternal(Camera2CameraImpl.java:236) 
        at androidx.camera.camera2.internal.Camera2CameraImpl.tryAttachUseCases(Camera2CameraImpl.java:691) 
        at androidx.camera.camera2.internal.Camera2CameraImpl.lambda$attachUseCases$10$Camera2CameraImpl(Camera2CameraImpl.java:649) 
        at androidx.camera.camera2.internal.-$$Lambda$Camera2CameraImpl$_NFNV64YCFFY0Tn3VRiyE3Ss3S0.run(Unknown Source:4) 
        at androidx.camera.core.impl.utils.executor.SequentialExecutor$QueueWorker.workOnQueue(SequentialExecutor.java:230) 
        at androidx.camera.core.impl.utils.executor.SequentialExecutor$QueueWorker.run(SequentialExecutor.java:172) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:764) 

According to the logs, I don't insert camera permission, but I do that. Maybe I miss other permissions?

Mata2907
  • 61
  • 7
  • 1
    Could you share logs from when you run the app? Also, if you're testing on a device running on API level 23 or later, are you requesting the camera permission in runtime? – Husayn Hakeem Feb 05 '21 at 00:34
  • Thank you for the response, @Husayn Hakeem. I have two devices: one has Android 9 (API 28) the other has Android 5.1 (API 22). For my project I need both devices. For the moment I run my app only on the first device. I tried to add the logs (error) in my post: I'm new with Android-studio so I'm not sure that I get what you are asking for. – Mata2907 Feb 05 '21 at 14:53
  • 1
    Isn't camera a runtime permission? Are oyu requesting that permission before calling CameraX code? – Shark Feb 05 '21 at 14:56
  • Thanks @Shark. Now it works! I don't add runtime permission. And thank you too, Husayn – Mata2907 Feb 05 '21 at 15:19
  • @Mata2907 feel free to post it as an answer then and accept it. i heard there's badges for answering your own questions ;) – Shark Feb 05 '21 at 15:59
  • @Shark Thank you for the information, but I think it's more fair putting the following link: https://stackoverflow.com/questions/38552144/how-get-permission-for-camera-in-android-specifically-marshmallow – Mata2907 Feb 05 '21 at 16:42
  • not quite... while that link does answer your question, this question has nothing to do with it - the answer to your question is to request the runtime permission. So by answering your own questions, you literally help everyone that searches for "camerax preview" and finding your own answer here. Otherwise, i would have flagged it as duplicate. – Shark Feb 05 '21 at 16:47

1 Answers1

2

With the suggestions of Husayn and Shark I've solved the problem. Any device with Android 6 or higher version (API 23+) requires a runtime permission.

Check if the user has granted the camera permission. Otherwise, request that permission. Insert the following code inside the onCreate() method before calling CameraX code:

if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST);
}

where CAMERA_REQUEST is a constant. Here's an example:

private static final int CAMERA_REQUEST = 100;

Then, it will appear a dialog, in which the user can allow or deny the permission. We can see the result with the following method:

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == CAMERA_REQUEST) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                Toast.makeText(this, "CameraX permission granted", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(this, "CameraX permission denied", Toast.LENGTH_SHORT).show();
            }
        }
    }
Mata2907
  • 61
  • 7