Camera Intent with Kotlin – Android

Camera Intent with Kotlin | Camera feature in our App with Kotlin

We know that in many situations our app needs to use the Camera of the device to take pictures, You might know how to use Camera feature in your Android app with Java which is a traditional language for Android Development.

Here we are going to learn how to use Camera feature in our App with Kotlin.

Add permissions

Make sure that you have added the following permissions into your manifest.xml file.

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

Set up Layout

We are going to setup Layout file for MainActivity.xml. Our layout consists of an ImageView and a Capture Button as given below.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <LinearLayout
       android:layout_centerInParent="true"
       android:orientation="vertical"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">

       <ImageView
           android:id="@+id/image_view"
           android:background="@drawable/img_placehlder"
           android:layout_gravity="center_horizontal"
           android:layout_width="200dp"
           android:layout_height="300dp" />
       <Button
           android:id="@+id/btn_capture"
           android:text="Capture"
           android:layout_marginTop="12dp"
           android:layout_gravity="center_horizontal"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />

   </LinearLayout>

</RelativeLayout>

The layout will be like this.

Camera Intent with Kotlin

Set Up MainActivity

Now we are going to set up our MainActivity.kt, Have the following methods.

Firstly we need to handle the permissions, From Android 6.0 (Marshmellow) Google introduced Run time permissions. We need to declare the permissions in the manifest.xml file and then request these permissions in runtime so that user can approve or decline each permission.  Add the following code to check permissions and request permission

private fun checkPersmission(): Boolean {
        return (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) ==
                PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
    }

    private fun requestPermission() {
        ActivityCompat.requestPermissions(this, arrayOf(READ_EXTERNAL_STORAGE, CAMERA),
        PERMISSION_REQUEST_CODE)
    }
    

We need to Configure the FileProvider in our app’s manifest.xml file to add a provider to our application.

<application>
   ... 
<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.android.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_path">
                
            </meta-data>
        </provider>
    ...
</application>

Create a new xml file file_path.xml under  res/xml folder.  Make sure you have added your package name in the path instead of “com.jigopost.cameraintent”

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images"
        path="Android/data/com.jigopost.cameraintent/files/Pictures" />
</paths>

We are going to check this permission in Capture Button click. So if the user is already given the permissions to access Camera and External Storage we can directly open the Camera to take Picture. But we should manage the onRequestPermissionsresult() to open the camera after the request for permissions and if the user accepted it. This includes a method takePicture() which is defined later. The code is given below

MainActivity.kt

package com.jigopost.cameraintent

import android.Manifest.permission.CAMERA
import android.Manifest.permission.READ_EXTERNAL_STORAGE
import android.app.Activity
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.support.v4.content.FileProvider
import android.support.v7.app.AppCompatActivity
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.Toast
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*


class MainActivity : AppCompatActivity() {
    lateinit var imageView: ImageView
    lateinit var captureButton: Button

    val REQUEST_IMAGE_CAPTURE = 1


    private val PERMISSION_REQUEST_CODE: Int = 101

    private var mCurrentPhotoPath: String? = null;
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        imageView = findViewById(R.id.image_view)
        captureButton = findViewById(R.id.btn_capture)
        captureButton.setOnClickListener(View.OnClickListener {
            if (checkPersmission()) takePicture() else requestPermission()
        })


    }


    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        when (requestCode) {
            PERMISSION_REQUEST_CODE -> {

                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)
                        && grantResults[1] == PackageManager.PERMISSION_GRANTED) {

                    takePicture()

                } else {
                    Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show()
                }
                return
            }

            else -> {

            }
        }
    }

    private fun takePicture() {

        val intent: Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        val file: File = createFile()

        val uri: Uri = FileProvider.getUriForFile(
                this,
                "com.example.android.fileprovider",
                file
        )
        intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE)

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {

            //To get the File for further usage
            val auxFile = File(mCurrentPhotoPath)


            var bitmap: Bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath)
            imageView.setImageBitmap(bitmap)

        }
    }

    private fun checkPersmission(): Boolean {
        return (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) ==
                PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
    }

    private fun requestPermission() {
        ActivityCompat.requestPermissions(this, arrayOf(READ_EXTERNAL_STORAGE, CAMERA), PERMISSION_REQUEST_CODE)
    }

    @Throws(IOException::class)
    private fun createFile(): File {
        // Create an image file name
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val storageDir: File = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        return File.createTempFile(
                "JPEG_${timeStamp}_", /* prefix */
                ".jpg", /* suffix */
                storageDir /* directory */
        ).apply {
            // Save a file: path for use with ACTION_VIEW intents
            mCurrentPhotoPath = absolutePath
        }
    }
}


Output – Camera Intent with Kotlin

Camera Intent with Kotlin

Read More

Add a Back Button to Action Bar Android Studio (Kotlin)

Leave a Reply