2012-03-12 21 views
9

Tôi đã tạo ứng dụng chụp ảnh khi bạn chạm vào bản xem trước. Tôi có thể chụp nhiều ảnh, nhưng đôi khi tôi chạm vào bản xem trước để chụp ảnh, không có tiếng màn trập và toàn bộ ứng dụng bị đóng băng. Hơn nữa, sau đó, nếu tôi cố gắng khởi chạy ứng dụng camera tích hợp, tôi nhận được thông báo rằng máy ảnh không thể sử dụng được.Máy ảnh Android - Đôi khi khi chụp ảnh, ứng dụng bị đóng băng và máy ảnh không thể sử dụng được

Tôi không biết lý do cho hành vi đó, nó xảy ra ngẫu nhiên và khi nó xảy ra tôi phải khởi động lại thiết bị (Samsung Galaxy S) để có thể sử dụng lại máy ảnh.

Trong DDM, sau sự sụp đổ của tôi có thể nhìn thấy dòng sau: keyDispatchingTimedOut

Đây là mã có liên quan: CameraActivity Class:

public class CameraActivity extends Activity { 
    private static final String TAG = "CameraDemo"; 
    Preview preview; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

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

    Log.d(TAG, "Camera Activity Created."); 

    } 
} 

Preview Class:

class Preview extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener { 
    private static final String TAG = "Preview"; 

    SurfaceHolder mHolder; 
    public Camera camera; 
    Context ctx; 
    boolean previewing = false; 

    Preview(Context context) { 
     super(context); 
     ctx = context; 
     // Install a SurfaceHolder.Callback so we get notified when the 
     // underlying surface is created and destroyed. 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 


    // Called once the holder is ready 
    public void surfaceCreated(SurfaceHolder holder) { 
     // The Surface has been created, acquire the camera and tell it where 
     // to draw. 
     camera = Camera.open(); 
    } 

    // Called when the holder is destroyed 
    public void surfaceDestroyed(SurfaceHolder holder) { 

     if (camera != null) { 
      camera.setPreviewCallback(null); 
      camera.stopPreview(); 
      camera.release(); 
      camera = null; 
     } 

     previewing = false; 
    } 

    // Called when holder has changed 
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 

     if(previewing){ 
      camera.stopPreview(); 
      previewing = false; 
     } 

     if (camera != null){ 
      try { 

       camera.setDisplayOrientation(90); 
       camera.setPreviewDisplay(holder); 
       camera.setPreviewCallback(new PreviewCallback() { 
        // Called for each frame previewed 
        public void onPreviewFrame(byte[] data, Camera camera) { 
         Log.d(TAG, "onPreviewFrame called at: " + System.currentTimeMillis()); 
         Preview.this.invalidate(); 
        } 
       }); 
       camera.startPreview(); 
       previewing = true; 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 

    public boolean onTouch(View v, MotionEvent event) { 
     camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
     return false; 
    } 


    // Called when shutter is opened 
    ShutterCallback shutterCallback = new ShutterCallback() { 
     public void onShutter() { 
      Log.d(TAG, "onShutter'd"); 
     } 
    }; 

    // Handles data for raw picture 
    PictureCallback rawCallback = new PictureCallback() { 
     public void onPictureTaken(byte[] data, Camera camera) { 
      Log.d(TAG, "onPictureTaken - raw"); 
     } 
    }; 

    // Handles data for jpeg picture 
    PictureCallback jpegCallback = new PictureCallback() { 

     public void onPictureTaken(byte[] data, Camera camera) { 
      FileOutputStream outStream = null; 
      try { 
       // Write to SD Card 
       outStream = new FileOutputStream(String.format("/sdcard/TVguide/Detection/detected.jpg", System.currentTimeMillis())); // <9> 
       outStream.write(data); 
       outStream.close(); 
       Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length); 
      } catch (FileNotFoundException e) { // <10> 
       //Toast.makeText(ctx, "Exception #2", Toast.LENGTH_LONG).show(); 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } finally {} 
      Log.d(TAG, "onPictureTaken - jpeg"); 
      Toast.makeText(ctx, "SAVED", Toast.LENGTH_SHORT).show(); 

      camera.startPreview(); 
     } 
    }; 

} 

Xin vui lòng giúp đỡ, tôi đang cố gắng một vài ngày để hiểu nơi mà vấn đề là không thành công

Eyal

+0

bất kỳ ai? Tôi thực sự bị mắc kẹt – Eyal

+0

cũng tôi đề nghị lưu hình ảnh vào thẻ sd được thực hiện trong một chủ đề nền, không phải chủ đề giao diện người dùng chính. – Paul

Trả lời

6

Tôi không biết những gì gây ra lỗi đó, nó sẽ thực sự giúp đỡ nếu bạn đăng sản lượng loggcat từ thời gian từ khi lỗi này xảy ra.

Nhưng, tôi có thể làm một số gusesses. Có vẻ như máy ảnh bị khóa (máy ảnh tích hợp không hoạt động). Nếu ứng dụng của bạn bị đóng, khóa máy ảnh có thể do lỗi xử lý lỗi trong máy ảnh Samsung HAL. Đặc biệt là trong các điện thoại cũ, như Galaxy S, họ không thực hiện công việc tốt nhất trong việc xử lý các cuộc gọi API không đúng hoặc không chuẩn.

Dưới đây là một số gợi ý về những gì có thể đã gây ra hành vi này:

  1. Bạn nên thêm một người bảo vệ để chụp ảnh. Ngay bây giờ, nếu bạn chạm vào màn hình và chụp ảnh, bạn có thể chạm vào màn hình một lần nữa, trước khi hình ảnh kết thúc chụp. Vì vậy, camera.takePicture() sẽ được gọi hai lần. Cái thứ hai sẽ thất bại. Đây là dự đoán tốt nhất của tôi.

    Thêm một số boolean isTakingPicture = false biến và sau đó:

    public boolean onTouch(View v, MotionEvent event) { 
        if (!isTakingPicture) { 
        camera.takePicture(shutterCallback, rawCallback, jpegCallback); 
        isTakingPicture = true; 
        } 
        return false; 
    } 
    ... 
    public void onPictureTaken(byte[] data, Camera camera) { 
        isTakingPicture = false; 
        ... 
    
  2. gì bạn sử dụng previewCallback cho? Tôi không làm bất cứ điều gì hữu ích ở đây. Xem trước gọi lại đôi khi đôi khi có thể gây ra một số cơn đau, mặc dù mã của bạn có vẻ tốt với tôi. Bạn có thể alwys cố gắng loại bỏ nó và kiểm tra xem điều đó có giúp ích gì không.

+0

Tuyệt vời! Giải pháp đầu tiên không giúp được gì, nhưng giải pháp thứ hai (remove previewCallback) giải quyết được vấn đề – Eyal

+0

Hmm, có thể gọi invalidate() trên SurfaceView được gán cho Camera là vấn đề. Tôi chưa bao giờ thử điều đó và tôi không thể tưởng tượng bất kỳ người đọc nào để làm điều đó. Tuy nhiên, tôi nghĩ bạn nên áp dụng giải pháp đầu tiên, để ngăn chặn các lỗi tiềm ẩn. –

8

Tôi chỉ gặp sự cố này khi thử nghiệm ứng dụng của mình trên Samsung Galaxy SII. Bạn chỉ cần xóa cuộc gọi lại xem trước trước khi chụp ảnh:

mCamera.setPreviewCallback(null); 
mCamera.takePicture(null, null, mPictureCallback); 
+1

Trên HTC Sensation, ứng dụng máy ảnh tùy chỉnh của tôi, hiển thị bản xem trước trên không gian toàn màn hình. Khi người dùng chạm vào màn hình, tiêu điểm được gọi. Khi tiêu điểm hoàn thành và thành công, tôi gọi mCamera.takePicture. Đôi khi nó hoạt động, và tôi nhận được gọi lại để lưu dữ liệu JPG, lần khác nó chỉ nằm trong takePicture, mà không có thời gian chờ cũng như bất kỳ thông báo gỡ lỗi nào. Điều này là rất khó chịu, phải khởi động lại điện thoại mọi lúc, và không biết vấn đề là gì. SettingsPreviewCallback to null không giúp ích gì. Bất kỳ ý tưởng nào khác? – radhoo

2

Tôi gặp sự cố tương tự được báo cáo tại đây. Trên LG p705 và Samsung Galaxy Trend, sau khi chụp ảnh, bản xem trước bị đóng băng và máy ảnh không còn sử dụng được nữa cho đến khi điện thoại được khởi động lại. Tuy nhiên, trên Galaxy S3, bản xem trước tiếp tục hiển thị đúng ngay cả sau khi chụp nhiều ảnh.

Trong khi gỡ lỗi, tôi nhận thấy rằng lớp người nghe có liên quan đã nhận được nhiều cuộc gọi khi nhấn nút camera để chụp ảnh. Tôi không chắc chắn lý do tại sao nó được gọi hai lần, mặc dù nút chỉ được nhấp một lần. Trong mọi trường hợp, nhờ đề xuất của Tomasz về việc sử dụng biến boolean, cuộc gọi thứ hai bỏ qua việc chụp ảnh trong khi lần thử đầu tiên đang diễn ra. Và cảm ơn Eyal vì câu hỏi này. :)

Các vấn đề liên quan