我正在开发相机应用程序。我写了一些代码来显示预览,但它不起作用。没有错误,但屏幕始终是黑色的。我想我错过了什么。这是代码。
预览
public class Preview extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = "com.azeem.Debug";
private Context context;
private SurfaceView mSurfaceView;
public Camera mCamera;
private static final Camera.CameraInfo mCameraInfo = new Camera.CameraInfo();
private Display mDisplay;
private List<Camera.Size> mSupportedPreviewSizes;
Camera.Size mPreviewSize;
private static final int NO_CAMERA = -1;
private boolean mIsFrontCamera = false;
private boolean mIsFlashOn = false;
private int mFrontCameraId, mBackCameraId;
public Preview(Context ctx) {
super(ctx);
context = ctx;
Log.i(TAG, "First Constructor");
init();
}
public Preview(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
context = ctx;
Log.i(TAG, "Second Constructor");
init();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "surfaceCreated");
this.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.i(TAG, "surfaceChanged");
if(mPreviewSize != null) {
Log.i(TAG, "Activate Optimal Preview");
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "surfaceDestroyed");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i(TAG, "onMeasure");
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) {
Log.i(TAG, "onLayout");
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "onTouchEvent");
return super.onTouchEvent(event);
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.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);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
private void init(){
Log.i(TAG, "init");
if(hasCamera()) {
final SurfaceHolder surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
mBackCameraId = findCameraId(false);
if(hasFrontCamera()){
mFrontCameraId = findCameraId(true);
}else{
mFrontCameraId = NO_CAMERA; // Front Face Camera Not found on device
}
final WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
mDisplay = windowManager.getDefaultDisplay();
} // Else Camera not found on device
}
public void setCamera(){
Log.i(TAG, "setCamera");
//if(mSurfaceView != null && hasCamera()){
if(hasCamera()){
mCamera = Camera.open(mBackCameraId);
}
}
public void start(){
Log.i(TAG, "start");
if(mCamera != null){
try {
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
//mCamera.setPreviewDisplay(mSurfaceView.getHolder());
mCamera.setPreviewDisplay(this.getHolder());
mCamera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void stop(){
Log.i(TAG, "stop");
if(mCamera != null){
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
private boolean hasCamera() {
final PackageManager packageManager = context.getPackageManager();
return packageManager != null
&& packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}
private boolean hasFrontCamera() {
final PackageManager packageManager = context.getPackageManager();
return packageManager != null
&& packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
}
private int findCameraId(boolean front) {
final int cameraCount = Camera.getNumberOfCameras();
for (int i = 0; i < cameraCount; i++) {
Camera.getCameraInfo(i, mCameraInfo);
if ((front && mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
|| (!front && mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK)) {
return i;
}
}
return NO_CAMERA;
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
preview = new Preview(this);
capturePicture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
preview.mCamera.takePicture(null, null, jpegCallback);
}
});
}
@Override
protected void onResume() {
super.onResume();
preview.setCamera();
preview.start();
}
@Override
protected void onPause() {
super.onPause();
preview.stop();
}
// Other Code....
}
activity_main.xml中
<com.azeem.mycamera.Preview
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Other Codes Buttons etc -->
这是我正在使用的代码,但预览没有显示。你能不能让我知道我错过了什么。
更新
还有清单文件,我提到所有必需的uses-premissions
预览在我setCamera
课程内preview
时工作,但是当我从MainActivity
设置时,它无法正常工作。
这是有效的代码。 预览课程
// other code
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "surfaceCreated");
this.setCamera();
this.start();
}
// other code
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
}
// Other Code....
这是有效的,但是当我从MainActivity
进行设置时我无法正常工作,因为我在更新之前显示代码有什么问题我不能告诉我。
答案 0 :(得分:0)
您是否已在Android Manifest中声明了权限,并且还检查了使用Android最新版本的运行时权限。
答案 1 :(得分:0)
在创建曲面之前,无法开始预览。因此,在您的工作代码中使用onSurfaceCreated启动相机似乎是有意义的。如果你真的想在onResume中强制执行此行为,那么你可能做的最好的事情就是保持两个标志:resumed和surfaceCreated。
这样的东西(注意:psuedocode)......
onResume(... ){
resumed = true;
if (surfaceCreated){
startCam();
}
}
onSurfaceCreated(){
surfaceCreated = true;
if (resumed){
startCam();
}
}
onPause(){
resumed = false;
}
onSurfaceDestroyed(){
surfaceCreated = false;
}
这将确保在设置相机时满足您的所有条件。