我正在尝试从Android相机读取焦距(照片中的主体距离)。即使正确自动对焦,我的HTC Desire上的所有焦距仍然保持为0。这是整个应用程序,仅适用于v2.3.3及更高版本。
ImageCapture.java
package test.test;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import android.app.Activity;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PictureCallback;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
//THIS CLASS READS THE FOCUS DISTANCES
class ImageFocusCallback implements AutoFocusCallback {
@Override
public void onAutoFocus(boolean success, Camera camera) {
//READ FOCUS DISTANCES HERE
Camera.Parameters parameters = camera.getParameters();
float[] distances = new float[3];
if (success) {
// Only available with Android 9 (2.3)
// Focus Mode is always reported as auto but
// distances do not appear to be updating
// always: 0.1, 1.2, Infinity, (on my device it's 0,0,0)
Log.d("Focus Mode: ", parameters.getFocusMode());
parameters.getFocusDistances(distances);
Log.d("focus distance near", Float.toString(distances[0]));
Log.d("focus distance optimum", Float.toString(distances[1]));
Log.d("focus distance far", Float.toString(distances[2]));
}
}
}
public class ImageCapture extends Activity implements SurfaceHolder.Callback {
//CALL AUTO FOCUS HERE
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
ImageFocusCallback autoFocusCallBack = new ImageFocusCallback();
//AUTOFOCUS IS CALLED HERE
camera.autoFocus(autoFocusCallBack);
return true;
}
return false;
}
//REST OF THE CODE
private Camera camera;
private boolean isPreviewRunning = false;
private SimpleDateFormat timeStampFormat = new SimpleDateFormat("yyyyMMddHHmmssSS");
private SurfaceView surfaceView;
private SurfaceHolder surfaceHolder;
private Uri target = Media.EXTERNAL_CONTENT_URI;
@Override
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
public boolean onCreateOptionsMenu(android.view.Menu menu) {
MenuItem item = menu.add(0, 0, 0, "goto gallery");
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(Intent.ACTION_VIEW, target);
startActivity(intent);
return true;
}
});
return true;
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
Camera.PictureCallback mPictureCallbackRaw = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera c) {
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK RAW: " + data);
camera.startPreview();
}
};
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera c) {
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
}
};
Camera.ShutterCallback mShutterCallback = new Camera.ShutterCallback() {
@Override
public void onShutter() {
Log.e(getClass().getSimpleName(), "SHUTTER CALLBACK");
}
};
// 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;
// }
@Override
protected void onResume() {
Log.e(getClass().getSimpleName(), "onResume");
super.onResume();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
@Override
protected void onStop() {
Log.e(getClass().getSimpleName(), "onStop");
super.onStop();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e(getClass().getSimpleName(), "surfaceCreated");
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
float[] distances = new float[3];
Log.d("Focus Mode: ", parameters.getFocusMode());
parameters.getFocusDistances(distances);
Log.d("focus distance 0", Float.toString(distances[0]));
Log.d("focus distance 1", Float.toString(distances[1]));
Log.d("focus distance 2", Float.toString(distances[2]));
}
@Override
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;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e(getClass().getSimpleName(), "surfaceDestroyed");
camera.stopPreview();
isPreviewRunning = false;
camera.release();
}
}
class ImageCaptureCallback implements PictureCallback {
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();
}
}
}
}
main.xml中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<SurfaceView android:id="@+id/surface"
android:layout_width="fill_parent"
android:layout_height="10dip"
android:layout_weight="1">
</SurfaceView>
</LinearLayout>
的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="10" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ImageCapture"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
设备驱动程序中是否存在错误?在Android源码中,Camera.java调用native_autoFocus()和native_getParameters()来读取距离。有谁知道从哪里获得本地电话的来源?
答案 0 :(得分:2)
在Froyo中,frameworks / base / core / jni / android_hardware_Camera.cpp通过调用android_hardware_Camera_autoFocus()来实现native_autoFocus(),它似乎在运行时绑定到设备/供应商特定的代码。
不幸的是,“如果相机不支持自动对焦并且调用了自动对焦,则会立即调用onAutoFocus,并将伪成功值设置为true。”是documented behavior。
我很好奇您使用的哪些功能需要2.3.3,API级别10。
答案 1 :(得分:0)
可能是相机驱动程序中的一个错误,如果你再次设置手机,你只能解决这个问题,是的,我知道这真的很糟糕,但我也遇到了同样的问题。
但我选择为我的设备使用自定义ROM。我正在使用Android Revolution HD 6.1.1 http://forum.xda-developers.com/showthread.php?t=840040
对于您的问题,您可以从使用rom下载的软件包中取出相机应用程序的源文件。可能如果你改变它,它将起作用。
最好的问候
答案 2 :(得分:0)
我不知道在哪里可以获得原生呼叫的来源。但是如果在getFocusDistances(float [])方法中获得所有焦距的0,则可以阅读this issue。在那里你可以看到这个错误不是设备的错误,而是Android SDK的错误。
答案 3 :(得分:0)
这是错误14341 - &#34;在不考虑实际焦距的情况下,Camera.Parameters.getFocusDistances()返回的距离在Nexus S上不会改变。
首次报告于2011年1月26日,上次报告于2014年3月18日发布。因此,Bug在您遇到它之前不久就已报告,并且至今尚未确定。它会针对您的设备进行专门报告。
报告中的各种评论声称此Bug会影响&#34; Nexus S&#34;,&#34; HTC Sensation&#34;,&#34; Galaxy S Plus&#34;,&#34; Galaxy S II&#34;,&#34; HTC Desire HD &#34;,&#34; Galaxy Nexus&#34;,&#34; Xperia Mini ST15i&#34;,&#34; Nexus 5&#34;,&#34; Galaxy R&#34;和&#34; Galaxy Note II&#34 ;;一篇评论声称它在&#34; Galaxy Nexus&#34;。
上完美运行参考:https://code.google.com/p/android/issues/detail?id=14341。