2012-06-28 42 views
5

嗨,大家好,我試圖在顯示相機預覽的同時在設備的正面和背面相機之間切換。我正在關注通用軟件提供的示例。下面是我正在使用的代碼,每當我點擊翻轉按鈕時,表面視圖變黑,我不知道我哪裏出錯了。請幫我解決這個問題。我搜索了這個,我沒有得到任何合適的答案,因爲有些人試圖重新啓動當前的活動,但我不想那樣。希望得到更好的迴應。提前致謝。Android相機預覽在相機之間切換

package com.commonsware.android.camera; 
import android.app.Activity; 
import android.hardware.Camera; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.widget.CompoundButton; 
import android.widget.CompoundButton.OnCheckedChangeListener; 
import android.widget.Toast; 
import android.widget.ToggleButton; 
public class PreviewDemo extends Activity { 
    private SurfaceView preview = null; 
    private SurfaceHolder previewHolder = null; 
    private Camera camera = null; 
    private boolean inPreview = false; 
    private boolean cameraConfigured = false; 
    private ToggleButton flipCamera; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.main); 
    flipCamera = (ToggleButton) findViewById(R.id.flip); 
    preview = (SurfaceView) findViewById(R.id.preview); 
    previewHolder = preview.getHolder(); 
    previewHolder.addCallback(surfaceCallback); 
    previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    flipCamera.setOnCheckedChangeListener(new OnCheckedChangeListener() { 

     @Override 
     public void onCheckedChanged(CompoundButton buttonView, 
       boolean isChecked) { 
      // TODO Auto-generated method stub 
      restartPreview(isChecked); 
     } 
    }); 

} 

@Override 
public void onResume() { 
    super.onResume(); 

    // camera=Camera.open(); 
    int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    if (Camera.getNumberOfCameras() > 1 
      && camId < Camera.getNumberOfCameras() - 1) { 
     // startCamera(camId + 1); 
     camera = Camera.open(camId + 1); 
    } else { 
     // startCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 
     camera = Camera.open(camId); 
    } 
    startPreview(); 
} 

void restartPreview(boolean isFront) { 
    if (inPreview) { 
     camera.stopPreview(); 
    } 
    // 
    camera.release(); 

    // camera=null; 
    // inPreview=false; 
    // /*int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    // if (Camera.getNumberOfCameras() > 1 && camId < 
    // Camera.getNumberOfCameras() - 1) { 
    // //startCamera(camId + 1); 
    // camera = Camera.open(camId + 1); 
    // } else { 
    // //startCamera(Camera.CameraInfo.CAMERA_FACING_BACK); 
    // camera = Camera.open(camId); 
    // }*/ 
    int camId = Camera.CameraInfo.CAMERA_FACING_BACK; 
    if (isFront) { 
     camera = Camera.open(camId); 
     camera.startPreview(); 

    } else { 
     camera = Camera.open(camId + 1); 
     camera.startPreview(); 

    } 
    // startPreview(); 
} 

@Override 
public void onPause() { 
    if (inPreview) { 
     camera.stopPreview(); 
    } 

    camera.release(); 
    camera = null; 
    inPreview = false; 

    super.onPause(); 
} 

private Camera.Size getBestPreviewSize(int width, int height, 
     Camera.Parameters parameters) { 
    Camera.Size result = null; 

    for (Camera.Size size : parameters.getSupportedPreviewSizes()) { 
     if (size.width <= width && size.height <= height) { 
      if (result == null) { 
       result = size; 
      } else { 
       int resultArea = result.width * result.height; 
       int newArea = size.width * size.height; 

       if (newArea > resultArea) { 
        result = size; 
       } 
      } 
     } 
    } 

    return (result); 
} 

private void initPreview(int width, int height) { 
    if (camera != null && previewHolder.getSurface() != null) { 
     try { 
      camera.setPreviewDisplay(previewHolder); 
     } catch (Throwable t) { 
      Log.e("PreviewDemo-surfaceCallback", 
        "Exception in setPreviewDisplay()", t); 
      Toast.makeText(PreviewDemo.this, t.getMessage(), 
        Toast.LENGTH_LONG).show(); 
     } 

     if (!cameraConfigured) { 
      Camera.Parameters parameters = camera.getParameters(); 
      Camera.Size size = getBestPreviewSize(width, height, parameters); 

      if (size != null) { 
       parameters.setPreviewSize(size.width, size.height); 
       camera.setParameters(parameters); 
       cameraConfigured = true; 
      } 
     } 
    } 
} 

private void startPreview() { 
    if (cameraConfigured && camera != null) { 

     camera.startPreview(); 
     inPreview = true; 
    } 
} 

SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() { 
    public void surfaceCreated(SurfaceHolder holder) { 
     // no-op -- wait until surfaceChanged() 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     initPreview(width, height); 
     startPreview(); 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // no-op 
     if (camera != null) { 
      /* 
      * Call stopPreview() to stop updating the preview surface. 
      */ 
      camera.stopPreview(); 

      /* 
      * Important: Call release() to release the camera for use by 
      * other applications. Applications should release the camera 
      * immediately in onPause() (and re-open() it in onResume()). 
      */ 
      camera.release(); 

      camera = null; 
     } 
    } 
}; 
} 
+0

使'camId'成爲靜態成員,並在檢查更改時再次啓動活動..就像開始自己並在下一行中調用完成一樣......'遞歸活動'.. – Ronnie

+0

@ userSeven7s儘管這樣可以解決問題它不是(在我看來)一個明智的設計選擇。攝像機的一個常見模式是讓它們返回捕獲圖像的路徑。如果我從活動A啓動相機並且相機自行啓動,則從相機獲取結果變得複雜。此外,將遞歸添加到Android的「特殊」生命週期聽起來像是一個可怕的想法。 – TheCrafter

回答

12

你似乎從restartPreviev()方法調用startPreview()之前忘記調用setPreviewDisplay()(或者,你的情況,initPreview())。實際上,您正在嘗試開始預覽,而沒有指定要渲染預覽的曲面。