我正在研究需要控制相機的應用程序,但我嘗試初始化時遇到了問題。使用按鈕初始化相機導致空白屏幕,在onCreate中初始化工作正常
如果我在onCreate()
裏面調用功能SafeOpenCamera()
一切正常,我可以看到相機預覽。但是,如果我按下按鈕時嘗試調用它,預覽的區域應爲空白。
在這兩種情況下,「Camera started」都會被記錄下來,我也沒有例外。
我試圖弄清楚這幾天,但我找不到原因。 我需要用一個按鈕激活它,以便用戶可以選擇使用哪個相機,並希望在應用程序運行時交換它們。
主要活動:
public class MainActivity extends ActionBarActivity {
private Camera mCamera;
private CameraPreview mPreview;
private View mCameraView;
private Button ulButton;
private int current_camera=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ulButton= (Button) findViewById(R.id.ul_button);
ulButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// If I try to start the camera with the button, the preview area goeas blank
boolean opened = safeOpenCamera((FrameLayout) findViewById(R.id.preview_layout), current_camera);
if (opened == false) {
Log.d("Camera", "Error, Camera failed to open");
} else {
Log.d("Camera", "Camera started");
}
}
});
// If I place the code for opening the camera here, it works fine: //
/*boolean opened = safeOpenCamera((FrameLayout) findViewById(R.id.preview_layout), current_camera);
if (opened == false) {
Log.d("Camera", "Error, Camera failed to open");
} else {
Log.d("Camera", "Camera started");
}*/
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
private boolean safeOpenCamera(View view, int camera_id){
Log.d("SafeOpenCamera","starting method");
boolean qOpened=false;
releaseCameraAndPreview();
Log.d("SafeOpenCamera", "camera id " + camera_id);
mCamera=getCameraInstance(camera_id);
mCamera.setDisplayOrientation(90);
mCameraView=view;
qOpened=(mCamera!=null);
if(qOpened==true) {
Log.d("SafeOpenCamera","qOpened true");
mPreview = new CameraPreview(getBaseContext(), mCamera,mCameraView);
FrameLayout preview = (FrameLayout) findViewById(R.id.preview_layout);
preview.addView(mPreview);
mPreview.startCameraPreview();
//addItemsOnSpinner2(mPreview.getSizes());
}
return qOpened;
}
public Camera getCameraInstance(int camera_id){
Camera c=null;
try{
c = Camera.open(camera_id);
}catch (Exception e){
e.printStackTrace();
}
return c;
}
private void releaseCameraAndPreview(){
if(mCamera!=null) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
//if(mPreview!=null){
//mPreview.destroyDrawingCache();
//}
}
}
預覽類:
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Context mContext;
private Camera.Size mPreviewSize;
private List<Camera.Size> mSupportedPreviewSizes;
private List<Camera.Size> mSupportedSizes;
private List<String> mSupportedFlashModes;
private View mCameraView;
public CameraPreview(Context context, Camera camera, View cameraView){
super(context);
mCameraView=cameraView;
mContext=context;
setCamera(camera);
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void startCameraPreview(){
try{
Log.d("Terminal preview","Try set preview");
mCamera.setPreviewDisplay(mHolder);
Log.d("Terminal preview", "Try start preview");
mCamera.startPreview();
}catch(Exception e){
Log.d("Terminal preview","exception");
e.printStackTrace();
}
}
public List<Camera.Size> getSizes(){
return mCamera.getParameters().getSupportedPictureSizes();
}
private void setCamera(Camera camera){
Log.d("Terminal preview","set camera");
mCamera=camera;
mSupportedPreviewSizes=mCamera.getParameters().getSupportedPreviewSizes();
mSupportedSizes=mCamera.getParameters().getSupportedPictureSizes();
mSupportedFlashModes=mCamera.getParameters().getSupportedFlashModes();
Camera.Parameters parameters=mCamera.getParameters();
Log.d("Terminal preview","set rotation");
parameters.setRotation(90);
if(mSupportedFlashModes!=null && mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO)){
Log.d("Terminal preview","set flash mode");
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
}
Log.d("Terminal preview","set params");
mCamera.setParameters(parameters);
Log.d("Terminal preview", "requesting layout...");
requestLayout();
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
Log.d("Terminal preview", "Surface changed");
if (mHolder.getSurface()==null){
Log.d("Terminal preview","mHolder null, return");
return;
}
try{
Log.d("Terminal preview","Try stop preview");
mCamera.stopPreview();
}catch (Exception e){
Log.d("Terminal", "surfaceChanged exception stopPreview");}
try{
Camera.Parameters parameters=mCamera.getParameters();
if (mCamera.getParameters().getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
Log.d("Terminal preview", "set focus mode");
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
}
if(mPreviewSize!=null){
Camera.Size previewSize=mPreviewSize;
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
mCamera.setParameters(parameters);
mCamera.startPreview();
}catch (Exception e){
Log.d("Terminal","surfaceChanged exception");
e.printStackTrace();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try{
Log.d("Terminal preview", "try surfaceCreated");
if(mCamera==null){Log.d("Terminal","mCamera es null");}
if(holder==null){Log.d("Terminal","holder es null");}
mCamera.setPreviewDisplay(holder);
mCamera.startPreview(); //
}catch (IOException e ){
Log.d("Terminal preview", "exception surfaceCreated");
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("Terminal preview", "surface destroyed");
if (mCamera!=null){
try{
mCamera.stopPreview();
mCamera=null;
}catch (Exception e){Log.d("Terminal preview", "exception surface destroyed");}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
Log.d("Terminal preview", "onMeassure");
final int width=resolveSize(getSuggestedMinimumWidth(),widthMeasureSpec);
final int height=resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes!=null){
mPreviewSize=getOptimalPreviewSize(mSupportedPreviewSizes,width,height);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Log.d("Terminal preview", "onLayout");
if (changed) {
final int width=right-left;
final int height=top-bottom;
int previewWidth=width;
int previewHeight=height;
if(mPreviewSize!=null){
Display display=((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation()){
case Surface.ROTATION_0:
previewWidth=mPreviewSize.height;
previewHeight=mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth=mPreviewSize.width;
previewHeight=mPreviewSize.height;
break;
case Surface.ROTATION_180:
previewWidth=mPreviewSize.height;
previewHeight=mPreviewSize.width;
break;
case Surface.ROTATION_270:
previewWidth=mPreviewSize.width;
previewHeight=mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
}
Log.d("Terminal","t,b,l,r: "+top+" "+bottom+" "+left+" "+right);
Log.d("Terminal","w: "+width);
Log.d("Terminal","h: "+height);
Log.d("Terminal","pw: "+previewWidth);
Log.d("Terminal","ph: "+previewHeight);
final int scaledChildHeight=previewHeight*width/previewWidth;
Log.d("Terminal","h-sh: "+(height-scaledChildHeight));
mCameraView.layout(0, height - scaledChildHeight, width, height);
}
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int width, int height){
Log.d("Terminal preview", "getOptimalPreviewSize");
Camera.Size optimalSize=null;
final double ASPECT_TOLERANCE=0.1;
double targetRatio = (double)height/width;
for(Camera.Size size: sizes){
if(size.height!=width) continue;
double ratio=(double)size.width/size.height;
if(ratio<=targetRatio+ASPECT_TOLERANCE && ratio >targetRatio-ASPECT_TOLERANCE){
optimalSize=size;
}
}
if(optimalSize==null){
}
return optimalSize;
}
}
這是我得到時,相機的onCreate(初始化日誌)(正常工作的那個)
/SafeOpenCamera﹕ starting method
/SafeOpenCamera﹕ camera id 1
/dalvikvm﹕ Note: class Lcom/lge/mdm/manager/ILGMDMDevicePolicyManager$Stub; has 235 unimplemented (abstract) methods
/SafeOpenCamera﹕ qOpened true
/Terminal preview﹕ set camera
/Terminal preview﹕ set rotation
/Terminal preview﹕ set params
/Terminal preview﹕ requesting layout...
/Terminal preview﹕ Try set preview
/Camera﹕ app passed NULL surface
/Terminal preview﹕ Try start preview
/Camera﹕ Camera started
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/libEGL﹕ loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
/libEGL﹕ loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
/libEGL﹕ loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
/OpenGLRenderer﹕ Enabling debug mode 0
/Terminal preview﹕ onLayout
/Terminal﹕ t,b,l,r: 0 300 0 492
/Terminal﹕ w: 492
/Terminal﹕ h: -300
/Terminal﹕ pw: 492
/Terminal﹕ ph: -300
/Terminal﹕ h-sh: 0
/Terminal preview﹕ onLayout
/Terminal preview﹕ try surfaceCreated
/Terminal preview﹕ Surface changed
/Terminal preview﹕ Try stop preview
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/Terminal preview﹕ onLayout
下面是當我嘗試用按鈕(不工作的那個)初始化它時得到的日誌
/ViewRootImpl﹕ ViewRoot TouchDown(Absolute) DOWN (105 , 202)
/SafeOpenCamera﹕ starting method
/SafeOpenCamera﹕ camera id 1
/dalvikvm﹕ Note: class Lcom/lge/mdm/manager/ILGMDMDevicePolicyManager$Stub; has 235 unimplemented (abstract) methods
/SafeOpenCamera﹕ qOpened true
/Terminal preview﹕ set camera
/Terminal preview﹕ set rotation
/Terminal preview﹕ set params
/Terminal preview﹕ requesting layout...
/Terminal preview﹕ Try set preview
/Camera﹕ app passed NULL surface
/Terminal preview﹕ Try start preview
/Camera﹕ Camera started
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/Terminal preview﹕ onMeassure
/Terminal preview﹕ getOptimalPreviewSize
/Terminal preview﹕ onLayout
/Terminal﹕ t,b,l,r: 0 300 0 492
/Terminal﹕ w: 492
/Terminal﹕ h: -300
/Terminal﹕ pw: 492
/Terminal﹕ ph: -300
/Terminal﹕ h-sh: 0
/Terminal preview﹕ onLayout
/Terminal preview﹕ try surfaceCreated
/Terminal preview﹕ Surface changed
/Terminal preview﹕ Try stop preview
日誌之間唯一的區別似乎是,當預覽表被成功繪製onMeassure()被調用,並且加載庫:libEGL_POWERVR_SGX540_120.so,libGLESv1_CM_POWERVR_SGX540_120.so和libGLESv2_POWERVR_SGX540_120.so,和我不知道它們是否與相機有關。
在佈局中,我將預覽區設置爲彩色背景,當我嘗試使用按鈕初始化預覽時,會變成白色,addView()是無法正常工作的函數。
的源代碼可以在這裏萬一有人發現有檢查的時間: dropbox
你不需要'mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);'。那現在沒用了。生病檢查,看看有什麼可能導致你的問題,雖然 – Aggressor
你是否獲取日誌的預覽開始? – Aggressor
你可以發佈日誌輸出,當你使用按鈕,當你只是添加它? – Aggressor