2016-10-10 4 views
0

TakePic 클래스에서 AsyncTask를 실행하고 있습니다. doInBackground 기능에서 나는 Camera.takePicture 기능을 사용하고 있습니다. 이제 모든 것이이 시점에서 괜찮습니다. 사진을 찍고 그 위치를 /sdcard/%d.jpg에 저장하고 있습니다.doInBackground Android 실행 후 AsyncTask가 완료되지 않습니다.

public class TakePic extends AsyncTask<CameraPreview, String, Integer> { 

    @Override 
    protected Integer doInBackground(final CameraPreview... params) { 
      params[0].camera.takePicture(null,null,new Camera.PictureCallback() { 
       @Override 
       public void onPictureTaken(byte[] data, Camera camera) { 
        FileOutputStream outStream = null; 
        try { 
         outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis())); 
         outStream.write(data); 
         outStream.close(); 
         Log.e("picture_saved", "Picture has been saved succesfully: " + data.length); 
         camera.release(); 
        } catch (FileNotFoundException e) { 
         e.printStackTrace(); 
         Log.e("file_not_found: ","couldn't save the file "+e.getMessage()); 
        } catch (IOException e) { 
         e.printStackTrace(); 
         Log.e("IOexception: ","couldn't save the file "+e.getMessage()); 
        } 
       } 
      }); 
     Log.e("doinback_compt:" ,"done"); 
     return 0; 
    } 

    @Override 
    protected void onPostExecute(Integer integer) { 
    } 
} 

그러나 주 클래스에서이 AsyncTask를 실행하면 완료되지 않습니다. 다른 함수를 실행해야하고이 AsyncTask가 끝날 때까지 기다려야합니다. 그래서 AsyncTask를 실행 한 후에 while 루프를 사용하여 작업의 상태를 확인하지만 상태는 변하지 않습니다.

TakePic backCam=new TakePic(); 
    backCam.execute(cameraPreview_front); 
    while (backCam.getStatus()!= AsyncTask.Status.FINISHED){ 
     *waiting for async task to finish* 
    } 

그것은 while 루프 정상을 실행 doInBackground 내 로그 캣 쇼에 갇혀, 그리고 파일이 해당 위치에 저장됩니다.

10-10 18:06:14.497 15975-15975/com.urun.camera_test E/clicked_capture:: ok 
10-10 18:06:14.633 15975-16452/com.urun.camera_test E/doinback_compt:: done 

그래서 무엇을해야합니까? 미리 감사드립니다.

+0

왜 그것이 끝나지 않았다고 생각합니까? – xAqweRx

+0

while 루프에서 부정확 한 체크를 한 것 같습니다. 그리고 이것 때문에 * 비동기 태스크 대기 중 *이 정상적으로 작동하지 않습니다. – xAqweRx

+2

'while' 루프가 UI 스레드를 효과적으로 차단하기 때문에 'AsyncTask'를 사용하는 것은 잘못된 방법입니다. 'AsyncTask'가 완료된 후에 실행할 코드를 onPostExecute()로 옮깁니다. – Egor

답변

0

AsyncTask 실행 후 일부 코드를 수행해야하는 경우 하나의 솔루션을 제안 할 수 있습니다. 이 Runnable*waiting for async task to finish* 코드를 감싸고 비동기 작업에 PARAM 파일로 보내 (그러나 이것은 최적의 솔루션, 단지 빠른 아니다) 현재 코드

new AsyncTask<Object, Void, Runnable>() { 
     @Override 
     protected Runnable doInBackground(Object... runnables) { 
      CameraPreview cp = (CameraPreview) runnables[0]; 
      Runnable callback = (Runnable) runnables[1]; 

      /**your main logic*/ 

      return callback; 
     } 

     @Override 
     protected void onPostExecute(Runnable aVoid) { 
      super.onPostExecute(aVoid); 
      if (aVoid != null) 
       aVoid.run(); 
     } 
    }.execute(cameraPreview , new Runnable() { 
     @Override 
     public void run() { 
      /**code to run();**/ 
     } 
    }); 

가능한 문제 것은 :

당신은

@Override 
protected void onPostExecute(Integer integer) { 
super.onPostExecute(integer); 
} 
super.onPostExecute(integer);

보십시오 변화 코드를 실행하지 않습니다

+0

좋아, 어디에서 내 자신의 CameraPreview 매개 변수를 전달합니까? –

+0

@AhmetUrun을 첫 번째 매개 변수로 사용합니다. 업데이트 된 AsyncTask – xAqweRx

+0

나는 편집 한 코드와 좋은 형제를 시도했다. –

0

앞서 지적한 것처럼 특정 이벤트를 기다리는 동안 주 스레드를 차단하는 것은 의미가 없습니다. 그러나 여전히 AsyncTask에서 무언가를 얻으려는 경우 사용할 것을 권합니다. FutureTask

0

코드에서 볼 수 있듯이 AsyncTask가 올바르게 끝납니다. 문제는 AsyncTask 내부에서 사진을 찍는 것입니다. 따라서 Camera.PictureCallback이 그림을 기다리는 동안 작업은 "takePicture"메서드를 호출 한 직후에 끝납니다. 어떻게해야합니까

(이것은 단지 접근이다)이 같은 것입니다 :

public class TakePic { 

    public interface MyTakePicListener{ 
     void onPictureTaken(); 
     void onPictureError(); 
    } 

    private MyTakePicListener myListener; 


    public void takePicture(CameraPreview cameraPreview) { 
     cameraPreview.camera.takePicture(null, null, new Camera.PictureCallback() { 
      @Override 
      public void onPictureTaken(final byte[] data, final Camera camera) { 

       new Thread(new Runnable() { 
        @Override 
        public void run() { 

         FileOutputStream outStream = null; 
         try { 
          outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis())); 
          outStream.write(data); 
          outStream.close(); 
          Log.e("picture_saved", "Picture has been saved succesfully: " + data.length); 
          camera.release(); 

          HERE you should call a listener to continue with your success code 
          myListener.onPictureTaken(); 
         } catch (FileNotFoundException e) { 
          e.printStackTrace(); 
          Log.e("file_not_found: ", "couldn't save the file " + e.getMessage()); 

          HERE you should call a listener to continue with your error code 
          myListener.onPictureError(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
          Log.e("IOexception: ", "couldn't save the file " + e.getMessage()); 

          HERE you should call a listener to continue with your error code 
          myListener.onPictureError(); 
         } 

         Log.e("doinback_compt:", "done"); 



        } 
       }).start(); 
      } 

     }); 
    } 

} 

, 이것은 당신을 도울 수 있는지 알려 주시기 바랍니다.

0

이것은 이상한 방식으로 처리됩니다. 먼저 CameraPreview.camera.takePicture()이 백그라운드에서 실행되기 때문에 생성자에 Camera.PictureCallback을 전달해야합니다. 거기에 스레드를 간단하게 쌓아 두는 것입니다. 메인 스레드에서 이것을 시도하십시오

[yourCameraPreview].camera.takePicture(null,null,new Camera.PictureCallback() { 
    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     camera.release(); 
     // Read below 
    } 
} 

이제 우리는 그림 콜백을 기다릴 수 있습니다. 데이터를 다시 얻으면 AsyncTask를 호출하여 파일에 저장하고 자체 콜백을 적용하여 응답을 기다릴 수 있습니다. 우리는 정적 인 내부 클래스를 활용하여 모든 것을 작동시킬 수 있습니다.그런 다음

private static class ImageSaver extends AsyncTask<Byte, Void, Exception>{ 

    public interface ImageSavedListener{ 
     void onImageSaved(Exception e); 
    } 

    private ImageSavedListener mCallback; 

    public ImageSaver(ImageSavedListener callback){ 
     mCallback = callback; 
    } 

    @Override 
    protected void doInBackground(Byte... data){ 
     if(data == null || data.length == 0) 
      return new Exception("Data returned from camera is invalid"); 

     try { 
      FileOutputStream outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis())); 
      outStream.write(data); 
      outStream.close(); 
      Log.d("picture_saved", "Picture has been saved succesfully: " + data.length); 
     } catch (FileNotFoundException e) { 
      Log.e("file_not_found: ","couldn't save the file "+e.getMessage()); 
      return e; 
     } catch (IOException e) { 
      Log.e("IOexception: ","couldn't save the file "+e.getMessage()); 
      return e; 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Exception e){ 
     if(mCallback != null) 
      mCallback.onImageSaved(e); 
    } 
} 

과 같이 호출

new ImageSaver(new ImageSavedListener(){ 
    @Override 
    public void onImageSaved(Exception e){ 
     if(e == null){ 
      // do what you want 
     } 
     else 
      e.printStackTrace(); 
    } 
}).execute(data); 

이것은 백그라운드에서 사진을 촬영 응답을 기다리는 백그라운드에서 파일에 대한 응답을 저장합니다 (섹션에서 위 Read below를 언급) , 응답을 기다린 다음 저장 후 반환 된 예외를 기반으로 원하는 작업을 수행하십시오.

관련 문제