2015-04-17 42 views
1

我是新來開發Android,我發現事件的流程相當混亂。Android中的事件流程

我想開發一個簡單的應用程序,每3秒拍一張照片並將其保存到外部存儲。我寫的(非常糟糕)的代碼看起來應該是繼這些事件序列:

button pressed > take photo > save photo > take photo > save photo > ...

而是它似乎是在做以下幾點:

button pressed > take photo > ... > take photo > save photo > ... > save photo

即節約大概所有的RAM中的照片,然後寫在磁盤的所有最後,而不是在路上。這對於大量圖像而言失敗。

任何人都可以指向正確的方向嗎?這是我的(可怕的)代碼:

@SuppressWarnings("deprecation") 
public class PhotoActivity extends Activity { 

    Camera c = Camera.open(); 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_photo); 

     // Original, eh? 
     final Button button = (Button)findViewById(R.id.button1); 

     button.setOnClickListener(new View.OnClickListener() { 
      public void onClick(View v) { 
       try { 
        // Fails for large i 
        for(int i = 0; i < 500; i++) { 
         // I don't think this is right. 
         Thread.sleep(1500); 
         takePictureNoPreviewAtAll(i); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    private void takePictureNoPreviewAtAll(int i) throws IOException, InterruptedException { 
     // I don't know why this is 1, but it seems to work :) 
     SurfaceTexture mTexture = new SurfaceTexture(1); 
     c.setPreviewTexture(mTexture); 
     c.startPreview(); 

     // This is not right either, but the camera seems to need both sleeps to work. 
     Thread.sleep(1500); 
     c.takePicture(null, null, getJpegCallback(i)); 
    } 
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     getMenuInflater().inflate(R.menu.menu_photo, menu); 
     return true; 
    } 

    private android.hardware.Camera.PictureCallback getJpegCallback(final int i) { 
     android.hardware.Camera.PictureCallback jpeg = new android.hardware.Camera.PictureCallback() { 
      @Override 
      public void onPictureTaken(byte[] data, Camera camera) { 
       try { 
        // Provided in a separate file, just saving to SD card, it seems to work. 
        Map<String, File> externalLocations = ExternalStorage.getAllStorageLocations(); 
        File externalSdCard = externalLocations.get(ExternalStorage.EXTERNAL_SD_CARD); 

        FileOutputStream f = new FileOutputStream(externalSdCard.getPath() + "/" + System.currentTimeMillis() + ".jpg"); 
        f.write(data); 
        f.flush(); 
        f.close(); 
        Log.d(externalSdCard.getAbsolutePath(), "ddd"); 
       } catch (IOException e) { 
        //do something about it 
        e.printStackTrace(); 
       } 
      } 
     }; 
     return jpeg; 
    } 
} 

如果需要,我可以提供ExternalStorage的來源。

+2

不要試圖睡在一個UI事件回調,或在ui線程的任何地方。您需要創建後臺線程或使用定時器或延遲發佈到處理程序的機制(如果要在活動處於前臺時執行此操作,或者如果要在活動時執行此操作,則需要使用服務中的線程)不是。 –

回答

-1

我寧願等到回調完成它的工作,然後才拍攝其他照片。或者至少限制同時呼叫相機的數量,從而限制照片處理量。不知道它是否有助於消除所有等待,但至少會使代碼更漂亮。

1

正如克里斯所說,問題可能是你阻止了UI線程兩次,你可以嘗試使用Timer和TimerTask類。

http://examples.javacodegeeks.com/android/core/activity/android-timertask-example/

Timer timer = new Timer(); 
TimerTask cameraTask = new TimerTask() { 
    public void run() { 
     //Your camera code will be here. 
    } 
}; 
timer.schedule(cameraTask, 0, 1500); 

這樣,你的代碼將在不同的線程中執行。