<< RETURN: Coding / Android / Coding with Android Studio
Introduction
If you just want to capture an image with the Camera and store it in your Android App for future or immediate use, you can achieve this by starting an activity with an intent that has the following action, "android.media.action.IMAGE_CAPTURE"
Camera interfacing application in action
Full Sample Code
The code for the following files are displayed in this section: MainActivity.kt, activity_main.xml, and AndroidManifest.xml.
package com.example.androidlab
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.widget.Button
import android.widget.ImageView
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private lateinit var button: Button
private lateinit var imageView: ImageView
private val CAMERA_PERMISSION_CODE = 1
private lateinit var cameraActivityResultLauncher: ActivityResultLauncher<Intent>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.button)
imageView = findViewById(R.id.imageView)
registerActivityResultLauncher()
button.setOnClickListener {
if (ContextCompat.checkSelfPermission(
applicationContext,
android.Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraActivityResultLauncher.launch(intent)
} else {
ActivityCompat.requestPermissions(
this@MainActivity,
arrayOf(android.Manifest.permission.CAMERA),
CAMERA_PERMISSION_CODE
)
}
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_PERMISSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraActivityResultLauncher.launch(intent)
}
}
}
private fun registerActivityResultLauncher() {
cameraActivityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { resultCamera ->
val resultCode = resultCamera.resultCode
val data = resultCamera.data
if (resultCode == RESULT_OK && data != null) {
val extras = data.extras
val imageBitmap: Bitmap? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
extras!!.getParcelable("data", Bitmap::class.java)
} else {
extras!!["data"] as Bitmap?
}
imageView.setImageBitmap(imageBitmap)
}
}
}
}
Kotlin<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="58dp"
android:text="Capture"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<ImageView
android:id="@+id/imageView"
android:layout_width="237dp"
android:layout_height="227dp"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_camera" />
</androidx.constraintlayout.widget.ConstraintLayout>
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">
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
<application
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AndroidLab"
tools:targetApi="31">
<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>
XMLCode Breakdown
Step 1 – Update your manifest XML file
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.CAMERA" />
XMLIn-between your <manifest> tag and above (outside) the <application> tag, add the above two lines to tell the device that your application require permissions to the Camera.
Step 2 – Add Permission Checks
Within the code logic of any user interface element (i.e. buttons), add the programming logic to check if Camera permissions were granted, and grant them if they were not already done so.
if (ContextCompat.checkSelfPermission(
applicationContext,
android.Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraActivityResultLauncher.launch(intent)
} else {
ActivityCompat.requestPermissions(
this@MainActivity,
arrayOf(android.Manifest.permission.CAMERA),
CAMERA_PERMISSION_CODE
)
}
KotlinThis simple if-else block uses ContextCompat.checkSelfPermission(@NonNull Context context, @NonNull String permission) to decide whether or not to request for permissions. If permissions wasn’t granted, the application will request for it. At this point, users will encounter a prompt asking them if they will allow the application to take pictures and record video. Note that this will only happen the first time this application is used, or when the camera permission is not granted for this application.
Step 3 – Add Permission Result and Activity Result Launcher
So what happens when after you grant the permission? It needs to start the default camera application, take a picture, and return the resulting image data.
First of, lets declare the ActivityResultLauncher variable.
private val CAMERA_PERMISSION_CODE = 1
private lateinit var cameraActivityResultLauncher: ActivityResultLauncher<Intent>
KotlinNote that the camera permission code is used to identify the permission request and launch the correct ActivityResultLauncher.
Then, override the onRequestPermissionsResult function. We want it to launch the Camera application after the permission has been granted.
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String?>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAMERA_PERMISSION_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraActivityResultLauncher.launch(intent)
}
}
}
KotlinLast but not least, add the ActivityResultLauncher code to the button (or to the relevant UI element).
val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
cameraActivityResultLauncher.launch(intent)
KotlinStep 4 – Register the ActivityResultLauncher
private fun registerActivityResultLauncher() {
cameraActivityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { resultCamera ->
val resultCode = resultCamera.resultCode
val data = resultCamera.data
if (resultCode == RESULT_OK && data != null) {
val extras = data.extras
val imageBitmap: Bitmap? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
extras!!.getParcelable("data", Bitmap::class.java)
} else {
extras!!["data"] as Bitmap?
}
imageView.setImageBitmap(imageBitmap)
}
}
}
KotlinRegistering this ActivityResultLauncher with the StartActivityForResult() contract, tells your application that any intent launched with this ActivityResultLauncher will return to this section of code. Upon proper result return, the acquired image bitmap is used to fill the ImageView.
Next Up
Once you’re done, you can also check out Taking Photos with Camera Previews. (TBD)