2011-11-17 72 views
2

我找到了一些教程來使用相機。模擬器上沒有錯誤,但它在設備上崩潰,爲什麼?我只是創建簡單的代碼來預覽圖片。相機無法在Android設備上工作

我測試該設備是HTC野火的Android 2.2

Mainclass

private Camera camera; 
private boolean isPreviewRunning = false; 
private SimpleDateFormat timeStampFormat = new SimpleDateFormat("yyyyMMddHHmmssSS"); 

private SurfaceView surfaceView; 
private SurfaceHolder surfaceHolder; 

public void onCreate(Bundle icicle) 
{ 
    super.onCreate(icicle); 
    Log.e(getClass().getSimpleName(), "onCreate"); 
    getWindow().setFormat(PixelFormat.TRANSLUCENT); 
    setContentView(R.layout.main); 
    surfaceView = (SurfaceView)findViewById(R.id.surface); 
    surfaceHolder = surfaceView.getHolder(); 
    surfaceHolder.addCallback(this); 
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 


@Override 
protected void onRestoreInstanceState(Bundle savedInstanceState) 
{ 
    super.onRestoreInstanceState(savedInstanceState); 
} 

Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() 
{ 
    public void onPictureTaken(byte[] data, Camera c) 
    { 
     Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data); 
     camera.startPreview(); 
    } 
}; 

Camera.PictureCallback mPictureCallbackJpeg= new Camera.PictureCallback() 
{ 
    public void onPictureTaken(byte[] data, Camera c) 
    { 
     Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data); 
    } 
}; 

Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() 
{ 
    public void onShutter() 
    { 
     Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK"); 
    } 
}; 


public boolean onKeyDown(int keyCode, KeyEvent event) 
{ 
    ImageCaptureCallback iccb = null; 
    if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER) 
    { 
     try 
     { 
      String filename = timeStampFormat.format(new Date()); 
      ContentValues values = new ContentValues(); 
      values.put(Media.TITLE, filename); 
      values.put(Media.DESCRIPTION, "Image capture by camera"); 
      Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values); 
      //String filename = timeStampFormat.format(new Date()); 
      iccb = new ImageCaptureCallback(getContentResolver().openOutputStream(uri)); 
     } 
     catch(Exception ex) 
     { 
      ex.printStackTrace(); 
      Log.e(getClass().getSimpleName(), ex.getMessage(), ex); 
     } 
    } 

    if (keyCode == KeyEvent.KEYCODE_BACK) 
    { 
     return super.onKeyDown(keyCode, event); 
    } 

    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) 
    { 
     camera.takePicture(mShutterCallback, mPictureCallbackRaw, iccb); 
     return true; 
    } 

    return false; 
} 

protected void onResume() 
{ 
    Log.e(getClass().getSimpleName(), "onResume"); 
    super.onResume(); 
} 

protected void onSaveInstanceState(Bundle outState) 
{ 
    super.onSaveInstanceState(outState); 
} 

protected void onStop() 
{ 
    Log.e(getClass().getSimpleName(), "onStop"); 
    super.onStop(); 
} 

public void surfaceCreated(SurfaceHolder holder) 
{ 
    Log.e(getClass().getSimpleName(), "surfaceCreated"); 
    camera = Camera.open(); 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) 
{ 
    Log.e(getClass().getSimpleName(), "surfaceChanged"); 
    if (isPreviewRunning) 
    { 
     camera.stopPreview(); 
    } 

    Camera.Parameters p = camera.getParameters(); 
    p.setPreviewSize(w, h); 
    camera.setParameters(p); 

    try 
    { 
     camera.setPreviewDisplay(holder); 
    } 

    catch (IOException e) 
    { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    camera.startPreview(); 
    isPreviewRunning = true; 
} 

public void surfaceDestroyed(SurfaceHolder holder) 
{ 
    Log.e(getClass().getSimpleName(), "surfaceDestroyed"); 
    camera.stopPreview(); 
    isPreviewRunning = false; 
    camera.release(); 
} 

}

ImageCaptureCallBack

private OutputStream filoutputStream; 

public ImageCaptureCallback(OutputStream filoutputStream) 
{ 
    this.filoutputStream = filoutputStream; 
} 

@Override 
public void onPictureTaken(byte[] data, Camera camera) 
{ 
    try 
    { 
     Log.v(getClass().getSimpleName(), "onPictureTaken=" + data + " length = " + data.length); 
     filoutputStream.write(data); 
     filoutputStream.flush(); 
     filoutputStream.close(); 
    } 
    catch(Exception ex) 
    { 
     ex.printStackTrace(); 
    } 
} 

}

和清單

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
package="com.photo.test" 
android:versionCode="1" 
android:versionName="1.0" > 
<uses-sdk android:minSdkVersion="8" /> 
<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" /> 
<uses-permission android:name="android.permission.CAMERA" /> 
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
<application 
    android:icon="@drawable/ic_launcher" 
    android:label="@string/app_name" > 
    <activity 
     android:label="@string/app_name" 
     android:name=".Main" > 
     <intent-filter > 
      <action android:name="android.intent.action.MAIN" /> 
      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

+2

在那裏它會崩潰,附加logcat的輸出 –

+0

林整個上午並沒有什麼想,什麼是最簡單的例子代碼讓相機的預覽和設備上顯示呢? – goodm

+1

請附上logcat的詳細信息。 –

回答

5

相機預覽工作非常不同在不同設備上。我們在mixare增強現實引擎中遇到了很多問題。

首先,最好使用兼容性類來讓代碼在舊設備上工作。你可以在這裏看到的代碼:

https://github.com/mixare/mixare/blob/master/src/org/mixare/Compatibility.java

然後,你可以在這裏看到,這是你的責任,選擇由系統提供的預覽列表中正確的: https://github.com/mixare/mixare/blob/master/src/org/mixare/MixView.java在行871和持續。

  List<Camera.Size> supportedSizes = null; 
      //On older devices (<1.6) the following will fail 
      //the camera will work nevertheless 
      supportedSizes = Compatibility.getSupportedPreviewSizes(parameters); 

      //preview form factor 
      float ff = (float)w/h; 
      Log.d("Mixare", "Screen res: w:"+ w + " h:" + h + " aspect ratio:" + ff); 

      //holder for the best form factor and size 
      float bff = 0; 
      int bestw = 0; 
      int besth = 0; 
      Iterator<Camera.Size> itr = supportedSizes.iterator(); 

      //we look for the best preview size, it has to be the closest to the 
      //screen form factor, and be less wide than the screen itself 
      //the latter requirement is because the HTC Hero with update 2.1 will 
      //report camera preview sizes larger than the screen, and it will fail 
      //to initialize the camera 
      //other devices could work with previews larger than the screen though 
      while(itr.hasNext()) { 
       Camera.Size element = itr.next(); 
       //current form factor 
       float cff = (float)element.width/element.height; 
       //check if the current element is a candidate to replace the best match so far 
       //current form factor should be closer to the bff 
       //preview width should be less than screen width 
       //preview width should be more than current bestw 
       //this combination will ensure that the highest resolution will win 
       Log.d("Mixare", "Candidate camera element: w:"+ element.width + " h:" + element.height + " aspect ratio:" + cff); 
       if ((ff-cff <= ff-bff) && (element.width <= w) && (element.width >= bestw)) { 
        bff=cff; 
        bestw = element.width; 
        besth = element.height; 
       } 
      } 
      Log.d("Mixare", "Chosen camera element: w:"+ bestw + " h:" + besth + " aspect ratio:" + bff); 
      //Some Samsung phones will end up with bestw and besth = 0 because their minimum preview size is bigger then the screen size. 
      //In this case, we use the default values: 480x320 
      if ((bestw == 0) || (besth == 0)){ 
       Log.d("Mixare", "Using default camera parameters!"); 
       bestw = 480; 
       besth = 320; 
      } 
      parameters.setPreviewSize(bestw, besth); 

HTH 丹尼爾

+0

謝謝,我將在未來嘗試使用此,現在我可能只是使用:Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(cameraIntent,CAMERA_REQUEST); – goodm

相關問題