2015-02-23 37 views
1

以下文档来自developper.android.comAndroid使用低RAM设备拍照 - 可以使用setPictureSize()降低内存使用量吗?

我写了一个简短的Activity来从应用内拍照。

我有时会遇到这样的错误:

02-23 17:37:06.323: E/IMemory(5003): binder=0x3c010388 transaction failed fd=-2147483647, size=0, err=-2147483646 (Unknown error: 2147483646) 
02-23 17:37:06.328: E/IMemory(5003): cannot dup fd=-2147483647, size=0, err=-2147483646 (Bad file number) 
02-23 17:37:06.328: E/IMemory(5003): cannot map BpMemoryHeap (binder=0x3c010388), size=0, fd=-1 (Bad file number) 
  • 你能帮助我理解它?

  • 是否将图片大小设置为从getPictureSizes()方法检索到的最小值在捕获时需要更少的内存还是稍后再应用?

的信息,这是我的activitity(只是从这个page代码示例的串联)。在该代码之前,我使用了一个带有预览和takePicture的非常简单的代码。

public class CatchImage extends Activity { 
private boolean fgDebugLocal = true; 
private String tagLocal = "CatchImage ";  

private Button btTake, btRetour; 
private Intent intent; 
private String refPhoto; 


private String strPath = ""; 
private String strFileName = ""; 

private Context context; 

private CameraPreview mPreview; 
private FrameLayout preview; 
private Camera cameraCatchImage; 

/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState){ 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    context = getApplicationContext(); 
    /** 
    * Set full screen 
    * Used in Landscape 
    */ 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
    Baseline.tepvLogger.stat(tagLocal, "init "); 

    setContentView(R.layout.camera); 

    /** 
    * get the id of picture 
    */ 
    intent = getIntent(); 
    refPhoto = intent.getStringExtra("refPhoto"); 
    strPath = intent.getStringExtra("strSdInternalPath"); 
    StringBuilder sb = new StringBuilder(); 
    sb.append(strPath); 
    sb.append(File.separatorChar); 
    sb.append(Params.PATH_REP_PHOTO); 
    sb.append(File.separatorChar); 
    sb.append(Params.PHOTO_FILE_NAME); 
    sb.append(refPhoto); 
    sb.append(Params.PHOTO_FILE_EXT_JPG); 
    strFileName = sb.toString(); 

    if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "strFileName = " + strFileName);}; 

    btTake = (Button) findViewById(R.id.btStatCatchPictureTake); 
    btRetour = (Button) findViewById(R.id.btStatCatchPictureRetour); 

    btTake.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "btTake");}; 
      mPreview.mCamera.takePicture(shutterCallback, rawCallback, jpegCallback); 
     } 
    }); 


    btRetour.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "btRetour ");}; 

      Intent intent = new Intent(CatchImage.this, StationnementPhoto.class); 
      startActivity(intent); 
      finish(); 

     } 
    }); 

} 

@Override 
public void onResume() { 
    super.onResume(); 
    if (!checkCameraHardware(context)) { 
     afficheAlertDlg(getResources().getString(R.string.dlg_titre_alert), getResources().getString(R.string.catch_image_no_camera), getResources().getDrawable(R.drawable.ic_alert)); 
    } else { 
     if (Camera.getNumberOfCameras()>1) { 
      new TePVException(this.getClass().getName(), "checkCameraHardware", "More than one camera detected"); 
     } 

     if (safeCameraOpen(0)) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "safeCameraOpen(0) true : creating preview");}; 
      btTake.setEnabled(true); 
      btTake.setBackgroundResource(R.drawable.bt_border_selector); 

      mPreview = new CameraPreview(context, cameraCatchImage); 
      preview = (FrameLayout) findViewById(R.id.flStatCatchPreview); 
      preview.addView(mPreview); 

     } else { 
      btTake.setEnabled(false); 
      btTake.setBackgroundResource(R.drawable.bt_border_disable); 
     } 
    } 


} 

@Override 
public void onPause() { 
    super.onPause(); 
    releaseCameraAndPreview();    // release the camera immediately on pause event 
} 

private boolean safeCameraOpen(int id) { 
    boolean qOpened = false; 

    try { 
     releaseCameraAndPreview(); 
     cameraCatchImage = Camera.open(id); 
     qOpened = (cameraCatchImage != null); 
    } catch (Exception e) { 
     if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "failed to open Camera");}; 
     e.printStackTrace(); 
    } 

    return qOpened;  
} 

private void releaseCameraAndPreview() { 
    if (mPreview!=null) mPreview.setCamera(null); 
    if (cameraCatchImage != null) { 
     cameraCatchImage.release(); 
     cameraCatchImage = null; 
    } 
} 

/** Check if this device has a camera */ 
private boolean checkCameraHardware(Context context) { 
    if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ 
     // this device has a camera 
     return true; 
    } else { 
     // no camera on this device 
     return false; 
    } 
} 


ShutterCallback shutterCallback = new ShutterCallback() { 
    public void onShutter() { 
     if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "shutterCallback ");}; 
    } 
}; 

/** Handles data for raw picture */ 
PictureCallback rawCallback = new PictureCallback() { 
    public void onPictureTaken(byte[] data, Camera camera) { 
     if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "rawCallback ");}; 
    } 
}; 

private PictureCallback jpegCallback = new PictureCallback() { 

    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "jpegCallback ");}; 
     FileOutputStream outStream = null; 
     try { 
      //String strFileNameComplet = strPath + File.separatorChar + strFileName + refPhoto + Params.PHOTO_FILE_EXT_JPG; 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "strFileName = " + strFileName);}; 
      outStream = new FileOutputStream(strFileName); 
      outStream.write(data); 
      outStream.close(); 

      File fileVerif = new File(strFileName); 
      if (fileVerif.exists()){ 
       if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "Photo stockée ");}; 
       Intent intent = new Intent(CatchImage.this, StationnementPhoto.class); 
       startActivity(intent); 
       finish(); 
      }else { 
       new TePVException("CatchImage", "PictureCallback", "Pb stockage image = " + strFileName); 
       Toast.makeText(context, "Erreur enregistrement de la photo, essayez à nouveau", Toast.LENGTH_LONG).show(); 
      } 
     } catch (FileNotFoundException e) { 
      new TePVException("CatchImage", "PictureCallback", "FileNotFoundException = " + e.getMessage()); 
     } catch (IOException e) { 
      new TePVException("CatchImage", "PictureCallback", "IOException = " + e.getMessage()); 
     } finally { 

     } 
    } 
}; 

/** A basic Camera preview class */ 
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 

    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 

     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void setCamera(Camera object) { 
     mCamera = object; 
    } 

    public Camera getCamera() { 
     return mCamera; 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, now tell the camera where to draw the preview. 
     try { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.d(tagLocal, "Error setting camera preview: " + e.getMessage());} 
     } 
    } 

    public void surfaceDestroyed(SurfaceHolder holder) { 
     // empty. Take care of releasing the Camera preview in your activity. 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 

     if (mHolder.getSurface() == null){ 
      // preview surface does not exist 
      return; 
     } 

     // stop preview before making changes 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e){ 
      // ignore: tried to stop a non-existent preview 
     } 

     // set preview size and make any resize, rotate or 
     // reformatting changes here 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.startPreview(); 

     } catch (Exception e){ 
      if (Params.tagFgDebug && fgDebugLocal){Log.d(tagLocal, "Error starting camera preview: " + e.getMessage());} 
     } 
    } 
} 

编辑:我看到this question但我已经将图像保存为文件。

回答

0

我找到了一个解决方案:

我们停止使用Camera camera.takePicture()并且只使用预览对象。基于@CommonsWare代码的照片显示的理念和基于斑马线的精明解决方案。

想法:

btTake.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(Params.tagGen, tagLocal + "btTake");}; 
      if (inPreview) { 
       camera.setOneShotPreviewCallback(previewCallback); 
       inPreview=false; 
      } 
     } 
}); 

预览代码:

final class PreviewCallback implements Camera.PreviewCallback { 

    @Override 
    public void onPreviewFrame(byte[] data, Camera camera) { 
     Log.i(tagLocal , "onPreviewFrame "); 
     File photo= new File(strFileName); 

     if (photo.exists()) { 
      photo.delete(); 
     } 


     try { 
      Camera.Parameters parameters = camera.getParameters(); 
      Size size = parameters.getPreviewSize(); 
      YuvImage image = new YuvImage(data, parameters.getPreviewFormat(), 
        size.width, size.height, null); 
      FileOutputStream filecon = new FileOutputStream(photo); 
      image.compressToJpeg(new Rect(0, 0, image.getWidth(), image.getHeight()), 90, filecon); 
     } catch (FileNotFoundException e) { 
      Toast.makeText(getBaseContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 
     } 


     /** 
     * Restart : 
     */ 
     File fileVerif = new File(strFileName); 
     if (fileVerif.exists() && fileVerif.length()!=0) { 
      if (Params.tagFgDebug && fgDebugLocal){Log.i(tagLocal , "Photo stockée file lenght = "+ fileVerif.length());}; 
      Intent intent = new Intent(CatchImageCommonsWare.this, Photo.class); 
      startActivity(intent); 
      finish(); 
     } else { 
      new Exception("CatchImageCommonsWare", "PreviewCallback", "Pb stockage image = " + strFileName); 
      Toast.makeText(context, "Erreur enregistrement de la photo, essayez à nouveau", Toast.LENGTH_LONG).show(); 
     } 

    } 

}