2014-01-20 60 views
1

我試圖使可拍照的活動畫面,唯一的問題是,回調是永遠不會被調用。預覽會停止並顯示「請稍候」對話框,因此一切正常,直到該部分。不能採取與Camera.takePicture

我測試上的Galaxy S3 I9300安裝AOKP ROM。 Android版本4.3.1

PictureTaker.java

package ...; 
import everything; 

public class PictureTaker extends Activity { 
    private Preview mPreview; 
    Camera mCamera; 
    int numberOfCameras; 
    int cameraCurrentlyLocked; 

    public AlertDialog diag; 
    protected PowerManager.WakeLock mWakeLock; 

    // The first rear facing camera 
    int defaultCameraId; 


    final Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback() { 
     @Override 
     public void onShutter() { 
      Log.d("Adnan", "onShutter"); 
     } 
    }; 


    final Camera.PictureCallback mPicture = new Camera.PictureCallback() { 
     String picPath = Environment.getExternalStorageDirectory() + "/billsterData/camTemp.jpg"; 

     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      String TAG = "Adnan"; 
      diag.dismiss(); 

      Log.d(TAG, "Attempting to store picture..."); 
      final int MEDIA_TYPE_IMAGE = 100; 
      File pictureFile = new File(picPath); 

      if (pictureFile == null){ 
       Log.d(TAG, "Error creating media file, check storage permissions"); 
       return; 
      } 

      try { 
       FileOutputStream fos = new FileOutputStream(pictureFile); 
       fos.write(data); 
       fos.close(); 
      } catch (FileNotFoundException e) { 
       Log.d(TAG, "File not found: " + e.getMessage()); 
      } catch (IOException e) { 
       Log.d(TAG, "Error accessing file: " + e.getMessage()); 
      } 
     } 
    }; 

    public void onExitPressed(View v) { 
     onBackPressed(); 
    } 

    public void takePic(View v) { 
     Log.i("Adnan", "taking picture..."); 

     mCamera.takePicture(shutterCallback, null, mPicture); 

     v.startAnimation(AnimationUtils.loadAnimation(this, R.anim.popup)); 

     AlertDialog.Builder builder = new AlertDialog.Builder(this); 
     builder.setTitle("Please wait"); 
     builder.setView(getLayoutInflater().inflate(R.layout.progress_circular, null)); 
     builder.setCancelable(false); 
     diag = builder.create(); 
     diag.show(); 
    } 



    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // Hide the window title. 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

     setContentView(R.layout.pic_taker_carry); 

     // Create a RelativeLayout container that will hold a SurfaceView, 
     // and set it as the content of our activity. 
     mPreview = new Preview(this); 
     RelativeLayout carry = (RelativeLayout)findViewById(R.id.container); 

     mPreview.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 

     carry.addView(mPreview,0); 

     //setContentView(mPreview); 

     // Find the total number of cameras available 
     numberOfCameras = Camera.getNumberOfCameras(); 

     // Find the ID of the default camera 
     Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); 
     for (int i = 0; i < numberOfCameras; i++) { 
      Camera.getCameraInfo(i, cameraInfo); 
      if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { 
       defaultCameraId = i; 
      } 
     } 
    } 

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

     final PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     this.mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag"); 
     this.mWakeLock.acquire(); 

     // Open the default i.e. the first rear facing camera. 
     mCamera = Camera.open(); 
     cameraCurrentlyLocked = defaultCameraId; 
     mPreview.setCamera(mCamera); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 

     this.mWakeLock.release(); 

     // Because the Camera object is a shared resource, it's very 
     // important to release it when the activity is paused. 
     if (mCamera != null) { 
      mPreview.setCamera(null); 
      mCamera.release(); 
      mCamera = null; 
     } 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     return true; 
    } 
} 

Preview.java

package ...; 

import everything 

public class Preview extends ViewGroup implements SurfaceHolder.Callback { 
    private final String TAG = "Preview"; 

    SurfaceView mSurfaceView; 
    SurfaceHolder mHolder; 
    Size mPreviewSize; 
    List<Size> mSupportedPreviewSizes; 
    Camera mCamera; 

    public Preview(Context context) { 
     super(context); 

     mSurfaceView = new SurfaceView(context); 
     addView(mSurfaceView); 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = mSurfaceView.getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void setCamera(Camera camera) { 
     mCamera = camera; 
     if (mCamera != null) { 
      mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes(); 
      requestLayout(); 
     } 
    } 

    public void switchCamera(Camera camera) { 
     setCamera(camera); 
     try { 
      camera.setPreviewDisplay(mHolder); 
     } catch (IOException exception) { 
      Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
     } 
     Camera.Parameters parameters = camera.getParameters(); 
     parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
     requestLayout(); 

     camera.setParameters(parameters); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     // We purposely disregard child measurements because act as a 
     // wrapper to a SurfaceView that centers the camera preview instead 
     // of stretching it. 
     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 l, int t, int r, int b) { 
     if (changed && getChildCount() > 0) { 
      final View child = getChildAt(0); 

      final int width = r - l; 
      final int height = b - t; 

      int previewWidth = width; 
      int previewHeight = height; 
      if (mPreviewSize != null) { 
       previewWidth = mPreviewSize.width; 
       previewHeight = mPreviewSize.height; 
      } 

      // Center the child SurfaceView within the parent. 
      if (width * previewHeight > height * previewWidth) { 
       final int scaledChildWidth = previewWidth * height/previewHeight; 
       child.layout((width - scaledChildWidth)/2, 0, 
         (width + scaledChildWidth)/2, height); 
      } else { 
       final int scaledChildHeight = previewHeight * width/previewWidth; 
       child.layout(0, (height - scaledChildHeight)/2, 
         width, (height + scaledChildHeight)/2); 
      } 
     } 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, acquire the camera and tell it where 
     // to draw. 
     try { 
      if (mCamera != null) { 
       mCamera.setPreviewDisplay(holder); 
      } 
     } catch (IOException exception) { 
      Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // Surface will be destroyed when we return, so stop the preview. 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
     } 
    } 


    private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) { 
     final double ASPECT_TOLERANCE = 0.1; 
     double targetRatio = (double) w/h; 
     if (sizes == null) return null; 

     Size optimalSize = null; 
     double minDiff = Double.MAX_VALUE; 

     int targetHeight = h; 

     // Try to find an size match aspect ratio and size 
     for (Size size : sizes) { 
      double ratio = (double) size.width/size.height; 
      if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 
      if (Math.abs(size.height - targetHeight) < minDiff) { 
       optimalSize = size; 
       minDiff = Math.abs(size.height - targetHeight); 
      } 
     } 

     // Cannot find the one match the aspect ratio, ignore the requirement 
     if (optimalSize == null) { 
      minDiff = Double.MAX_VALUE; 
      for (Size size : sizes) { 
       if (Math.abs(size.height - targetHeight) < minDiff) { 
        optimalSize = size; 
        minDiff = Math.abs(size.height - targetHeight); 
       } 
      } 
     } 
     return optimalSize; 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // Now that the size is known, set up the camera parameters and begin 
     // the preview. 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 

     } 

     Camera.Parameters parameters = mCamera.getParameters(); 
     parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); 
     parameters.setPictureFormat(PixelFormat.JPEG); 
     parameters.setJpegQuality(80); 

     requestLayout(); 

     mCamera.setParameters(parameters); 
     mCamera.startPreview(); 
    } 

} 

一些相關的行logcat的:

01-20 17:13:56.544 22594-5071/? E/exynos_param﹕ exynos_param_string_get: Unable to get data for key recording-hint 
01-20 17:13:56.544 22594-5071/? E/exynos_param﹕ exynos_param_string_get: Unable to get data for key focus-areas 
01-20 17:13:56.574 22594-5973/? E/exynos_camera﹕ exynos_camera_capture_thread: Starting thread 
01-20 17:13:56.729 22594-22631/? E/exynos_camera﹕ Preview thread was already stopped! 
01-20 17:13:56.739 22594-25719/? E/exynos_param﹕ exynos_param_data_set: Mismatching types for key horizontal-view-angle 
01-20 17:13:56.744 22594-25719/? E/exynos_param﹕ exynos_param_string_get: Unable to get data for key recording-hint 
01-20 17:13:56.744 22594-25719/? E/exynos_param﹕ exynos_param_string_get: Unable to get data for key focus-areas 
01-20 17:13:56.744 22594-5974/? E/exynos_camera﹕ exynos_camera_preview_thread: Starting thread 
01-20 17:13:58.709 22594-5975/? E/exynos_camera﹕ exynos_camera_picture_thread: Starting thread 
01-20 17:13:58.804 22594-5973/? E/exynos_camera﹕ s5c73m3_interleaved_decode: Invalid jpeg start 
01-20 17:13:58.804 22594-5973/? E/exynos_camera﹕ exynos_camera_capture: Unable to decode S5C73M3 interleaved 
01-20 17:13:58.804 22594-5973/? E/exynos_camera﹕ exynos_camera_capture_thread: Unable to capture 
01-20 17:14:15.479 22594-5974/? E/exynos_camera﹕ exynos_camera_preview_thread: Exiting thread 
01-20 17:14:15.534 22594-5975/? E/exynos_camera﹕ exynos_camera_picture_thread: Exiting thread 
01-20 17:14:15.534 22594-5973/? E/exynos_camera﹕ exynos_camera_capture_thread: Exiting thread 

通知這一個:

01-20 17:13:58.804 22594-5973/? E/exynos_camera﹕ s5c73m3_interleaved_decode: Invalid jpeg start 

回答

3

i相的CyanogenMod 10.1和以上對銀河S3(I9300)同樣的問題。今天我找到了解決方案。我認爲這是AOPK代碼中的一個問題。

你必須確保在previewsize的寬高比和畫面SICE相等。

試試這個代碼來獲得一個picturesize沒有這個問題:

private Camera.Size getBestPictureSize(List<Camera.Size> pictureSizes, int maxWidth, Size previewSize) { 
    Comparator<Camera.Size> cmp = new Comparator<Camera.Size>() { 
     public int compare(Camera.Size size_1, Camera.Size size_2) { 
      return Integer.valueOf(size_1.width).compareTo(Integer.valueOf(size_2.width)); 
     } 
    }; 
    final double ASPECT_TOLERANCE = 0.1; 
    double targetAspect = (double)previewSize.width/(double)previewSize.height; 

    ArrayList<Camera.Size> matchedPictureSizes = new ArrayList<Camera.Size>(); 


    for(Size pictureSize : pictureSizes) { 
     double pictureAspect = (double)pictureSize.width/(double)pictureSize.height; 

     if(pictureSize.width <= maxWidth && Math.abs(targetAspect - pictureAspect) < ASPECT_TOLERANCE) { 
      matchedPictureSizes.add(pictureSize); 
     } 
    } 

    Camera.Size bestPictureSize; 
    if(!matchedPictureSizes.isEmpty()) { 
     bestPictureSize = Collections.max(matchedPictureSizes, cmp); 
    } else { 
     bestPictureSize = Collections.max(pictureSizes, cmp); 
    } 

    return bestPictureSize; 
} 

我希望這個代碼解決您的問題。

+0

我在CM 10.2中有同樣的問題,所以它可能不是一個錯誤,而是新的標準。一旦我將預覽設置爲正確的寬高比,我就可以拍照。 – Howler