Android Camera Permission Essentials: Streamlining with BaseActivity

Ken Ruiz Inoue
Deuk
Published in
7 min readFeb 23, 2024

Introduction

Welcome to an essential guide designed to transform how you manage camera permissions in your Android applications. In this tutorial, we delve into the intricacies of leveraging BaseActivity, an approach that not only simplifies permission management but also significantly reduces the complexity within MainActivity. The integration of camera functionality stands at the forefront of mobile technology innovation, merging the realms of real-time data processing and machine learning (ML) to unlock new possibilities for what smartphones are capable of achieving.

This journey is crafted to arm you with the code insights and comprehensive understanding necessary to effortlessly integrate camera permissions into your apps, thereby unlocking new dimensions of capability and enhancing user experiences. Without further ado, let’s embark on this crucial journey to fully leverage the expansive potential of mobile camera technology.

Environment

  • Android Studio Hedgehog | 2023.1.1 Patch 2
  • Compose version: androidx.compose:compose-bom:2023.08.00
  • Pixel 4 API 28 Emulator (With Default Camera App)
  • Pixel 6 API 30 (Without Default Camera )

Step 1: Project Setup and AndroidManifest Update

Getting Started

Begin by launching Android Studio and initiating a new project. Opt for the “Empty Activity” template to establish a clean slate.

Configuring AndroidManifest.xml

Next, navigate to your project’s AndroidManifest.xml file.

Android View
Project View

It’s time to declare the permissions and features your app will need to interact with the device’s camera. Insert the following lines within the <manifest> tag but outside the <application> tag.

...
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false" />
<application
...

Understanding Permissions and Features

  • The uses-permission tag is crucial as it explicitly requests permission to use the device's camera. This step is mandatory for any app that intends to capture images or videos.
  • The uses-feature tag, while not strictly necessary for running this demo, plays a vital role in the broader app ecosystem. By declaring the camera as a non-required feature, you inform the Google Play Store (and users) that your app can function without it.

Step 2: BaseActivity for Permission Handling Logic

In this section, we’ve already laid out the foundation for BaseActivity, a crucial component for streamlining camera permission handling in Android apps. This approach not only simplifies permission management in MainActivity but also any other activity that requires camera access.

// Your package

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.provider.MediaStore
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat

// Open class allowing extension, so activities like MainActivity can inherit from it
// for common camera permission handling functionality
open class BaseActivity : ComponentActivity() {

// Key Point 1: Camera Permission Request Launcher
// Declare a launcher for the camera permission request, handling the permission result
private val cameraPermissionRequestLauncher: ActivityResultLauncher<String> =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
// Permission granted: proceed with opening the camera
startDefaultCamera()
} else {
// Permission denied: inform the user to enable it through settings
Toast.makeText(
this,
"Go to settings and enable camera permission to use this feature",
Toast.LENGTH_SHORT
).show()
}
}

// Key Point 2: Camera Intent Launcher
// Declare a launcher for taking a picture, handling the result of the camera app
private val takePictureLauncher: ActivityResultLauncher<Intent> =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
// This can be expanded to handle the result data
Toast.makeText(this, "Photo taken", Toast.LENGTH_SHORT).show()
}

// Checks camera permission and either starts the camera directly or requests permission
fun handleCameraPermission() {
when {
ContextCompat.checkSelfPermission(
this,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED -> {
// Permission is already granted: start the camera
startDefaultCamera()
}

else -> {
// Permission is not granted: request it
cameraPermissionRequestLauncher.launch(Manifest.permission.CAMERA)
}
}
}

// Starts the default camera app for taking a picture
private fun startDefaultCamera() {
Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
takePictureIntent.resolveActivity(packageManager)?.also {
// Camera app is available: launch it
takePictureLauncher.launch(takePictureIntent)
} ?: run {
// No camera app available: inform the user
Toast.makeText(this, "No camera app available", Toast.LENGTH_SHORT).show()
}
}
}
}

Key Point 1: Camera Permission Request Launcher

  • ActivityResultLauncher simplifies handling permissions and activity results, avoiding the cumbersome onActivityResult method. It's a modern approach that streamlines the permission request flow.
  • By registering an ActivityResultLauncher with ActivityResultContracts.RequestPermission(), developers can request permissions in a more straightforward manner. The launcher handles user responses to permission requests and returns a boolean indicating the outcome.

Key Point 2: Camera Intent Launcher

  • This launcher is tailored for activities that expect a result back, such as capturing a photo with the camera. It launches the camera activity and handles the return, which could include image data or confirmation of the action.
  • Unlike the permission launcher, ActivityResultContracts.StartActivityForResult() is used for any activity result, not just permissions. It's ideal for operations like taking pictures, where you manage the outcome (e.g., displaying the captured photo) through a callback function.

Step 3: MainActivity Update

To seamlessly integrate camera permission handling into your application, let’s focus on updating MainActivity.

// Your package

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

// MainActivity inherits from BaseActivity to utilize camera permission handling logic
class MainActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Box(
modifier = Modifier.fillMaxSize()
) {
Button(
onClick = {
// Calls handleCameraPermission() from BaseActivity when the button is clicked
// This function checks for camera permission and requests it if not already granted
handleCameraPermission()
},
modifier = Modifier.align(Alignment.BottomCenter)
) {
Text(text = "Take Photo")
}
}
}
}
}

Upon application launch, expect the camera permission dialogue to appear. The UI of this dialogue may differ across API levels due to variations in Android’s permission handling.

If the device does not have a compatible camera application to handle the intent, the user will be informed through a “No camera app available” message. This scenario highlights the importance of validating the presence of a camera app before attempting to capture an image.

Pixel 6 API 30 (Without Default Camera )

In contrast, if a compatible camera app is available and the photo capture process completes successfully, a “Photo Taken” message will be displayed, indicating the operation’s success.

Pixel 4 API 28 Emulator (With Default Camera App)

Conclusion

Congratulations on mastering the essentials of camera permission handling in Android apps! This tutorial marks a significant step in your journey towards becoming proficient in integrating advanced functionalities into your applications. Remember, the journey in Android development is continuous, filled with endless opportunities for growth and innovation.

I encourage you to keep exploring and deepening your knowledge in Android development. My collection of guides, built on over a decade of experience, is designed to help you advance your skills further. Each guide aims to not only enhance your technical abilities but also to instill best practices that will stand you in good stead throughout your career.

Thank you for following along. If you found this guide helpful, please show your support with claps and consider following for more insights into modern Android development. Your engagement and feedback inspire me to share more valuable content. Stay curious, keep learning, and I eagerly anticipate accompanying you on your next steps in this exciting development journey. Happy coding!

Deuk Services: Your Gateway to Leading Android Innovation

Are you looking to boost your business with top-tier Android solutions?Partner with Deuk services and take your projects to unparalleled heights.

🚀 Boost Your Productivity with Notion

New to Notion? Discover how it can revolutionize your productivity

Ready to take your productivity to the next level? Integrate this content into your Notion workspace with ease:

1. Access the Notion Version of this Content

2. Look for the Duplicate button at the top-right corner of the page

3. Click on it to add this valuable resource to your Notion workspace

Seamlessly integrate this guide into your Notion workspace for easy access and swift reference. Leverage Notion AI to search and extract crucial insights, enhancing your productivity. Start curating your knowledge hub with Notion AI today and maximize every learning moment.

--

--