Si je n'utilise que CAMERA_FACING_BACK
ou CAMERA_FACING_FRONT
, tout va bien.
J'ai des problèmes avec le passage de CAMERA_FACING_BACK
à CAMERA_FACING_FRONT
.
Mon extrait de code:
public class PhotoCameraActivity extends Activity implements OnClickListener {
private SurfaceView cameraView;
private Button turnButton;
private Camera camera = null;
private Callback listener;
private static int camId = Camera.CameraInfo.CAMERA_FACING_BACK;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_camera_main);
prepareActivity();
}
private void prepareActivity() {
cameraView = (SurfaceView) findViewById(R.id.photo_camera_surface_view);
turnButton = (ImageButton) findViewById(R.id.turn_button);
turnButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.equals(turnButton)) {
if (Camera.getNumberOfCameras() > 1 && camId < Camera.getNumberOfCameras() - 1) {
startCamera(camId + 1);
} else {
startCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
}
}
}
@Override
protected void onResume() {
startCamera(camId);
super.onResume();
}
@Override
protected void onPause() {
stopCamera();
super.onPause();
}
private void startCamera(int cameraId) {
if (camera != null) {
stopCamera();
}
holder = cameraView.getHolder();
listener = new Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
};
holder.addCallback(listener);
camId = cameraId;
camera = Camera.open(cameraId);
Camera.Parameters params = camera.getParameters();
if (cameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
params.setPreviewSize(1280, 800);
} else {
params.setPreviewSize(640, 480);
}
camera.setParameters(params);
}
private void stopCamera(){
System.out.println("stopCamera method");
if (camera != null){
camera.stopPreview();
camera.setPreviewCallback(null);
camera.release();
camera = null;
holder.removeCallback(listener);
holder = null;
}
}
}
Je redémarre l'activité avec cameraId = 2 et cela fonctionne.
Dans onCreate () de mon activité, j'ajoute l'écouteur onClick suivant à un bouton superposé à ma fenêtre Preview SurfaceView (il existe de nombreux exemples sur le Web pour la prévisualisation):
ImageButton useOtherCamera = (ImageButton) findViewById(R.id.useOtherCamera);
//if phone has only one camera, hide "switch camera" button
if(Camera.getNumberOfCameras() == 1){
useOtherCamera.setVisibility(View.INVISIBLE);
}
else {
useOtherCamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (inPreview) {
camera.stopPreview();
}
//NB: if you don't release the current camera before switching, you app will crash
camera.release();
//swap the id of the camera to be used
if(currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK){
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
}
else {
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
}
camera = Camera.open(currentCameraId);
//Code snippet for this method from somewhere on Android developers, i forget where
setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera);
try {
//this step is critical or preview on new camera will no know where to render to
camera.setPreviewDisplay(previewHolder);
} catch (IOException e) {
e.printStackTrace();
}
camera.startPreview();
}
Sur mon périphérique de test, la caméra arrière a un ID de 0 et la face avant est un. Je suggère d'utiliser des variables statiques Camera.CameraInfo pour les ID de votre caméra plutôt que des valeurs codées en dur. Je suis sûr que cela ne causera que des problèmes sur d'autres appareils.
J'ai supprimé et rajouté SurfaceView dans ma mise en page et cela a donc fonctionné.
public void switchCamera(int cameraType)
{
if(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT))
{
if(Camera.getNumberOfCameras() > cameraType)
{
// Set selected camera
this.cameraType = cameraType;
}
else
{
// Set default camera (Rear)
this.cameraType = Camera.CameraInfo.CAMERA_FACING_BACK;
}
if(mCamera != null)
{
// Destroy previuos Holder
surfaceDestroyed(holder);
holder.removeCallback(this);
// Remove and re-Add SurfaceView
ViewGroup rootLayout = (ViewGroup) surface.getParent();
rootLayout.removeView(surface);
surface = new SurfaceView(context);
holder = surface.getHolder();
holder.addCallback(this);
rootLayout.addView(surface, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
}
Je dois supprimer l'aperçu de la surface avant d'en ajouter un nouveau:
if (mPreview != null) {
mPreview.surfaceDestroyed(mPreview.getHolder());
mPreview.getHolder().removeCallback(mPreview);
mPreview.destroyDrawingCache();
FrameLayout preview = (FrameLayout) view.findViewById(R.id.camera_frame);
preview.removeView(mPreview);
mPreview.mCamera = null;
mPreview = null;
}
//then add your preview
Utilisez ce code:
if (mCamera != null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//swap the id of the camera to be used
if (currentCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
currentCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
else
currentCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
try {
mCamera = Camera.open(currentCameraId);
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
}
catch (Exception e) { e.printStackTrace(); }