2013-05-27 25 views
31

Mam metodę o nazwie switchCamera, staram się przełączać kamerę od przodu do tyłu za jednym kliknięciem przycisku, w jednym płynnym przejściu. Moja aplikacja zamarza, gdy nazywam tę metodę - wiem, że nie robię czegoś dobrze. Czy ktoś może mi pomóc?Android: Przełącz kamerę po kliknięciu przycisku

Każda pomoc jest doceniana.

public void switchCamera(){ 
    int camNum = 0; 
    camNum = Camera.getNumberOfCameras(); 
    int camBackId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    int camFrontId = Camera.CameraInfo.CAMERA_FACING_FRONT; 

    Camera.CameraInfo currentCamInfo = new Camera.CameraInfo(); 

    //if camera is running 
    if (camera != null){ 
     //and there is more than one camera 
     if (camNum > 1){ 
      //stop current camera 
      camera.stopPreview(); 
      camera.setPreviewCallback(null); 
      //camera.takePicture(null, null, PictureCallback); 
      camera.release(); 
      camera = null; 
      //stop surfaceHolder? 

      if (currentCamInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT){ 
       //switch camera to back camera 
       camera=Camera.open(camBackId); 
      } 
      else{ 
       //switch camera to front camera 
       camera=Camera.open(camFrontId); 
      } 
      //switch camera back on 
      //specify surface? 
      try { 
       camera.setPreviewDisplay(surfaceHolder); 
       camera.setPreviewCallback((PreviewCallback) this); 
       camera.startPreview(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 
+1

To może pomóc: http: // stackoverflow. com/questions/6599454/switch-front-camera-on-fly – Ben

+1

Czy możesz wkleić niektóre logi w logcat, zanim się zawiesi? – StarPinkER

Odpowiedz

59
Button otherCamera = (Button) findViewById(R.id.OtherCamera); 

otherCamera.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); 

setCameraDisplayOrientation(CameraActivity.this, currentCameraId, camera); 
try { 

    camera.setPreviewDisplay(previewHolder); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
camera.startPreview(); 
} 

Jeśli chcesz, aby pokazać obraz z kamery w tej samej orientacji jak wyświetlacza, można użyć następującego kodu.

public static void setCameraDisplayOrientation(Activity activity, 
     int cameraId, android.hardware.Camera camera) { 
    android.hardware.Camera.CameraInfo info = 
      new android.hardware.Camera.CameraInfo(); 
    android.hardware.Camera.getCameraInfo(cameraId, info); 
    int rotation = activity.getWindowManager().getDefaultDisplay() 
      .getRotation(); 
    int degrees = 0; 
    switch (rotation) { 
     case Surface.ROTATION_0: degrees = 0; break; 
     case Surface.ROTATION_90: degrees = 90; break; 
     case Surface.ROTATION_180: degrees = 180; break; 
     case Surface.ROTATION_270: degrees = 270; break; 
    } 

    int result; 
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 
     result = (info.orientation + degrees) % 360; 
     result = (360 - result) % 360; // compensate the mirror 
    } else { // back-facing 
     result = (info.orientation - degrees + 360) % 360; 
    } 
    camera.setDisplayOrientation(result); 
} 
+0

pomocna odpowiedź, ale jedno pytanie ... Camera.CameraInfo.CAMERA_FACING_BACK/FRONT wymaga poziomu API 9. Co robimy w starszych wersjach? – Anonymous

+0

Nadal obraz z kamery nie jest prawidłowo obracany w trybie pionowym. W trybie poziomym działa poprawnie. – AjayR

+0

Brilliant - zaoszczędziłeś mi mnóstwo czasu dzięki tej fajnej metodzie setCameraDisplayOrientation! – Ewald

-6

Spróbuj użyć AsyncTask. Kod będzie działał w osobnym wątku bez zakłócania wątku interfejsu użytkownika. Istnieje kilka przykładów użycia AsyncTask na tej stronie.

+3

Przepraszamy, ale to nie miało nic wspólnego z wątkiem interfejsu użytkownika. – shkschneider

3

Najpierw trzeba zniszczyć SurfacePreview poprzedniego aparatu, a następnie należy utworzyć nowy obiekt kamery (tył/przód)

`//Code to destroy SurfacePreview 
mPreview.surfaceDestroyed(mPreview.getHolder()); 
mPreview.getHolder().removeCallback(mPreview); 
mPreview.destroyDrawingCache(); 
preview.removeView(mPreview); 
mCamera.stopPreview(); 
mCamera.stopPreview(); 
mCamera.setPreviewCallback(null); 
mCamera.release(); 

//Now create new camera object 
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { 
    mCamera = Camera.open(camIdx); 
    mPreview = new CameraPreview(CameraActivity.this, mCamera); 
    preview.addView(mPreview); 
    mCamera.setPreviewDisplay(mPreview.getHolder()); 
    mCamera.startPreview(); 
}`