2015-09-15 35 views
0

我正在嘗試構建一個應用程序,它會定期調用相機拍攝照片並保存。 我的問題是,除非在'onCreate'中放置'takePictuce'調用,否則不會調用對'takePicture'(onPictureTaken)的響應。'takePicture'調用後,'onPictureTaken'響應取決於應用中的位置...爲什麼?

我已經儘可能簡單地分解了應用程序來說明。

如果一個類來處理照相機部分地定義爲:

public class CameraHandler { 
    private Camera mCamera; 

    public CameraHandler(){ 
     mCamera = Camera.open(); 
     mCamera.setPreviewTexture(new SurfaceTexture(10)); 

     mCamera.startPreview(); 
     mCamera.takePicture(null, null, mPicture); 
    } 

    Camera.PictureCallback mPicture = new Camera.PictureCallback() { 
     @Override 
     public void onPictureTaken(byte[] data, Camera camera) { 
      File pictureFile = getOutputMediaFile(); 
      if (pictureFile == null) { 
       return; 
      } 
      try { 
       FileOutputStream fos = new FileOutputStream(pictureFile); 
       fos.write(data); 
       fos.close(); 
      } catch (FileNotFoundException e) { 
      } catch (IOException e) {   } 
     } 
    }; 

然後當我把下面的代碼到MainActivity.java,「onPictureTaken」時CameraHandler被實例化時被調用。

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    CameraHandler cameraHandler = new CameraHandler(); 
} 

然而,把呼叫響應takePicture呼叫實例在MainActivity.java click事件CameraHandler不會叫「onPictureTaken」。

那麼,爲什麼會發生這種情況,我怎麼能得到調用拍照在其所屬的,而不是在程序的「主」類?

所有幫助歡迎

回答

0

終於想通了如何將手機設置爲定時採取圖片沒有任何屏幕顯示。 我遇到過兩個主要問題。首先,我想把照片不顯示在屏幕上。沿着這些線條,我找到了一個他們用過的例子: mCamera.setPreviewTexture(new SurfaceTexture(10));使用此預覽方法時屏幕上不顯示任何內容。看起來需要某種預覽。另一種方法是將預覽設置爲1個像素。這種方法有網上的例子似乎工作,但我沒有嘗試它。

第二個也是更大的問題與'onPictureTaken'方法有關。這個方法在'takePicture'調用之後處理你的圖片。 似乎無論我使用什麼循環方法,或者在代碼中調用'takePicture'的位置,所有'onPictureTaken'方法都會排隊,然後一次又一次地調用'takePicture'調用方的父級結束。

儘管由onPictureTaken處理的圖片數據的時間序列是正確的,但我可以看到有數百張圖片存儲並正在等待處理可能會導致問題,並且需要在圖片上處理並存儲之前下一張照片被拍攝。

沿着這些路線,我偶然發現了AlarmManager,並將它與BroadcastReceiver和Future類結合起來解決了這個問題。

我所做的是設置alarmManger以設定的時間或時間頻率關閉。 BroadcaseReceiver捕獲此呼叫&依次調用一個方法,該方法創建一個線程,在該線程中,「Future」對象使呼叫進行拍照。

'未來'的對象很好,因爲它會等待物理相機拍攝照片(takePicture)然後處理它(onPictureTaken)。這一切都發生在一個線程中,然後終止。所以不需要對圖片進行處理和每個圖片序列的排隊處理。

代碼包含在下面。請注意,一些默認的「覆蓋」已省略以節省空間。此外,可見屏幕基本上是一個捕獲點擊事件的按鈕...非常基本。主動式: 包myTest.com.test;

import android.app.Activity; 
import android.app.AlarmManager; 
import android.app.PendingIntent; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.content.IntentFilter; 
import android.location.LocationManager; 
import android.os.Bundle; 
import android.os.SystemClock; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.view.View; 
import android.widget.TextView; 
import android.widget.Toast; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.Future; 

public class MainActivity extends Activity { 
CameraHandler cameraHandler; 
public BroadcastReceiver br; 
public PendingIntent pi; 
public AlarmManager am; 

final static private long LOOPTIME = 20000; 
private static final ExecutorService threadpool = Executors.newFixedThreadPool(3); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    setup(); 
} 

private void setup() { 
    try{ 
     cameraHandler = new CameraHandler(); 
     br = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context c, Intent i) { 
       //Toast.makeText(c, "Taking a pic!", Toast.LENGTH_LONG).show(); 
       TryAThread(); 
      } 
     }; 
     registerReceiver(br, new IntentFilter("com.timedActivity.activity")); 
     pi = PendingIntent.getBroadcast(this, 0, new Intent("com.timedActivity.activity"), 0); 
     am = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE)); 
    } 
    catch (Exception e){  } 
} 

private void TryAThread() { 
    try{ 
     CameraCaller cameraCaller = new CameraCaller(cameraHandler); 
     Future future = threadpool.submit(cameraCaller); 

     while (!future.isDone()) { 
      try { 
       Thread.sleep(5000); 
      } catch (Exception ex) { } 
     } 
    } 
    catch (Exception e){  } 
} 

@Override 
protected void onDestroy() { 
    am.cancel(pi); 
    unregisterReceiver(br); 
    super.onDestroy(); 
} 

public void onClickListener(View view){ 
    try{ 
     am.setRepeating(am.ELAPSED_REALTIME,SystemClock.elapsedRealtime(), LOOPTIME, pi); 
    } 
    catch (Exception e){  } 
} 

}

CameraCaller.java :.

package myTest.com.test; 
import java.util.concurrent.Callable; 

public class CameraCaller implements Callable { 
private CameraHandler cameraHandler; 
public CameraCaller(CameraHandler ch){ 
    cameraHandler = ch; 
} 

@Override 
public Object call() throws Exception { 
    cameraHandler.takeAPic(); 
    return true; 
} 

}

CameraHandler.java :.

package myTest.com.test; 

import android.graphics.SurfaceTexture; 
import android.hardware.Camera; 
import android.os.Environment; 
import android.util.Log; 
import junit.runner.Version; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.text.SimpleDateFormat; 
import java.util.Date; 

public class CameraHandler implements Camera.PictureCallback{ 
private Camera mCamera; 
public CameraHandler(){ 
} 

    public Boolean takeAPic(){ 
    try{ 
     if (mCamera == null){ 
      mCamera = Camera.open(); 
      mCamera.enableShutterSound(false); 

      try { 
       mCamera.setPreviewTexture(new SurfaceTexture(10)); 
      } 
      catch (IOException e1) {Log.e(Version.id(), e1.getMessage()); 
      } 
     } 
     mCamera.startPreview(); 
     mCamera.takePicture(null, null, this); 
    } 
    catch (Exception ex){  } 
     return true; 
} 

    @Override 
    public void onPictureTaken(byte[] data, Camera camera) { 
     File pictureFile = getOutputMediaFile(); 
     if (pictureFile == null) { 
      return; 
     } 
     try { 
      FileOutputStream fos = new FileOutputStream(pictureFile); 
      fos.write(data); 
      fos.close(); 
     } catch (FileNotFoundException e) { 

     } catch (IOException e) {   } 
     try { 
      Thread.sleep(2000); 
     }catch (Exception ex){} 
    } 

public static File getOutputMediaFile() { 
    File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); 
    File mediaStorageDir = new File(file, "MyCameraApp"); 
    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; 
    mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); 
    return mediaFile; 
} 

}

相關問題