title: Android - taking pictures every minute with Camera
body: <p>I have a problem to solve - I was trying everything and nothing is working. 
  I am writing an application which should take picture every minute (period between pictures might be longer in future, but that isn't important) and upload it to ftp server. I am trying to open camera only for a while before taking photo and after taking photo release it and stop preview. But that doesn't work - there isn't even one picture taken. Opening camera etc. is doing by handler. If I put in handler only takePicture method - app works fine (and open camera once and keep it open in onCreate method), but I want to release camera and open it before taking picture to save battery.
  I attach my source code and logcat.</p>
  
  <blockquote>
    <p>MainActivity.java</p>
  </blockquote>
  
  <pre><code>public class MainActivity extends ActionBarActivity {
  
  private Camera mCamera;
  private CameraPreview mPreview;
  private File pictureFile;
  private File mediaStorageDir;
  private Context context;
  private Handler handler;
  
  public Camera.PictureCallback mPicture = new Camera.PictureCallback() {
  
      @Override
      public void onPictureTaken(byte[] data, Camera camera) {
          pictureFile = getOutputMediaFile();
          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());
          }
          Log.d("ftp", "photo taken: " + pictureFile);
          mCamera.release();
          startFTP();
      }
  };
  
  private Runnable runnable = new Runnable() {
      @Override
      public void run() {
          try {
              mCamera = Camera.open();
          } catch (Exception e) {
          }
          Camera.Parameters params = mCamera.getParameters();
          params.setPictureSize(1920, 1080);
          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
              params.set("orientation", "portrait");
              params.set("rotation", 90);
          }
          if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
              params.set("orientation", "landscape");
          }
          mCamera.setParameters(params);
          mPreview = new CameraPreview(context, mCamera);
          FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
          preview.addView(mPreview);
          mCamera.startPreview();
          mCamera.takePicture(null, null, mPicture);
          try {
              this.wait(5000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          handler.postDelayed(this, 60000);
      }
  };
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
  
      context = getApplicationContext();
      handler = new Handler();
      Button captureButton = (Button) findViewById(R.id.button_capture);
      captureButton.setOnClickListener(
              new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      handler.post(runnable);
                  }
              }
      );
  }
  
  public void startFTP()  {
          new Thread(new Runnable() {
              @Override
              public void run() {
                  Log.d("ftp", "photo uploading started: " + pictureFile);
                  String sendingPictureName = pictureFile.getName();
                  String serverAddress = "1111111";
                  String userId = "111111";
                  String password = "111111";
                  FTPClient ftp = new FTPClient();
                  try {
                      ftp.connect(serverAddress);
                      ftp.login(userId, password);
                      int reply = ftp.getReplyCode();
                      if (!FTPReply.isPositiveCompletion(reply)) {
                          ftp.disconnect();
                      }
                      ftp.setFileType(FTP.BINARY_FILE_TYPE);
                      ftp.enterLocalPassiveMode();
                      ftp.changeWorkingDirectory("/111111");
                      InputStream input;
                      input = new FileInputStream(pictureFile);
                      if (ftp.storeFile(pictureFile.getName(), input)) {
                          File fileToDelete = new File(mediaStorageDir.getPath() +"/"+ sendingPictureName);
                          //Log.d("ftp", "sciezka do usuwanego pliku: " + fileToDelete.getAbsolutePath());
                          fileToDelete.delete();
                      }
                      input.close();
                      Log.d("ftp", "photo uploading ended: " + sendingPictureName);
                      ftp.logout();
                      ftp.disconnect();
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
          }).start();
  
  }
  
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.menu_main, menu);
      return true;
  }
  
  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
      // Handle action bar item clicks here. The action bar will
      // automatically handle clicks on the Home/Up button, so long
      // as you specify a parent activity in AndroidManifest.xml.
      int id = item.getItemId();
      //noinspection SimplifiableIfStatement
      if (id == R.id.action_settings) {
          return true;
      }
      return super.onOptionsItemSelected(item);
  }
  
  private File getOutputMediaFile() {
      mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
      if (!mediaStorageDir.exists()) {
          if (!mediaStorageDir.mkdirs()) {
              Log.d("MyCameraApp", "failed to create directory");
              return null;
          }
      }
      String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
      File mediaFile;
      mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");
      return mediaFile;
  }
  
  
  public void cancelTimer(View view) {
      handler.removeCallbacks(runnable);
  }
  }
  </code></pre>
  
  <blockquote>
    <p>CameraPreview.java</p>
  </blockquote>
  
  <pre><code>public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
  private SurfaceHolder mHolder;
  private Camera mCamera;
  
  public CameraPreview(Context context, Camera camera) {
      super(context);
      mCamera = camera;
      mHolder = getHolder();
      mHolder.addCallback(this);
      mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  }
  
  public void surfaceCreated(SurfaceHolder holder) {
      try {
          mCamera.setPreviewDisplay(holder);
          mCamera.setDisplayOrientation(90);
          mCamera.startPreview();
      } catch (IOException e) {
          Log.d("TAG", "Error setting camera preview: " + e.getMessage());
      }
  }
  
  public void surfaceDestroyed(SurfaceHolder holder) {
  }
  
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
      if (mHolder.getSurface() == null){
          // preview surface does not exist
          return;
      }
      try {
          mCamera.stopPreview();
      } catch (Exception e){
      }
      try {
          mCamera.setPreviewDisplay(mHolder);
          mCamera.startPreview();
      } catch (Exception e){
          Log.d("TAG", "Error starting camera preview: " + e.getMessage());
      }
  }
  }
  </code></pre>
  
  <blockquote>
    <p>activity_main.xml - it's layout only for testing and it isn't perfect</p>
  </blockquote>
  
  <pre><code>&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  &gt;
  &lt;FrameLayout
      android:id="@+id/camera_preview"
      android:layout_width="500px"
      android:layout_height="500px"
      android:layout_weight="0.1"
      android:layout_above="@+id/button_capture" /&gt;
  
  &lt;Button
      android:id="@+id/button_capture"
      android:text="start timer"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:layout_weight="1"
      android:layout_alignParentEnd="false"
      android:layout_alignParentStart="false"
      android:layout_centerVertical="true" /&gt;
  
  &lt;Button
      android:id="@+id/timer_button"
      android:text="stop timer"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:layout_weight="1"
      android:layout_below="@+id/button_capture"
      android:layout_alignParentLeft="true"
      android:layout_alignParentStart="false"
      android:onClick="cancelTimer" /&gt;
  </code></pre>
  
  <p></p>
  
  <blockquote>
    <p>Logcat:</p>
  </blockquote>
  
  <pre><code>08-24 09:42:42.828    8935-8935/? E/Zygote﹕ MountEmulatedStorage()
  08-24 09:42:42.828    8935-8935/? I/libpersona﹕ KNOX_SDCARD checking this for 10185
  08-24 09:42:42.828    8935-8935/? E/Zygote﹕ v2
  08-24 09:42:42.828    8935-8935/? I/libpersona﹕ KNOX_SDCARD not a persona
  08-24 09:42:42.828    8935-8935/? I/SELinux﹕ Function: selinux_compare_spd_ram , priority [2] , priority version is VE=SEPF_SM-A500FU_5.0.2_0023
  08-24 09:42:42.838    8935-8935/? E/SELinux﹕ [DEBUG] get_category: variable seinfo: default sensitivity: NULL, cateogry: NULL
  08-24 09:42:42.838    8935-8935/? I/art﹕ Late-enabling -Xcheck:jni
  08-24 09:42:42.878    8935-8935/? D/TimaKeyStoreProvider﹕ TimaSignature is unavailable
  08-24 09:42:42.878    8935-8935/? D/ActivityThread﹕ Added TimaKeyStore provider
  08-24 09:42:42.988    8935-8935/com.example.dawid.camerabezpodgladu D/PhoneWindow﹕ *FMB* installDecor mIsFloating : false
  08-24 09:42:42.988    8935-8935/com.example.dawid.camerabezpodgladu D/PhoneWindow﹕ *FMB* installDecor flags : -2139029248
  08-24 09:42:43.108    8935-8951/com.example.dawid.camerabezpodgladu D/OpenGLRenderer﹕ Render dirty regions requested: true
  08-24 09:42:43.118    8935-8935/com.example.dawid.camerabezpodgladu D/PhoneWindow﹕ *FMB* isFloatingMenuEnabled mFloatingMenuBtn : null
  08-24 09:42:43.118    8935-8935/com.example.dawid.camerabezpodgladu D/PhoneWindow﹕ *FMB* isFloatingMenuEnabled return false
  08-24 09:42:43.138    8935-8935/com.example.dawid.camerabezpodgladu D/SRIB_DCS﹕ log_dcs ThreadedRenderer::initialize entered!
  08-24 09:42:43.138    8935-8951/com.example.dawid.camerabezpodgladu I/Adreno-EGL﹕ &lt;qeglDrvAPI_eglInitialize:379&gt;: EGL 1.4 QUALCOMM build: SKARAJGA_AU_LINUX_ANDROID_LA.BR.1.1.2_RB1.05.00.02.031.018+PATCH[ES]_msm8916_32_refs/tags/AU_LINUX_ANDROID_LA.BR.1.1.2_RB1.05.00.02.031.018__release_ENGG (I856e09677e)
  OpenGL ES Shader Compiler Version: E031.25.03.02
  Build Date: 04/06/15 Mon
  Local Branch:
  Remote Branch: refs/tags/AU_LINUX_ANDROID_LA.BR.1.1.2_RB1.05.00.02.031.018
  Local Patches: 112c106f3772623daa7b4181c6cf23491044ead1 Revert "Disable ASTC on A405"
  58a118cb818fdc906095a49a90977c15f9d3b223 Remove ASTC
  08-24 09:42:43.138    8935-8951/com.example.dawid.camerabezpodgladu I/OpenGLRenderer﹕ Initialized EGL, version 1.4
  08-24 09:42:43.158    8935-8951/com.example.dawid.camerabezpodgladu D/OpenGLRenderer﹕ Get maximum texture size. GL_MAX_TEXTURE_SIZE is 4096
  08-24 09:42:43.158    8935-8951/com.example.dawid.camerabezpodgladu D/OpenGLRenderer﹕ Enabling debug mode 0
  08-24 09:42:43.258    8935-8935/com.example.dawid.camerabezpodgladu I/Timeline﹕ Timeline: Activity_idle id: android.os.BinderProxy@3d659231 time:4110726
  08-24 09:42:44.648    8935-8935/com.example.dawid.camerabezpodgladu D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
  08-24 09:42:45.678    8935-8935/com.example.dawid.camerabezpodgladu I/Choreographer﹕ Skipped 34 frames!  The application may be doing too much work on its main thread.
  08-24 09:43:45.138    8935-8935/com.example.dawid.camerabezpodgladu W/CameraBase﹕ An error occurred while connecting to camera: 0
  08-24 09:43:45.498    8935-8935/com.example.dawid.camerabezpodgladu D/AndroidRuntime﹕ Shutting down VM
  08-24 09:43:45.498    8935-8935/com.example.dawid.camerabezpodgladu E/AndroidRuntime﹕ FATAL EXCEPTION: main
  Process: com.example.dawid.camerabezpodgladu, PID: 8935
  java.lang.RuntimeException: startPreview failed
          at android.hardware.Camera.startPreview(Native Method)
          at com.example.dawid.camerabezpodgladu.CameraPreview.surfaceCreated(CameraPreview.java:31)
          at android.view.SurfaceView.updateWindow(SurfaceView.java:682)
          at android.view.SurfaceView$3.onPreDraw(SurfaceView.java:200)
          at android.view.ViewTreeObserver.dispatchOnPreDraw(ViewTreeObserver.java:921)
          at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2226)
          at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1239)
          at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
          at android.view.Choreographer$CallbackRecord.run(Choreographer.java:777)
          at android.view.Choreographer.doCallbacks(Choreographer.java:590)
          at android.view.Choreographer.doFrame(Choreographer.java:560)
          at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:763)
          at android.os.Handler.handleCallback(Handler.java:739)
          at android.os.Handler.dispatchMessage(Handler.java:95)
          at android.os.Looper.loop(Looper.java:145)
          at android.app.ActivityThread.main(ActivityThread.java:6145)
          at java.lang.reflect.Method.invoke(Native Method)
          at java.lang.reflect.Method.invoke(Method.java:372)
          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
  08-24 09:43:48.818    8935-8935/com.example.dawid.camerabezpodgladu I/Process﹕ Sending signal. PID: 8935 SIG: 9
  </code></pre>
  
  <p>Even once method takePicture isn't called. Error is getting from bad realesing camera and reopening it after minute (next handler action).</p>
  
  <p>I will be very thankful for even one tip
  Dawid</p>