Take Picture with Camera Intent - Android Studio - Compose

📸 Take Picture with Camera Intent in Android Studio (Compose) — Complete Guide

Learn how to capture images using the Camera Intent in Android Studio with Compose. This step-by-step tutorial covers everything you need to implement a built-in camera feature in your Android app. You’ll understand how to open the camera, handle permissions, save the captured image, and display it inside your application.

Whether you’re a beginner or an experienced Android developer, this guide will help you integrate camera functionality quickly and efficiently using clean and simple Java code.

What this post covers:

  • Requesting camera permissions

  • Launching the Camera Intent

  • Receiving the captured image

  • Displaying and saving the photo

  • Common errors & their solutions

Perfect for Android developers building apps that require image capturing features such as profile photos, scanning, media apps, and more.


Code:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!--Adding Camera, Write External Storage Permission-->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication">

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>

</manifest>

MainActivity.kt

package com.technifysoft.myapplication

import android.Manifest
import android.app.Activity
import android.content.ContentValues
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode.Companion.Color
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.compose.rememberAsyncImagePainter
import coil.request.ImageRequest
import com.technifysoft.myapplication.ui.theme.MyApplicationTheme

class MainActivityCompose : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()

        setContent {
            MainUi()
        }
    }

}

@Composable
fun MainUi() {

    val context = LocalContext.current
    var imageUri by remember { mutableStateOf<Uri?>(null) }
    var lastModified by remember { mutableStateOf(System.currentTimeMillis()) }

    // CAMERA RESULT
    val cameraLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.StartActivityForResult()
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {

            imageUri?.let { uri ->
                // Force update so the image becomes readable
                val values = ContentValues().apply {
                    put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
                }
                context.contentResolver.update(uri, values, null, null)

                // Force recomposition → refresh painter cache
                lastModified = System.currentTimeMillis()
            }

        } else {
            Toast.makeText(context, "Cancelled!", Toast.LENGTH_SHORT).show()
        }
    }

    // Permissions
    val permissionLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        val allGranted = permissions.values.all { it }

        if (allGranted) {
            pickImageFromCamera(context) { uri ->
                imageUri = uri
                val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
                intent.putExtra(MediaStore.EXTRA_OUTPUT, uri)
                cameraLauncher.launch(intent)
            }
        } else {
            Toast.makeText(context, "Permissions denied", Toast.LENGTH_SHORT).show()
        }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(20.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        imageUri?.let { uri ->
            Image(
                painter = rememberAsyncImagePainter(
                    model = "$uri?t=$lastModified" // force reload cache
                ),
                contentDescription = "Captured Image",
                modifier = Modifier
                    .fillMaxWidth()
                    .height(350.dp),
                contentScale = ContentScale.Crop
            )
        }

        Spacer(modifier = Modifier.height(20.dp))

        Button(onClick = {
            val requiredPermissions =
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
                    arrayOf(Manifest.permission.CAMERA)
                else
                    arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)

            permissionLauncher.launch(requiredPermissions)
        }) {
            Text("Capture Image")
        }
    }
}

fun pickImageFromCamera(
    context: android.content.Context,
    onImageUriCreated: (Uri) -> Unit
) {
    val contentValues = ContentValues().apply {
        put(MediaStore.Images.Media.TITLE, "TEMP_IMAGE")
        put(MediaStore.Images.Media.DESCRIPTION, "Captured by Camera")
    }

    val uri = context.contentResolver.insert(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        contentValues
    )

    onImageUriCreated(uri!!)
}

/**
 * GreetingPreview is a composable function for previewing the MainUI in Android Studio.
 * It is annotated with @Preview to enable live preview.
 *
 */
@Preview(showBackground = true)
@Composable
private fun GreetingPreview() {
    MyApplicationTheme {
        MainUi()
    }
}

Screenshots:

Take Picture with Camera - Android Studio - Kotlin

Comments

Popular posts from this blog

Picture In Picture - Android Studio - Kotlin

Manage External Storage Permission - Android Studio - Kotlin

How to add AIDL folder | Android Studio