In this tutorial we will go step-by-step on how to implement camera2 in our android app through opening a dialog with camera view, capturing a picture and display it in an ImageView without the need to open the default camera app or any other app in Android studio. This will add a great functionality to your apps.

Permissions

We will add the following permissions to our AndroidManifest.xml:

1
2
3
4
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.hardware.camera2.full" />

Since this a demo, I will ask for these permissions a button in the MainActivity.java is pressed

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    btnOpenCamera = findViewById(R.id.btnOpenCamera);


    btnOpenCamera.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            checkPermissions();
        }
    });

}

We will ask for the multiple permissions as following

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private void checkPermissions() {
    //Permissions we need
    String[] permissions = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.CAMERA
    };
    //Permissions that we will ask for
    ArrayList<String> needed_permissions = new ArrayList<>();

    //Check which is not granted yet
    for (String permission : permissions){
        if (ContextCompat.checkSelfPermission(MainActivity.this, permission) !=
                PackageManager.PERMISSION_GRANTED){
            needed_permissions.add(permission);
        }
    }

    //Ask for multiple not granted permissions
    if(!needed_permissions.isEmpty())
        ActivityCompat.requestPermissions(MainActivity.this, needed_permissions.toArray(new String[needed_permissions.size()]), ALL_PERMISSIONS);
    else
        openCameraDialog();
}

Then we handle the result of the permissions’ request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == ALL_PERMISSIONS){
        if ((grantResults.length > 0) &&
                (grantResults[0]
                        + grantResults[1]
                        + grantResults[2] == PackageManager.PERMISSION_GRANTED)){
            //This method will open the popup (dialog) cameraview 
            openCameraDialog();
            
        }else {
            Toast.makeText(MainActivity.this, "All permissions need to be granted", Toast.LENGTH_LONG)
                    .show();
        }
    }
}

CameraView dialog XML

We will use some floating button, a cameraView, and a smooth way to insert images in the imageView in our work so we will need CameraKit and the following dependencies

1
2
3
4
5
6
7
implementation 'com.android.support:design:28.0.0'
implementation 'com.camerakit:camerakit:1.0.0-beta3.11'
implementation 'com.camerakit:jpegkit:0.1.0'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0'
implementation 'com.github.bumptech.glide:glide:4.9.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'

We will also Vector asset to download some icons for our buttons on the cameraView dialog, then we will create our camera_view.xml in drawable/layout

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <com.camerakit.CameraKitView
        android:id="@+id/cameraKitView"
        app:camera_facing="back"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <ImageView
        android:id="@+id/imgView"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        android:visibility="gone"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:padding="16dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        android:gravity="center"
        android:layout_marginBottom="16dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fabCapture"
            android:alpha="0.5"
            android:src="@drawable/ic_camera_camera_24dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_centerHorizontal="true"/>
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fabRepeat"
            android:src="@drawable/ic_loop_white_24dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            android:alpha="0.5"
            android:layout_marginEnd="16dp"/>
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fabDone"
            android:src="@drawable/ic_done_white_24dp"
            android:layout_width="wrap_content"
            android:visibility="gone"
            android:alpha="0.5"
            android:layout_height="wrap_content" />
    </LinearLayout>

</RelativeLayout>

Now we are ready to use our cameraview dialog in an alert dialog within MainActivity.java

CameraView dialog JAVA

We will handle opening the dialog, and all button actions on the CameraView via our following method

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
private void openCameraDialog() {
    
    //Inflating the AlertDialog
    final AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
    LayoutInflater inflater = getLayoutInflater();
    View dialogView = inflater.inflate(R.layout.camera_view, null);
    alertDialog.setView(dialogView);

    //CameraView UI
    final AlertDialog screen = alertDialog.create();
    final CameraKitView cameraKitView = dialogView.findViewById(R.id.cameraKitView);
    final FloatingActionButton fabCapture = dialogView.findViewById(R.id.fabCapture);
    final FloatingActionButton fabDone = dialogView.findViewById(R.id.fabDone);
    final FloatingActionButton fabRepeat = dialogView.findViewById(R.id.fabRepeat);
    final ImageView imageView = dialogView.findViewById(R.id.imgView);


    //Handler
    final File[] image = {null};

    //We start the camera
    cameraKitView.onStart();


    //Capturing action
    fabCapture.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            cameraKitView.captureImage(new CameraKitView.ImageCallback() {
                @SuppressLint("RestrictedApi")
                @Override
                public void onImage(final CameraKitView cameraKitView, byte[] bytes) {
                    File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "Photos");
                    if (!folder.exists())
                        folder.mkdirs();
                    image[0] = new File(folder.getAbsoluteFile() + File.separator + "photo.jpg");
                    if (image[0].exists())
                        image[0].delete();

                    FileOutputStream outputStream = null;
                    try {
                        outputStream = new FileOutputStream(image[0].getPath(), false);
                        outputStream.write(bytes);
                        outputStream.flush();
                        outputStream.close();
                        Glide.with(MainActivity.this)
                                .load(image[0])
                                .skipMemoryCache(true)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .into(imageView);
                        cameraKitView.setVisibility(View.GONE);
                        imageView.setVisibility(View.VISIBLE);
                        fabCapture.setVisibility(View.GONE);
                        fabDone.setVisibility(View.VISIBLE);
                        fabRepeat.setVisibility(View.VISIBLE);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    });

    //Recapturing
    fabRepeat.setOnClickListener(new View.OnClickListener() {
        @SuppressLint("RestrictedApi")
        @Override
        public void onClick(View view) {
            imageView.setVisibility(View.GONE);
            cameraKitView.setVisibility(View.VISIBLE);
            fabRepeat.setVisibility(View.GONE);
            fabDone.setVisibility(View.GONE);
            fabCapture.setVisibility(View.VISIBLE);
        }
    });

    //Done, let's display it in the imgViewMainActivity
    fabDone.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (image[0] != null)
                Glide.with(MainActivity.this)
                        .load(image[0])
                        .skipMemoryCache(true)
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .into(imgViewMainActivity);
            screen.dismiss();
        }
    });
    
    //To let us start new capturing
        screen.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialogInterface) {
                cameraKitView.stopVideo();
                cameraKitView.onStop();
            }
        });

    //Display the dialog
    screen.show();
}

And that’s it, here we go!

Library

I have also created an android library that will save your time and effort if you wanted to use it, you can find it here.

Result

CameraKitExample1 CameraKitExample2 CameraKitExample3