如何在Android中完成现有运行的线程/处理程序后启动线程或处理程序

时间:2014-05-30 04:42:02

标签: android multithreading android-camera android-handler

我正在开发一个Android应用程序,用于自动从FrontBack相机捕获图像。我已经完成了将相机从后向前切换并保存捕获图像的编码进入SDcard。我在手动点击按钮时测试捕获图像,效果很好。我需要的是从back camera自动捕获图像然后从front camera自动捕获图像出于这个目的,我使用了handler.postDelayed()方法,但它显示了java.lang.RuntimeException: takePicture failed。在这里我附上了我的代码,所以任何人都可以帮我解决错误。

MainActivity.java

package com.example.camera1;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;


import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

       private Camera cameraObject;
       private ShowCamera showCamera;
       private ImageView pic;
       private Button takePhotoButton;
       FrameLayout preview;
       private static final ScheduledExecutorService worker = 
               Executors.newSingleThreadScheduledExecutor();
       public static Camera isCameraAvailiable(){
          Camera object = null;
          try {

             object = Camera.open(); 
          }
          catch (Exception e){
          }
          return object; 
       }

       private PictureCallback capturedIt = new PictureCallback() {

          @Override
          public void onPictureTaken(byte[] data, Camera camera) {

          Bitmap bitmap = BitmapFactory.decodeByteArray(data , 0, data .length);
          if(bitmap==null){
             Toast.makeText(getApplicationContext(), "not taken", Toast.LENGTH_SHORT).show();
          }
          else
          {
             Toast.makeText(getApplicationContext(), "taken", Toast.LENGTH_SHORT).show();  

             File pictureFileDir = getDir();

            if (!pictureFileDir.exists() && !pictureFileDir.mkdirs()) {

                Log.d("", "Can't create directory to save image.");
                Toast.makeText(MainActivity.this, "Can't create directory to save image.",
                        Toast.LENGTH_LONG).show();
                return;

            }
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyymmddhhmmss");
            String date = dateFormat.format(new Date());
            String photoFile = "Picture_" + date + ".jpg";

            String filename = pictureFileDir.getPath() + File.separator + photoFile;

            File pictureFile = new File(filename);

            try {
                FileOutputStream fos = new FileOutputStream(pictureFile);
                fos.write(data);
                fos.close();
                Toast.makeText(MainActivity.this, "New Image saved:" + photoFile,
                        Toast.LENGTH_LONG).show();
            } catch (Exception error) {
                Log.d("Constants.DEBUG_TAG", "File" + filename + "not saved: "
                        + error.getMessage());
                Toast.makeText(MainActivity.this, "Image could not be saved.",
                        Toast.LENGTH_LONG).show();
            }


          }

       }
    };

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

          takePhotoButton = (Button)findViewById(R.id.button_takephoto);      

          cameraObject = isCameraAvailiable();

          showCamera = new ShowCamera(this, cameraObject);
          preview = (FrameLayout) findViewById(R.id.camera_preview);
          preview.addView(showCamera);




        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                 cameraObject.takePicture(null, null, capturedIt);
            }
        }, 5000);

         cameraObject.stopPreview();    
          preview.removeView(showCamera);
        cameraObject.release();
        cameraObject = Camera.open(1);
         showCamera = new ShowCamera(MainActivity.this, cameraObject);  

          preview.addView(showCamera);

          Handler handlerFront = new Handler();
          handlerFront.postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub


                     cameraObject.takePicture(null, null, capturedIt);
                }
            }, 5000);    





       }
       private File getDir() {
        File sdDir = Environment
                .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        return new File(sdDir, "Front&BackCamera");
    }

       @Override
       public void onPause(){
           super.onPause();
           if (cameraObject != null) {
               cameraObject.stopPreview();
               cameraObject.release();
               cameraObject = null;
            }
//         FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
              preview.removeView(showCamera);
       }

       @Override
       public void onBackPressed() {
           if (cameraObject != null) {
               cameraObject.stopPreview();
               cameraObject.release();
               cameraObject = null;
            }
           finish();
           return;
       }

       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.activity_main, menu);
          return true;
       }
    }

ShowCamera.java

package com.example.camera1;

import java.io.IOException;

import android.content.Context;
import android.hardware.Camera;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class ShowCamera extends SurfaceView implements SurfaceHolder.Callback {

       private SurfaceHolder holdMe;
       private Camera theCamera;

       public ShowCamera(Context context,Camera camera) {
          super(context);
          theCamera = camera;
          holdMe = getHolder();
          holdMe.addCallback(this);
       }

       @Override
       public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
       }

       @Override
       public void surfaceCreated(SurfaceHolder holder) {
          try   {
              theCamera.setDisplayOrientation(90);
             theCamera.setPreviewDisplay(holder);
             theCamera.startPreview(); 
          } catch (IOException e) {
          }
       }

       @Override
       public void surfaceDestroyed(SurfaceHolder arg0) {
           this.getHolder().removeCallback(this);
           theCamera.stopPreview(); 
           theCamera.release();
       }

    }

LogCat输出

05-30 15:22:07.102: E/AndroidRuntime(7629): FATAL EXCEPTION: main
05-30 15:22:07.102: E/AndroidRuntime(7629): java.lang.RuntimeException: takePicture failed
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.hardware.Camera.native_takePicture(Native Method)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.hardware.Camera.takePicture(Camera.java:1233)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.hardware.Camera.takePicture(Camera.java:1178)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at com.example.camera1.MainActivity$2.run(MainActivity.java:176)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.os.Handler.handleCallback(Handler.java:615)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.os.Handler.dispatchMessage(Handler.java:92)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.os.Looper.loop(Looper.java:153)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at android.app.ActivityThread.main(ActivityThread.java:5086)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at java.lang.reflect.Method.invokeNative(Native Method)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at java.lang.reflect.Method.invoke(Method.java:511)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
05-30 15:22:07.102: E/AndroidRuntime(7629):     at dalvik.system.NativeStart.main(Native Method)

1 个答案:

答案 0 :(得分:1)

您可以通过移动

轻松重写代码
     cameraObject.stopPreview();    
      preview.removeView(showCamera);
    cameraObject.release();
    cameraObject = Camera.open(1);
     showCamera = new ShowCamera(MainActivity.this, cameraObject);  

      preview.addView(showCamera);

      Handler handlerFront = new Handler();
      handlerFront.postDelayed(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub


                 cameraObject.takePicture(null, null, capturedIt);
            }
        }, 5000);    

使用单独的方法,将其命名为MainActivity.takeSecondPictureAfterDelay()。现在,在完成处理第一张图片的所有工作后,不要从MainActivity.OnCeate()调用此方法,而是从onPictureTaken()调用此方法。

要做的重要更改:您需要一些机制来检查此方法是否仅被调用一次。例如。添加

private int picturesTaken = 0;

并在onPictureTaken() - 方法的最开头 - 添加

picturesTaken++;
if (picturesTaken >= 2) {
    return;
}

现在你可以进行一些清理,例如没有必要使用Handler来分隔。您可以为两张图片重复使用相同的处理程序,甚至可以使用showCamera.postDelayed()代替handlerXXX.postDelayed()