0

我试图通过代码调用camera.takepicture,它总是抛出一个运行时异常。我似乎无法在我的代码中找到错误。如果我使用按钮调用相同的东西,则拍照效果很好。我需要通过代码调用 takepicture,因为当用户实际执行不同的活动时,我需要它来随机拍摄照片。我需要设置一个计时器/间隔来查看正在拍摄的这些照片。我不能依赖程序的这一部分中的用户交互。

这是有关更多详细信息的代码。还附上了logcat。

CameraActivity.class

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class CameraActivity extends Activity implements Callback {

final static String DEBUG_TAG = "CameraActivity";
final static String TAG = "CameraActivity";
Camera camera;
private int cameraId = 0;
Button photo;
PhotoHandler mPhotoHandler = null;

Camera.Parameters parameters;
private SurfaceHolder sHolder;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // do we have a camera?
    if (!getPackageManager()
            .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
                .show();
    } else {
        cameraId = findFrontFacingCamera();
        if (cameraId < 0) {
            Toast.makeText(this, "No front facing camera found.",
                    Toast.LENGTH_LONG).show();
        } else {
            camera = Camera.open(cameraId);
            SurfaceView sv = new SurfaceView(getApplicationContext());
            setContentView(R.layout.camera);
            sv = (SurfaceView) findViewById(R.id.surfaceview);
            photo = (Button) findViewById(R.id.takepicture);
            photo.setText("Click a photo!!");
            // Get a surface
            sHolder = sv.getHolder();
            sHolder.addCallback(this);
            sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            try {
                camera.setPreviewDisplay(sHolder);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            parameters = camera.getParameters();
            // set camera parameters
            camera.setParameters(parameters);
            camera.startPreview();
            camera.setDisplayOrientation(90);
            try {

                photo.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View arg0) {
                        // TODO Auto-generated method stub
                        // Toast.makeText(getApplicationContext(),
                        // "photo clicked!",
                        // Toast.LENGTH_SHORT).show();

                        // just calling the function which captures the
                        // photo
                        takePhoto();
                    }
                });
                photo.performClick();

                // finish();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    try {
        camera.setPreviewDisplay(holder);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // set any cam params you need...
    camera.startPreview();
}

private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
        CameraInfo info = new CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
            Log.d(DEBUG_TAG, "CameraActivity found");
            cameraId = i;
            break;
        }
    }
    return cameraId;
}

@Override
protected void onPause() {
    if (camera != null) {
        camera.release();
        camera = null;
    }
    super.onPause();
}

Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {

    @Override
    public void onShutter() {
        // TODO Auto-generated method stub
        Log.d(TAG, "onShutter'd");
    }
};

Camera.PictureCallback rawpicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {
        // TODO Auto-generated method stub
        Log.d(TAG, "onPictureTaken - raw");
    }

};

Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera arg1) {
        // TODO Auto-generated method stub
        File pictureFileDir = getDir();

        if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

            Log.d(CameraActivity.DEBUG_TAG,
                    "Can't create directory to save image.");
            Toast.makeText(CameraActivity.this,
                    "Can't create directory to save image.",
                    Toast.LENGTH_LONG).show();
            return;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_" + date + ".jpg";

        String filename = pictureFileDir.getPath() + File.separator
                + photoFile;

        File pictureFile = new File(filename);

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
            Toast.makeText(CameraActivity.this,
                    "New Image saved:" + photoFile, Toast.LENGTH_LONG)
                    .show();
        } catch (Exception error) {
            Log.d(CameraActivity.DEBUG_TAG, "File" + filename
                    + "not saved: " + error.getMessage());
            Toast.makeText(CameraActivity.this,
                    "Image could not be saved.", Toast.LENGTH_LONG).show();
        }
    }

};

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // set any cam params you need...
    camera.startPreview();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera.stopPreview();
    camera.release();

}

private static File getDir() {
    File sdDir = Environment
            .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return new File(sdDir, "CameraAPIDemo");
}

public void takePhoto() {

    camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}

}

附上logcat的输出

*

> 04-17 00:41:03.264: D/CameraActivity(19076): CameraActivity found
> 04-17 00:41:03.444: D/Camera(19076): app passed NULL surface 04-17
> 00:41:03.474: W/System.err(19076): java.lang.RuntimeException:
> takePicture failed 04-17 00:41:03.474: W/System.err(19076):   at
> android.hardware.Camera.native_takePicture(Native Method) 04-17
> 00:41:03.474: W/System.err(19076):    at
> android.hardware.Camera.takePicture(Camera.java:1095) 04-17
> 00:41:03.474: W/System.err(19076):    at
> android.hardware.Camera.takePicture(Camera.java:1040) 04-17
> 00:41:03.474: W/System.err(19076):    at
> com.egnoita.ignoramus.CameraActivity.takePhoto(CameraActivity.java:226)
> 04-17 00:41:03.474: W/System.err(19076):  at
> com.egnoita.ignoramus.CameraActivity$4.onClick(CameraActivity.java:93)
> 04-17 00:41:03.474: W/System.err(19076):  at
> android.view.View.performClick(View.java:4204) 04-17 00:41:03.484:
> W/System.err(19076):  at
> com.egnoita.ignoramus.CameraActivity.onCreate(CameraActivity.java:96)
> 04-17 00:41:03.484: W/System.err(19076):  at
> android.app.Activity.performCreate(Activity.java:5104) 04-17
> 00:41:03.484: W/System.err(19076):    at
> android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
> 04-17 00:41:03.484: W/System.err(19076):  at
> android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
> 04-17 00:41:03.484: W/System.err(19076):  at
> android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
> 04-17 00:41:03.484: W/System.err(19076):  at
> android.app.ActivityThread.access$600(ActivityThread.java:141) 04-17
> 00:41:03.484: W/System.err(19076):    at
> android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
> 04-17 00:41:03.484: W/System.err(19076):  at
> android.os.Handler.dispatchMessage(Handler.java:99) 04-17
> 00:41:03.484: W/System.err(19076):    at
> android.os.Looper.loop(Looper.java:137) 04-17 00:41:03.484:
> W/System.err(19076):  at
> android.app.ActivityThread.main(ActivityThread.java:5041) 04-17
> 00:41:03.484: W/System.err(19076):    at
> java.lang.reflect.Method.invokeNative(Native Method) 04-17
> 00:41:03.484: W/System.err(19076):    at
> java.lang.reflect.Method.invoke(Method.java:511) 04-17 00:41:03.484:
> W/System.err(19076):  at
> com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
> 04-17 00:41:03.484: W/System.err(19076):  at
> com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 04-17
> 00:41:03.484: W/System.err(19076):    at
> dalvik.system.NativeStart.main(Native Method) 04-17 00:41:03.534:
> D/libEGL(19076): loaded /system/lib/egl/libEGL_adreno200.so 04-17
> 00:41:03.534: D/libEGL(19076): loaded
> /system/lib/egl/libGLESv1_CM_adreno200.so 04-17 00:41:03.544:
> D/libEGL(19076): loaded /system/lib/egl/libGLESv2_adreno200.so 04-17
> 00:41:03.554: I/Adreno200-EGL(19076): <eglInitialize:269>: EGL 1.4
> QUALCOMM build: Nondeterministic
> AU_full_mako_PARTNER-ANDROID/JB-MR1-DEV_CL2961380_release_AU
> (CL2961380) 04-17 00:41:03.554: I/Adreno200-EGL(19076): Build Date:
> 12/10/12 Mon 04-17 00:41:03.554: I/Adreno200-EGL(19076): Local Branch:
> 04-17 00:41:03.554: I/Adreno200-EGL(19076): Remote Branch:
> m/partner-android/jb-mr1-dev 04-17 00:41:03.554:
> I/Adreno200-EGL(19076): Local Patches: NONE 04-17 00:41:03.554:
> I/Adreno200-EGL(19076): Reconstruct Branch: NOTHING 04-17
> 00:41:03.624: D/OpenGLRenderer(19076): Enabling debug mode 0

* 如果您需要更多信息,请告诉我。所有权限和功能都添加到清单中

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_DATA" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
4

2 回答 2

1

我遇到了同样的问题,为了解决这个问题,我简单地将 takephoto 定义为静态,将回调定义为静态。完成此操作后,我可以通过代码调用 takephoto。

例如:

public static void takePhoto() {

    camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}

static Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera arg1) {
        // TODO Auto-generated method stub
        File pictureFileDir = getDir();

        if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

            Log.d(CameraActivity.DEBUG_TAG,
                    "Can't create directory to save image.");
            Toast.makeText(CameraActivity.this,
                    "Can't create directory to save image.",
                    Toast.LENGTH_LONG).show();
            return;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_" + date + ".jpg";

        String filename = pictureFileDir.getPath() + File.separator
                + photoFile;

        File pictureFile = new File(filename);

        try {
             FileOutputStream fos = new FileOutputStream(pictureFile);
             fos.write(data);
             fos.close();
             Toast.makeText(CameraActivity.this,
                    "New Image saved:" + photoFile, Toast.LENGTH_LONG)
                     .show();
        } catch (Exception error) {
            Log.d(CameraActivity.DEBUG_TAG, "File" + filename
                    + "not saved: " + error.getMessage());
            Toast.makeText(CameraActivity.this,
                    "Image could not be saved.", Toast.LENGTH_LONG).show();
        }
    }

};

static Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {

    @Override
    public void onShutter() {
        // TODO Auto-generated method stub
        Log.d(TAG, "onShutter'd");
    }
};

static Camera.PictureCallback rawpicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {
        // TODO Auto-generated method stub
        Log.d(TAG, "onPictureTaken - raw");
    }

};

我希望这可以帮助您或其他有同样问题的人。

于 2013-12-31T11:11:55.087 回答
0

你不需要四处走动,所以它takePhoto()是从 onClick() 调用的。您的编程方法失败的原因是camera.takePicture( )只能在camera.startPreview()完成 调用。这恰好是对 Android 相机生命周期的常见误解。

底线是onCreate(),您应该让活动准备好拍照,并让所有必要的回调按顺序调用。这是您的代码的最小重写。我希望它不仅可以完成工作,还可以帮助您了解正确对待相机的方法。

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.Size;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnClickListener;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public class CameraActivity extends Activity implements Callback {

final static String DEBUG_TAG = "CameraActivity";
final static String TAG = "CameraActivity";
Camera camera;
private int cameraId = 0;
Button photo;
PhotoHandler mPhotoHandler = null;
private boolean wantPhoto = false;

Camera.Parameters parameters;
private SurfaceHolder sHolder;

@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // do we have a camera?
    if (!getPackageManager()
            .hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
        Toast.makeText(this, "No camera on this device", Toast.LENGTH_LONG)
                .show();
    } else {
        cameraId = findFrontFacingCamera();
        if (cameraId < 0) {
            Toast.makeText(this, "No front facing camera found.",
                    Toast.LENGTH_LONG).show();
        } else {
            camera = Camera.open(cameraId);
            SurfaceView sv = new SurfaceView(getApplicationContext());
            setContentView(R.layout.camera);
            sv = (SurfaceView) findViewById(R.id.surfaceview);
            photo = (Button) findViewById(R.id.takepicture);
            photo.setText("Click a photo!!");
            // Get a surface
            sHolder = sv.getHolder();
            sHolder.addCallback(this);
            sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            try {
                camera.setPreviewDisplay(sHolder);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            parameters = camera.getParameters();
            // set camera parameters
            camera.setParameters(parameters);
            camera.startPreview();
            camera.setDisplayOrientation(90);
            try {

                photo.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View arg0) {
                        // TODO Auto-generated method stub
                        // Toast.makeText(getApplicationContext(),
                        // "photo clicked!",
                        // Toast.LENGTH_SHORT).show();

                        // just calling the function which captures the
                        // photo
                        takePhoto();
                    }
                });
//                photo.performClick();
                wantPhoto = true;

                // finish();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    try {
        camera.setPreviewDisplay(holder);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    // set any cam params you need...
    camera.startPreview();
    if (wantPhoto) {
        wantPhoto = false;
        takePhoto();
    }
}

private int findFrontFacingCamera() {
    int cameraId = -1;
    // Search for the front facing camera
    int numberOfCameras = Camera.getNumberOfCameras();
    for (int i = 0; i < numberOfCameras; i++) {
        CameraInfo info = new CameraInfo();
        Camera.getCameraInfo(i, info);
        if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
            Log.d(DEBUG_TAG, "CameraActivity found");
            cameraId = i;
            break;
        }
    }
    return cameraId;
}

@Override
protected void onPause() {
    if (camera != null) {
        camera.release();
        camera = null;
    }
    super.onPause();
}

Camera.ShutterCallback shuttercallback = new Camera.ShutterCallback() {

    @Override
    public void onShutter() {
        // TODO Auto-generated method stub
        Log.d(TAG, "onShutter'd");
    }
};

Camera.PictureCallback rawpicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] arg0, Camera arg1) {
        // TODO Auto-generated method stub
        Log.d(TAG, "onPictureTaken - raw");
    }

};

Camera.PictureCallback jpegcallback = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera arg1) {
        // TODO Auto-generated method stub
        File pictureFileDir = getDir();

        if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

            Log.d(CameraActivity.DEBUG_TAG,
                    "Can't create directory to save image.");
            Toast.makeText(CameraActivity.this,
                    "Can't create directory to save image.",
                    Toast.LENGTH_LONG).show();
            return;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
        String date = dateFormat.format(new Date());
        String photoFile = "Picture_" + date + ".jpg";

        String filename = pictureFileDir.getPath() + File.separator
                + photoFile;

        File pictureFile = new File(filename);

        try {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();
            Toast.makeText(CameraActivity.this,
                    "New Image saved:" + photoFile, Toast.LENGTH_LONG)
                    .show();
        } catch (Exception error) {
            Log.d(CameraActivity.DEBUG_TAG, "File" + filename
                    + "not saved: " + error.getMessage());
            Toast.makeText(CameraActivity.this,
                    "Image could not be saved.", Toast.LENGTH_LONG).show();
        }
    }

};

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // set any cam params you need...
    camera.startPreview();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera.stopPreview();
    camera.release();

}

private static File getDir() {
    File sdDir = Environment
            .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
    return new File(sdDir, "CameraAPIDemo");
}

public void takePhoto() {

    camera.takePicture(shuttercallback, rawpicture, jpegcallback);
}

}

请理解,有一些重要的改进可以使您的代码受益。例如,建议在后台线程上调用 camera.open(),因为在某些设备上,这可能是一个漫长的过程,它可能会冻结 UI 超过一秒。

于 2014-01-01T06:42:36.853 回答