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 .
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 Our layout consists of an ImageView and a Capture Button as given below.
<?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 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
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 -> {
}
}
}
Now let’s take a look at takePicture() method. In this method, we set up an Intent to open the Camera. This method consists of a method called createFile() used to create a File to store the Image.
@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
}
}
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 file file_path.xml under res/xml folder. Make sure you have added your package name in the path instead of “com.kotlincodes.cameraintentwithkotlin_android”
<?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.kotlincodes.cameraintentwithkotlin_android/files/Pictures" />
</paths>
Now we can set an Intent to start Camera to capture an Image as follows
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)
}
This method will open the Camera and we can capture an Image. After taking a Picture we need to show this Image on our ImageView. To set the ImageView add the following code
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)
}
}
Now we are all set to run the project. Please find the Complete code for MainActivity.kt file below.
MainActivity.kt
package com.kotlincodes.cameraintentwithkotlin_android
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
}
}
}
That’s it! Now run the project!
The full source code is available here.
kotlincodes/Camera-Intent-with-Kotlin
Camera Intent with Kotlin Android. Contribute to kotlincodes/Camera-Intent-with-Kotlin development by creating an account on GitHub.
Thanks for reading!