Camera availability tip

[Courtesy of gringo4tech]

It’s been a lot of time since I have written something interesting on Android. Following post is on how should we properly listen for camera being released. Duh!

Assume we are have to make our Service aware of camera usage, like Google Photos does it with the option to show Photos logo after you capture new image, for quick navigation to Photos gallery.

Their Service is triggered byJobScheduler that starts job when there are changes in MediaStore.Images.Media.EXTERNAL_CONTENT_URI. But how do they manage to remove fb-chat-head-like-shortcut-icon once you close the camera app? They are waiting for the app to release the camera (≥ Lollipop) and wait for camera app to be removed from foreground (< Lollipop).

There are two concerns here:
- API levels of the given CameraManager API methods
- API levels of the given ActivityManager API methods

Base class:

A centralized way to listen for camera availability.

public class CameraAvailability {
public static CameraAvailability get(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new CameraAvailabilityLollipop(context);
}
return new CameraAvailabilityPreLolipop(context);
}

void waitForCameraBeingAvailable(OnCameraReleasedListener l) {
throw new UnsupportedOperationException("Don't call super!");
}
interface OnCameraReleasedListener {
void onCameraAvailable();
}
}

Lollipop and above

In camera2 package CameraManager offers really simple way to listen for camera availability, just by using registerAvailabilityCallback() method

Prior Lollipop

After Lollipop there was uproar about how to get current visible activity, since getAppTasks() joined deprecation club. This is really great opportunity to leverage ActivityManager.

Here we are monitoring the current top activity is any of the list of activities that can handle ACTION_IMAGE_CAPTURE intent action. Once the current activity is no longer capable of handling our target intent action, it means that camera has been released. Recursive Runnable checks every 200ms.

On Stackoverflow there is a proposed way to use old Camera API and anticipating a RuntimeException to be thrown if the camera is used when we are attempting to open it.

I’m not fan of this proposed way, because it tries to throw exception and dumping the stacktrace might slow down your device, and it tries to open() and immediately release() the camera just to return boolean.

Usage:

private void registerForCameraAvailability() {
CameraAvailability cameraAvailability = CameraAvailability.get(this);
cameraAvailability.waitForCameraBeingAvailable(this);
}

Knitting code. One line at a time. @ WS Audiology

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Java Basics — Ep.16

How to write code when people keep interrupting you.

How to deploy an EFK stack to Kubernetes.

Gitlab CI Shell runner SSH Deploy

AWS SSH with Session Manager

Which is the best Football API

Advantages and Disadvantages of Compiled Languages

CI/CD with a mean app on AWS CodePipeline

A CI/CD pipeline integrates building and testing from commits, and automates deployment

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Nikola Despotoski

Nikola Despotoski

Knitting code. One line at a time. @ WS Audiology

More from Medium

Getting… rid of those missing android* source sets warnings on your KMP project

Scope functions in Kotlin

What makes Kotlin different?

Using reflection to patch gaps in current Compose APIs