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.
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
Read More