2016-09-22 25 views
7

Tôi đang tạo ứng dụng có trình quét qr bằng cách sử dụng api tầm nhìn của google. Tôi gặp sự cố khi dừng máy ảnh sau khi đọc mã qr. dòng chảy là MainActivity -> QrActivity khi mã qr nhận được một phát hiện ứng dụng sẽ trở lại hoạt động chính.Android cameraSource.stop() khiến ứng dụng đóng băng

Nếu tôi không gọi cameraSource.release(), nó hoạt động tốt nhưng thiết bị nóng lên rất nhiều và có tác động đáng kể đến việc xả pin. tuy nhiên nếu tôi phát hành nguồn camera, mainActivity sẽ không phản hồi và ứng dụng sẽ bị lỗi.

Tại sao nó không phản hồi? và đâu là nơi chính xác để phát hành nguồn camera?

QrActivity

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_qr); 
    cancelBtn = (Button) findViewById(R.id.cancel_button); 
    cancelBtn.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      onBackPressed(); 
     } 
    }); 

    new QrReader(this); 
} 

QrReader Lớp

public class QrReader { 

    private static final String TAG = "QrReader"; 

    private SurfaceView cameraView; 
    private TextView barcodeInfo; 
    private BarcodeDetector barcodeDetector; 
    private CameraSource cameraSource; 
    private Activity mActivity; 
    private AccessPointCredentials barCodeData; 

    public QrReader(Activity activity) { 
     this.mActivity = activity; 

     cameraView = (SurfaceView) mActivity.findViewById(R.id.camera_view); 
     barcodeInfo = (TextView) mActivity.findViewById(R.id.code_info); 

     barcodeDetector = 
       new BarcodeDetector.Builder(mActivity) 
         .setBarcodeFormats(Barcode.QR_CODE) 
         .build(); 

     cameraSource = new CameraSource 
       .Builder(mActivity, barcodeDetector) 
       .setAutoFocusEnabled(true) 
       .build(); 

     cameraView.getHolder().addCallback(new SurfaceHolder.Callback() { 

      @Override 
      public void surfaceCreated(SurfaceHolder holder) { 

       cameraSource = new CameraSource 
         .Builder(mActivity, barcodeDetector) 
         .setAutoFocusEnabled(true) 
         .setFacing(0) 
         .build(); 
       try {     
        cameraSource.start(cameraView.getHolder()); 

       } catch (Exception ioe) { 
        ioe.printStackTrace(); 
       } 
      } 

      @Override 
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
      } 

      @Override 
      public void surfaceDestroyed(SurfaceHolder holder) { 
        // Log.i(TAG, "surfaceDestroyed: stopping camera Source"); 

        // cameraSource.release(); 
      } 
     }); 

     barcodeDetector.setProcessor(new Detector.Processor<Barcode>() { 
      @Override 
      public void release() { 
       Log.i(TAG, "release: "); 
      } 

      @Override 
      public void receiveDetections(Detector.Detections<Barcode> detections) { 
       final SparseArray<Barcode> barCodes = detections.getDetectedItems(); 

       if (barCodes.size() != 0) { 

        Log.i(TAG, "received a Barcode"); 
        barcodeInfo.post(new Runnable() { // Use the post method of the TextView 
         public void run() { 
          barcodeInfo.setText(barCodes.valueAt(0).displayValue); 

         } 
        }); 
        Gson g = new Gson(); 
        try { 
         barCodeData = g.fromJson(barCodes.valueAt(0).rawValue, AccessPointCredentials.class); 
        } catch (Exception e) { 
         barCodeData = new AccessPointCredentials(); 
         barCodeData.setSsid(barCodes.valueAt(0).rawValue); 
         barCodeData.setPass(null); 
         e.printStackTrace(); 
        } 

        connectToWifi(barCodeData); 

        // CameraSource.release causes app to freeze 

        // cameraSource.release(); 
       } 
      } 
     }); 
    } 

    private void connectToWifi(final AccessPointCredentials credentials) { 

       //wificonnect code 

    } 

} 
+1

Không chắc, nhưng lưu ý rằng có một bản sao mã nguồn mở của CameraSource mà bạn có thể thử nếu bạn muốn thâm nhập vào này hơn nữa: https://github.com/googlesamples/android-vision /blob/master/visionSamples/barcode-reader/app/src/main/java/com/google/android/gms/samples/vision/barcodereader/ui/camera/CameraSource.java#L322 – pm0733464

+0

Tôi đã thử gọi 'cameraSoutce. release() 'ở hai nơi nó được nhận xét (trong' surfaceDestroyed() 'và' receiveDetections() ') – Lonergan6275

Trả lời

7

nó được 3 tháng nhưng tôi chỉ cần stumbled trên cùng một vấn đề và tìm hiểu. Các mã bên trong phương pháp receiveDetections đang chạy trên một sợi khác nhau vì vậy nếu bạn muốn làm một cái gì đó mà cần thread ui bạn cần phải đăng nó từ một handler:

Handler handler = new Handler(Looper.getMainLooper()); 
handler.post(new Runnable() { 
    @Override 
    public void run() { 
     cameraSource.release(); 
    } 
}); 
+0

Cảm ơn câu trả lời tôi sẽ kiểm tra nó khi tôi có cơ hội. – Lonergan6275

+1

Sau những giờ làm việc bực mình, tôi thực sự có thể xác nhận đó là vấn đề về luồng. Với ursing ^^ mã này hoặc sử dụng '' 'view.post (new Runnable() {cameraSource.release()})' '' bạn có thể sửa nó – Spidfire

0

heyo, bất kỳ bản cập nhật? Tôi vừa gặp phải một vấn đề tương tự, tôi cố gắng giải quyết các phương pháp release, nhưng không hoạt động. Tôi chỉ tìm thấy một giải pháp sửa chữa/giải quyết nhanh chóng. Muốn có một giải pháp thanh lịch.

Trường hợp của tôi là, người dùng ứng dụng có thể quét mã QR và sau đó thực hiện thanh toán.

MainActivity

  1. Drawer menu (https://github.com/mikepenz/MaterialDrawer)
  2. Fragment container (mảnh thay đổi khi người dùng nhấp vào menu ngăn kéo)

Tất cả các quan điểm khác của tôi là Fragment/ListFragment

ScanMainController

  1. BarcodeDetector
  2. CameraSource
  3. SurfaceView

kịch bản của tôi là như thế này, một khi tôi quét mã QR, tôi đẩy đến một trang khác để sử dụng để thực hiện thanh toán. Nhưng tôi cần tìm cách dừng máy quét QRCode vì tôi chỉ muốn receiveDetections được gọi một lần duy nhất. Trong iOS, tôi đã sử dụng để đặt delegate to nil hoạt động tương tự như cameraSource.release(); trong Android. Nhưng sau đó, tôi không thể tìm thấy một vị trí thích hợp để gọi phương thức release().

Nếu tôi chủ động gọi release(), thì khi sử dụng muốn điều hướng đến trang khác thông qua việc nhấp vào menu ngăn kéo, cam kết FragmentTransaction của tôi sẽ bị toàn bộ ứng dụng đóng băng. Và sau đó hệ thống Android sẽ bật lên cho tôi biết ứng dụng không phản hồi.

Tôi đã khắc phục nhanh bằng cách thêm cờ 'boolean' bên trong 'receiveDetections' để đảm bảo tôi chỉ đẩy chế độ xem một lần. Nó hoạt động. Nhưng tôi đang tìm kiếm một cách thanh lịch hơn và cách 'thích hợp' để làm điều đó.

Cảm ơn

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