在 Android 上使用相机 API 时出现问题

发布于 2024-11-04 19:30:09 字数 5149 浏览 0 评论 0原文

我正在尝试使用 Android 相机 API。视频预览效果很好。我有一个用于拍照的按钮实例,然后将其存储在 SDCARD 上。有时它工作得很好,有时则不然:按下按钮后,视频预览冻结,然后什么也没有发生,就在我收到弹出窗口“应用程序不回复等”之后。当这种情况发生时(大约 1 次或 3 次),我在 logcat 中没有错误消息。之后我必须重新启动手机,因为相机不再可用。这是我的代码:

  public class Test_cam extends Activity implements PictureCallback,ShutterCallback,OnClickListener{
     private static final String TAG = "CameraDemo";
      Test_cam_preview preview; //  This object will create the Camera object and return it to the CameraDemo activity. 
      Button buttonClick; 
      public boolean onProgress = false;

      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.camera);

        preview = new Test_cam_preview(this); 
        ((FrameLayout) findViewById(R.id.preview)).addView(preview); 

        buttonClick = (Button) findViewById(R.id.buttonClick);
        buttonClick.setOnClickListener(this);      
        Log.d(TAG, "onCreate'd");
      }

      public void launch_scanpic(){
              Intent intent = new Intent(Test_cam.this,Test_cam_scanpic.class);
              startActivity(intent);
      }



            @Override
            public void onClick(View v) { 
                     if(!onProgress)
                     {
                            onProgress = true;
                    preview.camera.takePicture(Test_cam.this, null, Test_cam.this); //bien mettre null car raw callback renvoit tjrs null!
                    //on lance scanclothe activity
                     }
     }


      @Override
  public void onShutter() {
          Log.d(getClass().getSimpleName(), "get pic...");               
  }



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

          FileOutputStream outStream = null;
          try {
            if (data==null)
            {
                    Log.e(TAG,"data is null !!!!!!!");
            }
            else
            {
                    // Write to SD Card
                    outStream = new FileOutputStream("/sdcard/test.jpg"); 
                    outStream.write(data);
                    Log.e(TAG, "onPictureTaken - wrote bytes: " + data.length);
                     outStream.close();
            }



          } catch (FileNotFoundException e) { 
              Log.e(getClass().getSimpleName(), "file not found",e);
            e.printStackTrace();
          } catch (IOException e) {
              Log.e(getClass().getSimpleName(), "Saving picture error",e);
            e.printStackTrace();
          } 

          Log.e(TAG, "onPictureTaken - jpeg");
          SystemClock.sleep(2000);
          onProgress=false;
          launch_scanpic();
      }

}

当应用程序工作时,我显然得到了正确的 logcat:

05-03 18:22:31.053: INFO/SecCamera(76): int android::SecCamera::endSnapshot() :
05-03 18:22:31.053: INFO/SecCamera(76): munmap():virt. addr 0x41ddb000 size = 4261248
05-03 18:22:31.061: DEBUG/dalvikvm(700): GC_FOR_MALLOC freed 506K, 57% free 2779K/6407K,   external 1625K/2137K, paused 15ms
05-03 18:22:31.061: INFO/dalvikvm-heap(700): Grow heap (frag case) to 7.734MB for   1114262-byte allocation
05-03 18:22:31.088: DEBUG/dalvikvm(700): GC_FOR_MALLOC freed 0K, 49% free 3867K/7559K, external 1625K/2137K, paused 13ms
05-03 18:22:31.127: DEBUG/dalvikvm(700): GC_CONCURRENT freed <1K, 49% free 3867K/7559K, external 1625K/2137K, paused 2ms+2ms
05-03 18:22:32.022: ERROR/CameraDemo(700): onPictureTaken - wrote bytes: 1114246
05-03 18:22:32.022: ERROR/CameraDemo(700): onPictureTaken - jpeg

我尝试添加计时器为应用程序留出时间来存储图片,但没有效果。我正在 Google Nexus S (2.3.4) 上进行测试。任何人都可以帮我解决这个问题吗?

这是我的代码的预览部分:

class Test_cam_preview extends SurfaceView implements SurfaceHolder.Callback{ 
  private static final String TAG = "Preview";
  SurfaceHolder mHolder; 
  public Camera camera; 

  Test_cam_preview(Context context){
    super(context);
    mHolder = getHolder(); 
    mHolder.addCallback(this);  
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}

  public void surfaceCreated(SurfaceHolder holder){
    camera = Camera.open();
    Camera.Parameters params = camera.getParameters();
    params.setPictureFormat(PixelFormat.JPEG);
    params.set("flash-mode", "auto");
    camera.setParameters(params);     
    try {
      camera.setPreviewDisplay(holder);  

      camera.setPreviewCallback(new PreviewCallback(){ 
        public void onPreviewFrame(byte[] data, Camera camera){ 
          Test_cam_preview.this.invalidate();  
        }
      });
    } catch (IOException e) {
      e.printStackTrace();
      camera.release(); 
      camera = null;
    }}
  public void surfaceDestroyed(SurfaceHolder holder){
      if(camera != null){
          camera.stopPreview();
          camera.setPreviewCallback(null);
          camera.release(); //it is important that this is done so camera is     
          camera = null;
      }
  }
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    camera.startPreview();
  }}

提前致谢。

约翰

I am trying to use the android camera API. The video preview works great. I have a button instance used for taking the picture and then store it on an SDCARD. Sometimes it works perfectly, sometimes not: just after pushing the button, the video preview freezes then nothing happens and just after I get the popup "application does not reply etc.". When this case happens (around 1 time on 3) I have no error message in the logcat. After that I have to reboot my phone since the camera is no longer available. Here is my code:

  public class Test_cam extends Activity implements PictureCallback,ShutterCallback,OnClickListener{
     private static final String TAG = "CameraDemo";
      Test_cam_preview preview; //  This object will create the Camera object and return it to the CameraDemo activity. 
      Button buttonClick; 
      public boolean onProgress = false;

      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.camera);

        preview = new Test_cam_preview(this); 
        ((FrameLayout) findViewById(R.id.preview)).addView(preview); 

        buttonClick = (Button) findViewById(R.id.buttonClick);
        buttonClick.setOnClickListener(this);      
        Log.d(TAG, "onCreate'd");
      }

      public void launch_scanpic(){
              Intent intent = new Intent(Test_cam.this,Test_cam_scanpic.class);
              startActivity(intent);
      }



            @Override
            public void onClick(View v) { 
                     if(!onProgress)
                     {
                            onProgress = true;
                    preview.camera.takePicture(Test_cam.this, null, Test_cam.this); //bien mettre null car raw callback renvoit tjrs null!
                    //on lance scanclothe activity
                     }
     }


      @Override
  public void onShutter() {
          Log.d(getClass().getSimpleName(), "get pic...");               
  }



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

          FileOutputStream outStream = null;
          try {
            if (data==null)
            {
                    Log.e(TAG,"data is null !!!!!!!");
            }
            else
            {
                    // Write to SD Card
                    outStream = new FileOutputStream("/sdcard/test.jpg"); 
                    outStream.write(data);
                    Log.e(TAG, "onPictureTaken - wrote bytes: " + data.length);
                     outStream.close();
            }



          } catch (FileNotFoundException e) { 
              Log.e(getClass().getSimpleName(), "file not found",e);
            e.printStackTrace();
          } catch (IOException e) {
              Log.e(getClass().getSimpleName(), "Saving picture error",e);
            e.printStackTrace();
          } 

          Log.e(TAG, "onPictureTaken - jpeg");
          SystemClock.sleep(2000);
          onProgress=false;
          launch_scanpic();
      }

}

When the application is working, I obviously get correct logcat:

05-03 18:22:31.053: INFO/SecCamera(76): int android::SecCamera::endSnapshot() :
05-03 18:22:31.053: INFO/SecCamera(76): munmap():virt. addr 0x41ddb000 size = 4261248
05-03 18:22:31.061: DEBUG/dalvikvm(700): GC_FOR_MALLOC freed 506K, 57% free 2779K/6407K,   external 1625K/2137K, paused 15ms
05-03 18:22:31.061: INFO/dalvikvm-heap(700): Grow heap (frag case) to 7.734MB for   1114262-byte allocation
05-03 18:22:31.088: DEBUG/dalvikvm(700): GC_FOR_MALLOC freed 0K, 49% free 3867K/7559K, external 1625K/2137K, paused 13ms
05-03 18:22:31.127: DEBUG/dalvikvm(700): GC_CONCURRENT freed <1K, 49% free 3867K/7559K, external 1625K/2137K, paused 2ms+2ms
05-03 18:22:32.022: ERROR/CameraDemo(700): onPictureTaken - wrote bytes: 1114246
05-03 18:22:32.022: ERROR/CameraDemo(700): onPictureTaken - jpeg

I tried to add timer to leave time for the application to store the picture, but no effect. I am testing on Google Nexus S (2.3.4). Anyone could help me to fix this issue?

Here is the preview part of my code:

class Test_cam_preview extends SurfaceView implements SurfaceHolder.Callback{ 
  private static final String TAG = "Preview";
  SurfaceHolder mHolder; 
  public Camera camera; 

  Test_cam_preview(Context context){
    super(context);
    mHolder = getHolder(); 
    mHolder.addCallback(this);  
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}

  public void surfaceCreated(SurfaceHolder holder){
    camera = Camera.open();
    Camera.Parameters params = camera.getParameters();
    params.setPictureFormat(PixelFormat.JPEG);
    params.set("flash-mode", "auto");
    camera.setParameters(params);     
    try {
      camera.setPreviewDisplay(holder);  

      camera.setPreviewCallback(new PreviewCallback(){ 
        public void onPreviewFrame(byte[] data, Camera camera){ 
          Test_cam_preview.this.invalidate();  
        }
      });
    } catch (IOException e) {
      e.printStackTrace();
      camera.release(); 
      camera = null;
    }}
  public void surfaceDestroyed(SurfaceHolder holder){
      if(camera != null){
          camera.stopPreview();
          camera.setPreviewCallback(null);
          camera.release(); //it is important that this is done so camera is     
          camera = null;
      }
  }
  public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    camera.startPreview();
  }}

Thanks in advance.

John

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

随心而道 2024-11-11 19:30:09

我和你的情况几乎一样。

它在 onPictureTaken 中崩溃,因为拍照的 JNI 线程尚未完成,并且 libcamera/SecCameraHWInterface.cpp 中的 mCaptureInProgress 变量尚未设置为 false。

要解决您的问题,您必须删除“SystemClock.sleep(2000);”而是向另一个线程发送一条延迟消息,该线程将在 takePicture 线程终止后启动您的 Intent。

我想这一定是 Nexus S 相机本机代码中的错误,因为我在几部 Android 手机上尝试了我的应用程序,除了 Nexus S 之外,每次都运行良好:(

I'm almost in the same case as you.

It crash in onPictureTaken because the JNI thread which takes a picture is not yet finished and mCaptureInProgress variable in libcamera/SecCameraHWInterface.cpp is not yet set to false.

To fix your problem, you'll have to remove your "SystemClock.sleep(2000);" and instead send a delayed message to another thread which will launch your Intent AFTER the takePicture thread be terminated.

I suppose it must be a bug in Nexus S camera native code because I tried my application on several Android phones and it worked fine everytime excepted on Nexus S :(

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文