More generally, if a device has more than one embedded camera,
is there a way to initialize one of them in particular?
I didn't find it in Android reference documentation:
https://developer.android.com/reference/android/hardware/Camera.html
https://developer.android.com/reference/android/hardware/camera2/package-summary.html
https://developer.android.com/reference/android/hardware/camera2/CameraManager.html
Samsung SHW-M100S has two cameras. If there is no reference to use two cameras, any idea how Samsung did...?
private Camera openFrontFacingCameraGingerbread() {
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
try {
cam = Camera.open(camIdx);
} catch (RuntimeException e) {
Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
}
}
}
return cam;
}
Add the following permissions in the AndroidManifest.xml file:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
Note: This feature is available in Gingerbread(2.3) and Up Android Version.
All older answers' methods are deprecated by Google (supposedly because of troubles like this), since API 21 you need to use the Camera 2 API:
This class was deprecated in API level 21. We recommend using the new
android.hardware.camera2 API for new applications.
In the newer API you have almost complete power over the Android device camera and documentation explicitly advice to
String[] getCameraIdList()
and then use obtained CameraId to open the camera:
void openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)
99% of the frontal cameras have id = "1", and the back camera id = "0"
according to this:
Non-removable cameras use integers starting at 0 for their
identifiers, while removable cameras have a unique identifier for each
individual device, even if they are the same model.
However, this means if device situation is rare like just 1-frontal -camera tablet you need to count how many embedded cameras you have, and place the order of the camera by its importance ("0"). So CAMERA_FACING_FRONT == 1 CAMERA_FACING_BACK == 0, which implies that the back camera is more important than frontal.
I don't know about a uniform method to identify the frontal camera on all Android devices. Simply said, the Android OS inside the device can't really find out which camera is exactly where for some reasons: maybe the only camera hardcoded id is an integer representing its importance or maybe on some devices whichever side you turn will be .. "back".
Documentation: https://developer.android.com/reference/android/hardware/camera2/package-summary.html
Explicit Examples: https://github.com/googlesamples/android-Camera2Basic
For the older API (it is not recommended, because it will not work on modern phones newer Android version and transfer is a pain-in-the-arse). Just use the same Integer CameraID (1) to open frontal camera like in this answer:
cam = Camera.open(1);
If you trust OpenCV to do the camera part:
Inside
<org.opencv.android.JavaCameraView
../>
use the following for the frontal camera:
opencv:camera_id="1"
As of Android 2.1, Android only supports a single camera in its SDK. It is likely that this will be added in a future Android release.
To open the back camera:-
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)
To open the front camera:-
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.O -> {
cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT) // Tested on API 24 Android version 7.0(Samsung S6)
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT) // Tested on API 27 Android version 8.0(Nexus 6P)
cameraIntent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true)
}
else -> cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", 1) // Tested API 21 Android version 5.0.1(Samsung S4)
}
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)
I could not make it work for API 28 and above. Also, opening the front camera directly is not possible in some devices(depends on the manufacturer).
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
Camera.Parameters p = mCamera.getParameters();
p.set("camera-id",2);
mCamera.setParameters(p);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
For API 21 (5.0) and later you can use the CameraManager API's
try {
String desiredCameraId = null;
for(String cameraId : mCameraIDsList) {
CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
List<CameraCharacteristics.Key<?>> keys = chars.getKeys();
try {
if(CameraCharacteristics.LENS_FACING_FRONT == chars.get(CameraCharacteristics.LENS_FACING)) {
// This is the one we want.
desiredCameraId = cameraId;
break;
}
} catch(IllegalArgumentException e) {
// This key not implemented, which is a bit of a pain. Either guess - assume the first one
// is rear, second one is front, or give up.
}
}
}
With the release of Android 2.3 (Gingerbread), you can now use the android.hardware.Camera class to get the number of cameras, information about a specific camera, and get a reference to a specific Camera. Check out the new Camera APIs here.
build.gradle
dependencies {
compile 'com.google.android.gms:play-services-vision:9.4.0+'
}
Set View
CameraSourcePreview mPreview = (CameraSourcePreview) findViewById(R.id.preview);
GraphicOverlay mGraphicOverlay = (GraphicOverlay) findViewById(R.id.faceOverlay);
CameraSource mCameraSource = new CameraSource.Builder(context, detector)
.setRequestedPreviewSize(640, 480)
.setFacing(CameraSource.CAMERA_FACING_FRONT)
.setRequestedFps(30.0f)
.build();
mPreview.start(mCameraSource, mGraphicOverlay);
Camera camera;
if (Camera.getNumberOfCameras() >= 2) {
//if you want to open front facing camera use this line
camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);
//if you want to use the back facing camera
camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
}
try {
camera.setPreviewDisplay("your surface holder here");
camera.startPreview();
} catch (Exception e) {
camera.release();
}
/* This is not the proper way, this is a solution for older devices that run Android 4.0 or older. This can be used for testing purposes, but not recommended for main development. This solution can be considered as a temporary solution only. But this solution has helped many so I don't intend to delete this answer*/
I found this works nicely.
fun frontCamera(context: Context): Int {
val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
return cameraManager.cameraIdList
.find { id ->
cameraManager.getCameraCharacteristics(id)[LENS_FACING] == LENS_FACING_FRONT
}?.toInt() ?: 0
}
Related
Problem happening on a Nokia 6 with Android 7.1.1
Permission granted
AppOpsManager#checkOp(AppOpsManager.OPSTR_CAMERA, Process.myUid(), getPackageName()) returns AppOpsManager#MODE_ALLOWED
Yet when trying Camera.open(i) for checking camera properties I get
I/CameraService: Camera 0: Access for "package" has been restricted
Apparently this could only happen [1] if application's package or uId has been explicitly restricted from starting AppOpsManager#OP_CAMERA.
But why would this happen? After AppOpsManager#checkOp says AppOpsManager#MODE_ALLOWED
Sample code
for (int i = 0; i < numCameras; ++i) {
List<Size> supportedSizes = null;
List<int[]> supportedFpsRanges = null;
Camera camera = null;
try {
camera = Camera.open(i);
Parameters parameters = camera.getParameters();
supportedSizes = parameters.getSupportedPreviewSizes();
supportedFpsRanges = getFpsRangesRobust(parameters);
} catch (Exception e) {
...
} finally {
if (camera != null) {
camera.release();
}
}
[1] https://github.com/aosp-mirror/platform_frameworks_base/blob/oreo-mr1-release/services/core/java/com/android/server/AppOpsService.java#L2588
Aparently it's a device issue.
Nokia 6 / TA-1000, Android 7.1.1
The scenario
try to use camera
app asks for permission, tap Deny
try to use camera
app asks for permission, tap Allow
Error posted in logcat, camera doesn't work
Is reproducible with any other application, including the default camera app.
Check you have added this line to your app manifest.
android:foregroundServiceType="camera"
I have been working on Custom SurfaceView Camera. I need to work with front camera as my application takes user's selfie.
For that I have checked a for whether front camera is available using below code.
public boolean checkFrontCamera() {
int numCameras = Camera.getNumberOfCameras();
for (int i = 0; i < numCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (CameraSource.CAMERA_FACING_FRONT == info.facing) {
return true;
}
}
return false;
}
Its working fine if device has both the camera, and it returns true. But if device has only one camera, this method always returns false as info.facing is 0 in this case and for the same in this code CameraSource.CAMERA_FACING_FRONT is 1.
for Camera, I have used gms vision library. Below code is for camera source.
CameraSource mCameraSource = new CameraSource.Builder(context, detector)
.setRequestedPreviewSize(640, 480)
.setFacing(CameraSource.CAMERA_FACING_FRONT)
.setRequestedFps(30.0f)
.build();
Here I need to pass camera facing params.
Please provide if any other alternative. All solutions are welcomed.
Well you can use this method, which returns the camera object
private Camera getCameraInstance() {
Camera c = null;
try {
if (Camera.getNumberOfCameras() >= 2) {
//Front facing camera
c = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else {
// only has one camera (Rear)
c = Camera.open();
}
} catch (Exception e) {
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
Camera cam = Camera.open();
Parameters p = cam.getParameters();
p.setFlashMode(Parameters.FLASH_MODE_TORCH);
cam.setParameters(p);
cam.startPreview();
The above dose not work on Lollipop, Because Camera is deprecated in Lollipop. I cant able to find any other way to turn on flash programmatically in Lollipop. How can I achieve this. Thanks in advance.
Camera class is now deprecated.
For LOLLIPOP above you need to use camera2 Api
so nickkadrov's solution doesent work for 6.0 & above device,best way to on/off flash light is try code below
public static void toggleFlashLight(){
toggle=!toggle;
try {
CameraManager cameraManager = (CameraManager) getApplicationContext().getSystemService(Context.CAMERA_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
for (String id : cameraManager.getCameraIdList()) {
// Turn on the flash if camera has one
if (cameraManager.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
cameraManager.setTorchMode(id, true);
}
}
}
}
} catch (Exception e2) {
Toast.makeText(getApplicationContext(), "Torch Failed: " + e2.getMessage(), Toast.LENGTH_SHORT).show();
}
}
where toggle is class level static Boolean variable whose default value is false
static boolean toggle=false;
mCam = Camera.open();
Camera.Parameters p = mCam.getParameters();
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
mCam.setParameters(p);
mPreviewTexture = new SurfaceTexture(0);
try {
mCam.setPreviewTexture(mPreviewTexture);
} catch (IOException ex) {
// Ignore
}
mCam.startPreview();
It works for me on Android 5.0.x. And don't forget to add permission in manifest for camera usage.
<uses-permission android:name="android.permission.CAMERA" />
Your code should actually work. Please check if you added the permission for using the camera properly:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT"/>
This should be added to your AndroidManifest above of your other specifications.
Additionally, there is an interesting discussion about different devices and an example which should work on every device here: Flashlight in Android
If you dont want to use the deprecated API, you can check out:
Package Summary of Camera2
Camera device specification on the new api
Unfortunately I can not give you an example for using the new API, because I did not use it myself yet.
More generally, if a device has more than one embedded camera,
is there a way to initialize one of them in particular?
I didn't find it in Android reference documentation:
https://developer.android.com/reference/android/hardware/Camera.html
https://developer.android.com/reference/android/hardware/camera2/package-summary.html
https://developer.android.com/reference/android/hardware/camera2/CameraManager.html
Samsung SHW-M100S has two cameras. If there is no reference to use two cameras, any idea how Samsung did...?
private Camera openFrontFacingCameraGingerbread() {
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
Camera.getCameraInfo(camIdx, cameraInfo);
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
try {
cam = Camera.open(camIdx);
} catch (RuntimeException e) {
Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
}
}
}
return cam;
}
Add the following permissions in the AndroidManifest.xml file:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
Note: This feature is available in Gingerbread(2.3) and Up Android Version.
All older answers' methods are deprecated by Google (supposedly because of troubles like this), since API 21 you need to use the Camera 2 API:
This class was deprecated in API level 21. We recommend using the new
android.hardware.camera2 API for new applications.
In the newer API you have almost complete power over the Android device camera and documentation explicitly advice to
String[] getCameraIdList()
and then use obtained CameraId to open the camera:
void openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)
99% of the frontal cameras have id = "1", and the back camera id = "0"
according to this:
Non-removable cameras use integers starting at 0 for their
identifiers, while removable cameras have a unique identifier for each
individual device, even if they are the same model.
However, this means if device situation is rare like just 1-frontal -camera tablet you need to count how many embedded cameras you have, and place the order of the camera by its importance ("0"). So CAMERA_FACING_FRONT == 1 CAMERA_FACING_BACK == 0, which implies that the back camera is more important than frontal.
I don't know about a uniform method to identify the frontal camera on all Android devices. Simply said, the Android OS inside the device can't really find out which camera is exactly where for some reasons: maybe the only camera hardcoded id is an integer representing its importance or maybe on some devices whichever side you turn will be .. "back".
Documentation: https://developer.android.com/reference/android/hardware/camera2/package-summary.html
Explicit Examples: https://github.com/googlesamples/android-Camera2Basic
For the older API (it is not recommended, because it will not work on modern phones newer Android version and transfer is a pain-in-the-arse). Just use the same Integer CameraID (1) to open frontal camera like in this answer:
cam = Camera.open(1);
If you trust OpenCV to do the camera part:
Inside
<org.opencv.android.JavaCameraView
../>
use the following for the frontal camera:
opencv:camera_id="1"
As of Android 2.1, Android only supports a single camera in its SDK. It is likely that this will be added in a future Android release.
To open the back camera:-
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)
To open the front camera:-
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.O -> {
cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT) // Tested on API 24 Android version 7.0(Samsung S6)
}
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", CameraCharacteristics.LENS_FACING_FRONT) // Tested on API 27 Android version 8.0(Nexus 6P)
cameraIntent.putExtra("android.intent.extra.USE_FRONT_CAMERA", true)
}
else -> cameraIntent.putExtra("android.intent.extras.CAMERA_FACING", 1) // Tested API 21 Android version 5.0.1(Samsung S4)
}
startActivityForResult(cameraIntent, REQUEST_CODE_CAMERA)
I could not make it work for API 28 and above. Also, opening the front camera directly is not possible in some devices(depends on the manufacturer).
public void surfaceCreated(SurfaceHolder holder) {
try {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(holder);
Camera.Parameters p = mCamera.getParameters();
p.set("camera-id",2);
mCamera.setParameters(p);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
For API 21 (5.0) and later you can use the CameraManager API's
try {
String desiredCameraId = null;
for(String cameraId : mCameraIDsList) {
CameraCharacteristics chars = mCameraManager.getCameraCharacteristics(cameraId);
List<CameraCharacteristics.Key<?>> keys = chars.getKeys();
try {
if(CameraCharacteristics.LENS_FACING_FRONT == chars.get(CameraCharacteristics.LENS_FACING)) {
// This is the one we want.
desiredCameraId = cameraId;
break;
}
} catch(IllegalArgumentException e) {
// This key not implemented, which is a bit of a pain. Either guess - assume the first one
// is rear, second one is front, or give up.
}
}
}
With the release of Android 2.3 (Gingerbread), you can now use the android.hardware.Camera class to get the number of cameras, information about a specific camera, and get a reference to a specific Camera. Check out the new Camera APIs here.
build.gradle
dependencies {
compile 'com.google.android.gms:play-services-vision:9.4.0+'
}
Set View
CameraSourcePreview mPreview = (CameraSourcePreview) findViewById(R.id.preview);
GraphicOverlay mGraphicOverlay = (GraphicOverlay) findViewById(R.id.faceOverlay);
CameraSource mCameraSource = new CameraSource.Builder(context, detector)
.setRequestedPreviewSize(640, 480)
.setFacing(CameraSource.CAMERA_FACING_FRONT)
.setRequestedFps(30.0f)
.build();
mPreview.start(mCameraSource, mGraphicOverlay);
Camera camera;
if (Camera.getNumberOfCameras() >= 2) {
//if you want to open front facing camera use this line
camera = Camera.open(CameraInfo.CAMERA_FACING_FRONT);
//if you want to use the back facing camera
camera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
}
try {
camera.setPreviewDisplay("your surface holder here");
camera.startPreview();
} catch (Exception e) {
camera.release();
}
/* This is not the proper way, this is a solution for older devices that run Android 4.0 or older. This can be used for testing purposes, but not recommended for main development. This solution can be considered as a temporary solution only. But this solution has helped many so I don't intend to delete this answer*/
I found this works nicely.
fun frontCamera(context: Context): Int {
val cameraManager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
return cameraManager.cameraIdList
.find { id ->
cameraManager.getCameraCharacteristics(id)[LENS_FACING] == LENS_FACING_FRONT
}?.toInt() ?: 0
}
How to detect no of camera's available in android device? and also if the device has front camera how to use it?
What I would suggest is similar to doc_180's answer, but should be able to detect both front and back facing cameras even for Froyo, though if I'm not mistaken, Froyo never supported front-facing cameras, so you'll always get a false response for frontCam on Froyo.
PackageManager pm = getPackageManager();
boolean frontCam, rearCam;
//Must have a targetSdk >= 9 defined in the AndroidManifest
frontCam = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
rearCam = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
EDIT: Just realized this is a really, really old question. Oh well, hopefully it helps someone in the future.
Use packagemanager to check if the device supports the Intent. In this case Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
public static boolean isIntentAvailable(Context context, String action) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(action);
List<ResolveInfo> list =
packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
Camera.getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_FRONT) {
}
}
The quickest way I've found to check if a (backfacing) camera exists is to check if Camera.open() returns null.
Camera cam = Camera.open();
if(null == cam){
//no camera exists
}
This should be available for earlier versions of android as well.
you can use this static method if you just want to know how many cameras there are:
Camera.getNumberOfCameras(); (api 9)
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
I am using this method to get the count of the available camera
public int getCameraCount(){
CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
try {
String[] strings = manager.getCameraIdList();
return strings.length;
} catch (CameraAccessException e) {
e.printStackTrace();
return 0;
}
}
Try this, this worked for me in a Moto RAZR HD:
public static Camera open (int cameraId)
Example usage:
mCamera = Camera.open(1);