android - 如何在使用加速计传感器检测到运动时拍照

标签 android android-camera android-sensors

我想开发一个可以使用加速度计拍照的应用程序。 我可以使用按钮拍照,但是当我调用相同的方法时,即来自“onSensorChanged”方法的 camera.takePicture 应用程序崩溃。

这是我的代码

package com.example.recognizer;

import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;

public class Camera_Capture extends Activity implements  SurfaceHolder.Callback
{

       private SurfaceView sv;
       private SurfaceHolder sHolder;
       private Camera mCamera;
       private Parameters parameters;
       private Button button;
       private boolean mInitialized;
       private SensorManager sensorManager =null;
       private Sensor mAccelerometer;
       private final float NOISE = (float) 2.0;
       private float mLastx, mLasty;

    /** Called when the activity is first created. */
    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_capture);
        sv = (SurfaceView) findViewById(R.id.surfaceview);
        Log.d("Logging", " inside onCreate()");

        mInitialized =false;
        sensorManager =(SensorManager)getSystemService(Context.SENSOR_SERVICE);
        mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        sensorManager.registerListener(sl, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);

        button = (Button)findViewById(R.id.capture_image);
        button.setOnClickListener(new View.OnClickListener()
    {

        @Override
        public void onClick(View v)
        {
            Log.d("Logging", "inside onclick()");
            capture();
        }




    });

        sHolder = sv.getHolder();
        sHolder.addCallback(this);
        Log.d("Logging", "callback added");

        //tells Android that this surface will have its data constantly replaced
        sHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mCamera = Camera.open(0);
        try {
           mCamera.setPreviewDisplay(sHolder);
           Log.d("Logging", "before startpreview()");
           mCamera.startPreview();

        } catch (IOException exception) {
            exception.printStackTrace(); 
            mCamera.release();
            mCamera = null;
        }

    }

    @Override
    protected void onResume()
    {
        super.onResume();
    sensorManager.registerListener(sl, mAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause()
    {
        sensorManager.unregisterListener(sl);
        super.onPause();
    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
    {
        Log.d("Logging", "inside  surfaceChanged()");
            try
        {
            mCamera.setPreviewDisplay(arg0);
        } catch (IOException e)
        {
                e.printStackTrace();
        }

         parameters = mCamera.getParameters();
         parameters.setPictureSize(640,480);
         mCamera.setParameters(parameters);
         Log.d("Logging", "before startpreview() of surfaceChanged()");

         mCamera.startPreview();



    }
        private void capture()
        {
        Log.d("Cam_capture","Inside Capture" );
        mCamera.takePicture(null, null, new Camera.PictureCallback()
         {
             @Override
             public void onPictureTaken(byte[] data, Camera camera)
             {
                Log.d("Capture_cam", "Inside onPictureTaken()");
                  Intent intent = new Intent();
                intent.putExtra("image_arr", data);
                mCamera.stopPreview();
                setResult(RESULT_OK, intent);
                finish();
             }

         });

        }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        if (Build.VERSION.SDK_INT >= 8) mCamera.setDisplayOrientation(90);
        // The Surface has been created, acquire the camera and tell it where
        // to draw the preview.

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {

       mCamera.stopPreview();
       mCamera.release();
       mCamera = null;
    }
   SensorEventListener sl =new SensorEventListener() {

    @Override
    public void onSensorChanged(SensorEvent event) {
        float x = event.values[0];
        float y = event.values[1];

        if(!mInitialized){
        mLastx = x;
        mLasty = y;
        mInitialized = true;
        }
        else{
        float deltaX = Math.abs(mLastx - x);
        float deltaY = Math.abs(mLasty - y);
        Log.d("Cam_cap","DeltaX="+deltaX+"deltay="+deltaY);
        mLastx = x;
        mLasty = y;
        if(deltaX > NOISE || deltaY > NOISE)
            capture();

        }

    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // TODO Auto-generated method stub

        }
     };

}

这是我的 logcat 的输出*(已编辑)*

01-20 16:42:39.835 20331 20331 D AndroidRuntime: 
01-20 16:42:39.835 20331 20331 D AndroidRuntime: >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit (tool) <<<<<<
01-20 16:42:39.835 20331 20331 D AndroidRuntime: CheckJNI is OFF
01-20 16:42:39.835 20331 20331 D AndroidRuntime: language=-Duser.language=en region=-Duser.region=IN
01-20 16:42:39.971 20331 20331 D AndroidRuntime: Calling main entry com.android.commands.am.Am
01-20 16:42:39.981 20331 20331 D AndroidRuntime: Shutting down VM
01-20 16:43:34.148 20346 20346 D AndroidRuntime: Shutting down VM
01-20 16:43:34.171 20346 20346 E AndroidRuntime: FATAL EXCEPTION: main
01-20 16:43:34.171 20346 20346 E AndroidRuntime: java.lang.RuntimeException: takePicture failed
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.hardware.Camera.native_takePicture(Native Method)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.hardware.Camera.takePicture(Camera.java:1278)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at com.example.currencyrecognizer.Camera_Capture$1.onSensorChanged(Camera_Capture.java:216)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.hardware.SystemSensorManager$ListenerDelegate$1.handleMessage(SystemSensorManager.java:204)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:99)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:153)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:5297)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at java.lang.reflect.Method.invokeNative(Native Method)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Method.java:511)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
01-20 16:43:34.171 20346 20346 E AndroidRuntime:    at dalvik.system.NativeStart.main(Native Method)
01-20 16:43:40.926 20572 20572 D AndroidRuntime: 
01-20 16:43:40.926 20572 20572 D AndroidRuntime: >>>>>> AndroidRuntime START com.android.internal.os.RuntimeInit (tool) <<<<<<
01-20 16:43:40.927 20572 20572 D AndroidRuntime: CheckJNI is OFF
01-20 16:43:40.927 20572 20572 D AndroidRuntime: language=-Duser.language=en region=-Duser.region=IN
01-20 16:43:41.074 20572 20572 D AndroidRuntime: Calling main entry com.android.commands.am.Am
01-20 16:43:41.094 20572 20572 D AndroidRuntime: Shutting down VM

最佳答案

在相机预览准备就绪之前,您无法启动传感器监听器。我会简单地设置 sl = null 并将其初始化为 new SensorEventListener() 调用 sensorManager.registerListener(sl, ...) surfaceChanged() 结束时 startPreview() 之后;但是你也应该注意不要太晚调用它(当预览停止时),所以使用一个 boolean 字段来指示 capture() 方法可能是明智的可以调用mCamera.takePicture()

关于android - 如何在使用加速计传感器检测到运动时拍照,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21193122/

相关文章:

android - 未知方法安装包

android - 如何使线程串联工作

java - 使用 Android SDK 23 请求相机权限

android - 通过我的应用程序使用 Intent 打开相机时停止保存图像

android - 获取手机的 z 轴和磁北极(而不是 y 轴)之间的角度

java - Javamail-android商用

Android 完成 Activity 并重新加载以前的 Activity

java - 如何在 Java 中将字节数组存储到 SQL Server varbinary(MAX) 字段中?

android - 如何检测android中的用户存在?

android - 将设备中的磁场 X、Y、Z 值转换为全局引用系