2016-11-27 45 views
0

我已經通過很多鏈接尋找解決方案,但這是我在Android上的第一個官方應用程序。我已經制作了其他小型的計算器,但沒有一個這樣,所以即使我閱讀它們,我也無法理解這些建議和解決方案。Android攝像頭+陀螺儀/加速度計應用程序在拍照時崩潰

該應用程序基本上執行以下操作: -

  1. 取在陀螺儀和加速度計讀數運動的
  2. 計算角度爲在一個圓圈用戶移動。
  3. 每10度拍攝一張照片。

第一類工作在表面視圖。而第二個工作在拍照和計算傳感器讀數

我已經制定了前兩部分。但第三部分是問題。 每次拍攝圖像時,應用程序都會掛起,表面視圖停止工作。沒有任何反應。當我旋轉另一個10度時,應用程序崩潰。

有人可以告訴我我做錯了什麼。先謝謝你。

package com.example.mehta.accelerometerin; 

import android.app.Activity; 
import android.content.Context; 
import android.content.pm.PackageManager; 
import android.graphics.Bitmap; 
import android.hardware.Camera; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorManager; 
import android.net.Uri; 
import android.os.Environment; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.hardware.SensorEventListener; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 
import android.view.View; 
import android.widget.FrameLayout; 
import android.widget.TextView; 
import android.widget.Toast; 

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

import static android.content.ContentValues.TAG; 
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE; 
import static java.lang.Math.sqrt; 







class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 




    private boolean checkCameraHardware(Context context) { 
     if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { 
      // this device has a camera 
      return true; 
     } else { 
      // no camera on this device 
      return false; 
     } 
    } 




    public CameraPreview(Context context, Camera camera) { 
     super(context); 
     mCamera = camera; 


     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     // deprecated setting, but required on Android versions prior to 3.0 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 


    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, now tell the camera where to draw the preview. 
     try { 
      mCamera.setPreviewDisplay(holder); 
      mCamera.startPreview(); 
     } catch (IOException e) { 
      Log.d(TAG, "Error setting camera preview: " + e.getMessage()); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 
     // If your preview can change or rotate, take care of those events here. 
     // Make sure to stop the preview before resizing or reformatting it. 


     if (mHolder.getSurface() == null) { 
      // preview surface does not exist 
      return; 
     } 

     // stop preview before making changes 
     try { 
      mCamera.stopPreview(); 
     } catch (Exception e) { 
      // ignore: tried to stop a non-existent preview 
     } 

     // set preview size and make any resize, rotate or 
     // reformatting changes here 

     // start preview with new settings 
     try { 
      mCamera.setPreviewDisplay(mHolder); 
      mCamera.setDisplayOrientation(90); 
      mCamera.startPreview(); 

     } catch (Exception e) { 
      Log.d(TAG, "Error starting camera preview: " + e.getMessage()); 
     } 

    } 


    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 

    } 


} 


class MainActivity extends AppCompatActivity implements SensorEventListener { 
    private Camera mCamera; 
    private CameraPreview mPreview; 

    private SensorManager senSensorManager; 
    private Sensor senAccelerometer; 
    private Sensor senGyroscope; 
    private long lastUpdate = 0; 
    private float last_x, last_y, last_z; 
    private static final int SHAKE_THRESHOLD = 600; 
    TextView tv1, tv2, tv3, tv4, tv5; 
    int j = 0; 
    int i = 1; 
    int l = 10; 
    int m = 0; 
    private float xg, yg, zg, xa, ya, za; 
    private float x1, y1; 
    float x2, y2; 
    private float xang, yang, zang; 
    private float zacc; 
    private float xacc; 
    private float yacc; 
    private int greset; 
    public static Camera getCameraInstance() { 
     Camera c = null; 
     try { 
      c = Camera.open(); // attempt to get a Camera instance 
     } catch (Exception e) { 
      // Camera is not available (in use or does not exist) 
     } 
     return c; // returns null if camera is unavailable 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     // Create an instance of Camera 
     mCamera = getCameraInstance(); 

     // Create our Preview view and set it as the content of our activity. 
     mPreview = new CameraPreview(this, mCamera); 
     FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); 
     preview.addView(mPreview); 
     greset = 0; 
     senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
     senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
     senGyroscope = senSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 

     senSensorManager.registerListener(this,senAccelerometer,SensorManager.SENSOR_DELAY_NORMAL); 
     senSensorManager.registerListener(this,senGyroscope,SensorManager.SENSOR_DELAY_NORMAL); 


    } 



    public static final int MEDIA_TYPE_IMAGE = 1; 
    public static final int MEDIA_TYPE_VIDEO = 2; 

    /** Create a file Uri for saving an image or video */ 
    private static Uri getOutputMediaFileUri(int type){ 
     return Uri.fromFile(getOutputMediaFile(type)); 
    } 

    /** Create a File for saving an image or video */ 
    private static File getOutputMediaFile(int type){ 

     // To be safe, you should check that the SDCard is mounted 
     // using Environment.getExternalStorageState() before doing this. 

     File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
       Environment.DIRECTORY_PICTURES), "MyCameraApp"); 
     // This location works best if you want the created images to be shared 
     // between applications and persist after your app has been uninstalled. 

     // Create the storage directory if it does not exist 
     if (! mediaStorageDir.exists()){ 
      if (! mediaStorageDir.mkdirs()){ 
       Log.d("MyCameraApp", "failed to create directory"); 
       return null; 
      } 
     } 

     // Create a media file name 
     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
     File mediaFile; 
     if (type == MEDIA_TYPE_IMAGE){ 
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
        "IMG_"+ timeStamp + ".jpg"); 
     } else if(type == MEDIA_TYPE_VIDEO) { 
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + 
        "VID_"+ timeStamp + ".mp4"); 
     } else { 
      return null; 
     } 

     return mediaFile; 
    } 

    private Camera.PictureCallback mPicture = new Camera.PictureCallback() { 

     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      Toast.makeText(getApplicationContext(), "on Picture Taken", Toast.LENGTH_SHORT).show(); 

      File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); 
      if (pictureFile == null){ 
       Log.d(TAG, "Error creating media file, check storage permissions: "); 
       return; 
      } 

      try { 
       FileOutputStream fos = new FileOutputStream(pictureFile); 
       fos.write(data); 
       fos.close(); 
      } catch (FileNotFoundException e) { 
       Log.d(TAG, "File not found: " + e.getMessage()); 
      } catch (IOException e) { 
       Log.d(TAG, "Error accessing file: " + e.getMessage()); 
      } 
     } 
    }; 



    protected void onPause() { 
     super.onPause(); 
     senSensorManager.unregisterListener(this); 

    } 

    protected void onResume() { 
     super.onResume(); 
     senSensorManager.registerListener(this,senAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); 
     senSensorManager.registerListener(this,senGyroscope,SensorManager.SENSOR_DELAY_NORMAL); 
    } 


    public void onSensorChanged(SensorEvent sensorEvent) { 
     Sensor mySensor = sensorEvent.sensor; 


     if (mySensor.getType() == Sensor.TYPE_GYROSCOPE) { 
      greset ++; 
      zg += sensorEvent.values[1]; 
      xg +=sensorEvent.values[0]; 
      yg +=sensorEvent.values[2]; 
      if(zg>30) 
      { 
       zg=0; 
      } 
      if(xg>30) 
      { 
       xg=0; 
      } 
      if(yg>30) 
      { 
       yg=0; 
      } 
      xang = xg*12; 
      yang = yg*12; 
      zang = zg*12; 
      if(zang>=l) { 
       Toast.makeText(getApplicationContext(), "click="+i, Toast.LENGTH_SHORT).show(); 
       mCamera.stopPreview(); 
       mCamera.takePicture(null,null,mPicture); 
       mCamera.startPreview(); 
       l += 10; 
       i++;} 




      if (greset >10) 
      { 
       xg +=0.1; 

       greset = 0; 
      } 

     } 

     if(mySensor.getType()==Sensor.TYPE_ACCELEROMETER) 
     { 
      xa = sensorEvent.values[0]; 
      za = sensorEvent.values[1]; 
      ya = sensorEvent.values[2]; 



      zacc = (float)(za - (((90 - xang)/ 90) * 9.8)); 


     } 



     if (l > 360) { 
      l = 10; 
     } 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) { 

    } 

    public int returnvalue(){ 
     return(i); 
    } 

} 

回答

0
  1. 立即調用takePicture()之前不要叫stopPreview()This method is only valid when preview is active (after startPreview()). Preview will be stopped after the image is taken

  2. 您應致電startPreview()onPictureTaken(),而不是在撥打takePicture()後不立即。

  3. 在單獨的處理程序線程上打開相機,而不是在主(UI)線程上打開相機。

您的代碼可能存在其他問題,但讓我們先着手解決這三個即時問題。

+0

嗨,謝謝你的指針。我做了第1部分和第2部分,這讓我的應用程序至少不會一直掛着,我真的不明白第3點,請您稍後解釋一下。但現在又出現了一個問題,它不會將圖像保存到我的SD卡上。我開始調試模式,所有口口聲聲說 1)式Qcamera :: QCameraExif *式Qcamera :: QCamera2HardwareInterface :: getExifData():getExifGpsDataTimeStamp失敗 2)mm_jpeg_configure_job_params:配置製造商註釋數據未能 3) faceproc_comp_eng_destroy:相冊保存失敗-1 –

+0

哦,我想出了問題。無論如何謝謝。如果你可以解釋點3會很棒。 –

+0

你可以找到一些解釋在_ [HandlerThread優於其他類似類的最佳使用](http://stackoverflow.com/questions/18149964/best-use-of-handlerthread-over-other-similar-classes/19154438#19154438 )_,或[Open Camera](https://github.com/almalence/OpenCamera)項目中的代碼示例。 –