2016-11-27 1 views
0

Я просмотрел множество ссылок, которые ищут решение, но это мое первое официальное приложение на Android. Я сделал другие маленькие, такие как калькулятор, но таких нет, поэтому я не могу понять советы и решения, даже если я их прочитаю.Android-камера + гироскоп/акселерометр сбой при съемке

приложение в основном выполняет следующие действия: -

  1. взять в гироскоп и акселерометр чтений
  2. CALCulate угол движения, как пользователь перемещается по кругу.
  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. Не называйте stopPreview() непосредственно перед вызовом takePicture(): 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: конфигурации Makernote данных не удалось 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) _ или пример кода в проекте [Открыть камеру] (https://github.com/almalence/OpenCamera). –