拍摄后拍摄照片'致电,' onPictureTaken'响应取决于app中的位置...为什么?

时间:2015-09-15 20:46:48

标签: java android callback android-camera

我正在尝试构建一个应用程序,它会定期调用相机拍照并保存。 我的问题是,除非我把'takePictuce'打电话给' onCreate'对“拍摄图片”的回应' (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();
}

但是,在MainActivity.java中的click事件中调用实例化CameraHandler将不会调用' onPictureTaken'响应takePicture电话。

(This snippet is located in MainACtivity.java)
  public void onClickListener(View view){
        CameraHandler cameraHandler = new CameraHandler();
}

那么为什么会发生这种情况呢?我怎样才能接到电话,让它在所属的班级拍照,而不是在主要的'该计划?

欢迎所有帮助

1 个答案:

答案 0 :(得分:0)

最后想出了如何设置手机拍摄定时照片而不显示任何屏幕。 我遇到了两个主要问题。首先,我想拍摄照片而不显示到屏幕。沿着这些方向,我找到了一个他们使用的例子:     mCamera.setPreviewTexture(new SurfaceTexture(10)); 使用此预览方法时,屏幕上没有显示任何内容。看来需要进行某种预览。另一种方法是将预览设置为1像素。这种方法在网上有例子似乎也有用,但我没试过。

第二个也是更大的问题与' onPictureTaken'方法。此方法会在拍摄照片后处理您的照片。呼叫。 似乎无论我使用什么循环方法,或者在代码中的哪个地方调用“拍摄图片”。找到了,所有的' onPictureTaken'方法排队等候,一旦接下来的话,就会一个接一个地调用方法。来电者结束了。

尽管onPictureTaken处理的图片数据处于适当的时间顺序,但我可以看到存储了数百张照片并等待处理可能会导致问题,并且需要找到一种方法,在处理和存储照片之前拍下一张照片。

沿着这些方向,我偶然发现了AlarmManager并将其与BroadcastReceiver和Future类耦合以解决问题。

我所做的是将alarmManger设置为在设定的时间或时间频率下关闭。 BroadcaseReceiver捕获此呼叫&反过来调用一个创建的方法 一个线索,其中一个未来'对象打电话拍照。

'未来'对象很好,因为它会等待物理相机拍摄照片(takePicture)然后处理它(onPictureTaken)。这一切都发生在一个线程中,然后终止。因此,不需要对要处理的图片进行排队,并且每个图片序列都是单独处理的。

代码包含在下面。请注意,某些默认'覆盖'被遗漏以节省空间。此外,可见屏幕基本上是一个捕获点击事件的按钮......非常基本。 MainActivity.java:     包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;
}

}