I'm a student and I am developing on Android 2.2 for a project. For my tests and app executions, I am using an HTC Desire HD (with Android 2.2).
I just want to create a composant (class) to take a picture with the mobile device. I have an Android class, which I use for the getOptimalPreviewSize() method (this method is in the ApiDemos 2.2). This method is used to fix this type of error :
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): java.lang.RuntimeException: Fail to connect to camera service
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.hardware.Camera.native_setup(Native Method)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.hardware.Camera.<init>(Camera.java:118)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.hardware.Camera.open(Camera.java:91)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at com.example.android.apis.graphics.Preview.surfaceCreated(CameraPreview.java:69)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.SurfaceView.updateWindow(SurfaceView.java:540)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.SurfaceView.dispatchDraw(SurfaceView.java:339)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewGroup.drawChild(ViewGroup.java:1660)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1389)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.View.draw(View.java:6764)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.widget.FrameLayout.draw(FrameLayout.java:352)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewGroup.drawChild(ViewGroup.java:1662)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1389)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.View.draw(View.java:6764)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.widget.FrameLayout.draw(FrameLayout.java:352)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1887)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewRoot.draw(ViewRoot.java:1422)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewRoot.performTraversals(ViewRoot.java:1167)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.view.ViewRoot.handleMessage(ViewRoot.java:1744)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.os.Handler.dispatchMessage(Handler.java:99)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.os.Looper.loop(Looper.java:143)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at android.app.ActivityThread.main(ActivityThread.java:5068)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at java.lang.reflect.Method.invokeNative(Native Method)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at java.lang.reflect.Method.invoke(Method.java:521)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
02-14 21:38:05.818: ERROR/AndroidRuntime(2884): at dalvik.system.NativeStart.main(Native Method)
So, I fixed this problem with this code :
public class CameraView extends Activity implements SurfaceHolder.Callback {
private SurfaceView mSurfaceView = null;
private SurfaceHolder mSurfaceHolder = null;
private Camera mCamera = null;
private boolean mPreviewRunning = false;
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.camera_surface);
mSurfaceView = (SurfaceView) findViewById(R.id.surface_camera);
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
if (!(android.os.Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED)))
{
Toast
.makeText(CameraView.this, R.string.msgNoSdCard, Toast.LENGTH_LONG)
.show();
}
else
{
Toast
.makeText(CameraView.this, R.string.msgPressBackBt,开发者_开发问答 Toast.LENGTH_LONG)
.show();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCamera = Camera.open();
try {
mCamera.setPreviewDisplay(holder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
// TODO: add more exception handling logic here
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mCamera.stopPreview();
mPreviewRunning = false;
mCamera.release();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//Handle the back button
if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) || (keyCode == KeyEvent.KEYCODE_CAMERA)){
mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
return true;
}
else {
return super.onKeyDown(keyCode, event);
}
}
ShutterCallback shutterCallback = new ShutterCallback() {
public void onShutter() {
}
};
/** Handles data for raw picture */
PictureCallback rawCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
}
};
/** Handles data for jpeg picture */
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
FileOutputStream outStream = null;
try {
// write to local sandbox file system
//outStream =
//CameraView.this.openFileOutput(String.format("%d.jpg",
//System.currentTimeMillis()), 0);
// Or write to sdcard
long fileName = System.currentTimeMillis();
outStream = new FileOutputStream(String.format(
"/sdcard/%d.jpg", fileName));
outStream.write(data);
outStream.close();
Intent resultIntent = new Intent();
String imageFileName = String.format("/sdcard/%d.jpg", fileName);
resultIntent.putExtra("MyAvatar", imageFileName);
setResult(Activity.RESULT_OK, resultIntent);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
}
}
};
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.05;
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;
}
@Override
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.
Camera.Parameters parameters = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
The final problem is : if the device is displaying the Camera View, the device is totally disoriented. If I point the camera to the top of a room (the scene which is filmed), the screen goes to the left, if I put the Camera to the ground, the screen goes the right. There is the same problem with landscape screen with wrong height and width and Camera Orientation.
Is there a solution to fix this problem of Camera API with the HTC Desire HD ?
Thanks,
Related links :
Android 2.2 SDK - setParameters failed for Camera API on Nexus One
http://code.google.com/p/android/issues/detail?id=7909
The problem isn't to do with your phone but rather the parameters you're setting for the camera resolution. I had a similar issue when learning to use the camera on a Nexus One. You need to get a list of known resolutions which works on the phone the code is working on and set it to one of those.
Are you sure get parameters doesn't work? can you post the code which didn't work? perhaps you're doing it wrong.
Ok, problem resolved with this code :
@Override
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.
Camera.Parameters parameters = mCamera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size optimalSize = getOptimalPreviewSize(sizes, w, h);
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
mCamera.setDisplayOrientation(90);
parameters.setRotation(90);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
Okay, I Discover another simple solution :
In Android Manifest, add to camera activity this property :
android:screenOrientation="landscape"
And, in Camera App for surfaceChanged :
just this :
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = mCamera.getParameters();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
Regards.
精彩评论