2015-07-21 42 views
1

我正在研究需要控制相機的應用程序,但我嘗試初始化時遇到了問題。使用按鈕初始化相機導致空白屏幕,在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

+0

你不需要'mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);'。那現在沒用了。生病檢查,看看有什麼可能導致你的問題,雖然 – Aggressor

+0

你是否獲取日誌的預覽開始? – Aggressor

+0

你可以發佈日誌輸出,當你使用按鈕,當你只是添加它? – Aggressor

回答

0

查看您的代碼後。問題出在onLayout調用上。

如果您忽略更改的參數(始終調用您的代碼),則會出現堆棧溢出,因爲存在無限次數的佈局調用。問題在於你如何使用onLayout的邏輯。我現在不能進一步深入(花了很長時間,因爲它是到這裏哈哈)。但刪除此功能會導致按鈕和非按鈕方案都起作用。

所以我會看看你在佈局代碼中調用更改,並更改你想要如何調整佈局的邏輯。但至於這裏發佈的問題,下面的代碼。刪除此功能,您的代碼將運行。這應該讓你再次去! (違規代碼低於)

@Override 
protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
    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; 
      } 
     } 

     final int scaledChildHeight=previewHeight*width/previewWidth; 

     mCameraView.layout(0, height - scaledChildHeight, width, height); 

    }  
} 
0

我不知道您的具體問題是什麼,但我有類似的問題。代替在SurfaceView處填充視圖,您可以在主佈局中插入一個空寬度爲零的空白寬度。這樣,它會更快。嘗試將它插入到您的主要XML佈局中,activity_main

<SurfaceView android:layout_width="0dp" android:layout_height="0dp" />