2016-08-02 26 views
0

我正在更新使用QR閱讀器將應用程序登錄到某些網站的應用程序。這個應用程序最初是在兩三年前編寫的,我一直在努力使其與新版API如棉花糖兼容。到目前爲止,它在我測試過的所有設備上都能正常工作,除了三星設備。當我嘗試啓動掃描儀活動時,顯示屏空白,無圖像預覽,當我點擊屏幕進行對焦時,相機不響應。當我點擊時,logcat顯示這兩行。運行棉花糖的三星電話不會顯示QR閱讀器

ViewRootImpl: ViewPostImeInputStage processPointer 0 
ViewRootImpl: ViewPostImeInputStage processPointer 1 

此問題僅發生在使用棉花糖的三星設備上。我測試了一款運行棒棒糖的三星手機,該應用沒有問題。

處理QR掃描的類。

public class QRCodeFragment extends Fragment { 

private Camera m_Camera; 
private CameraPreview m_Preview; 
private Handler m_autoFocusHandler; 
private String m_loginAttemptUdid = ""; 
private static Context m_context = null; 
ImageScanner m_scanner; 
private boolean m_shouldAuthenticate = false; 
private boolean previewing = true; 

static 
{ 
    System.loadLibrary("iconv"); 
} 

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){ 

    View rootView = inflater.inflate(R.layout.activity_qr_code_scan, parent, false); 
    getActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    m_context = this.getActivity(); 
    m_shouldAuthenticate = false; 
    ViewFactory.getInstance(m_context).scaleView((RelativeLayout) rootView.findViewById(R.id.QRRelativeLayout1)); 
    ImageView exitButton = (ImageView) rootView.findViewById(R.id.imageView3); 

    exitButton.setOnClickListener(new View.OnClickListener() 
    { 
     public void onClick(View v) 
     { 
      ((HomeActivity) getActivity()).selectItem(0); 
     } 
    }); 

    m_autoFocusHandler = new Handler(); 
    m_Camera = getCameraInstance(); 

    /* Instance barcode scanner */ 
    m_scanner = new ImageScanner(); 
    m_scanner.setConfig(0, Config.X_DENSITY, 3); 
    m_scanner.setConfig(0, Config.Y_DENSITY, 3); 

    if (m_Camera != null) 
    { 
     m_Preview = new CameraPreview(getActivity(), m_Camera, previewCb, autoFocusCB); 
     FrameLayout preview = (FrameLayout) rootView.findViewById(R.id.cameraPreview); 
     preview.addView(m_Preview); 
     m_Camera.setPreviewCallback(previewCb); 
     Parameters params = m_Camera.getParameters(); 
     m_Camera.setParameters(params); 
     m_Camera.startPreview(); 
     previewing = true; 
     m_Camera.autoFocus(autoFocusCB); 
    } 
    else 
    { 
     AlertDialog.Builder builder1 = new AlertDialog.Builder(m_context); 
     builder1.setTitle("Unexpected Error"); 
     builder1.setMessage("We are sorry but there is some unexpected Error. Plese try again later."); 
     builder1.setCancelable(true); 
     builder1.setPositiveButton("Ok", new DialogInterface.OnClickListener() 
     { 
      public void onClick(DialogInterface dialog, int id) 
      { 
       ((HomeActivity) getActivity()).selectItem(0); 
      } 
     }); 
     AlertDialog alert11 = builder1.create(); 
     alert11.show(); 
     alert11.setCancelable(false); 

    } 


    return rootView; 

} 

/** A safe way to get an instance of the Camera object. */ 
public static Camera getCameraInstance() 
{ 
    Camera c = null; 
    try 
    { 
     c = Camera.open(); 
    } 
    catch (Exception e) 
    { 
     if (!TWAppInfoManager.isProductionBuild()) 
      Log.e("CAMERAEXCEPTION", e.getMessage()); 
    } 
    return c; 
} 

private void releaseCamera() 
{ 
    if (m_Camera != null) 
    { 
     previewing = false; 
     m_Camera.setPreviewCallback(null); 
     m_Camera.stopPreview(); 
     // mCamera = null; 
    } 
} 

private Runnable doAutoFocus = new Runnable() 
{ 
    public void run() 
    { 
     if (previewing) 
     { 
      try 
      { 
       m_Camera.autoFocus(autoFocusCB); 
      } 
      catch (Exception e) 
      { 
      } 

     } 

    } 
}; 

PreviewCallback previewCb = new PreviewCallback() 
{ 
    public void onPreviewFrame(byte[] data, Camera camera) 
    { 
     //process data 
    } 
}; 

// Mimic continuous auto-focusing 
AutoFocusCallback autoFocusCB = new AutoFocusCallback() 
{ 
    public void onAutoFocus(boolean success, Camera camera) 
    { 
     m_autoFocusHandler.postDelayed(doAutoFocus, 1000); 
    } 
}; 


@Override 
public void onStop() { 
     super.onStop(); 
     if (m_Camera != null) 
     { 
      m_Camera.setPreviewCallback(null); 
      m_Camera.release(); 
      m_Camera = null; 
      m_Preview = null; 
     } 
} 

} 

相機預覽類。

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback 
{ 
    private SurfaceHolder mHolder; 
    private Camera mCamera; 
    private PreviewCallback previewCallback; 
    private AutoFocusCallback autoFocusCallback; 

@SuppressWarnings("deprecation") 
public CameraPreview(Context context, Camera camera, PreviewCallback previewCb, AutoFocusCallback autoFocusCb) 
{ 
    super(context); 
    mCamera = camera; 
    previewCallback = previewCb; 
    autoFocusCallback = autoFocusCb; 

    /* 
    * Set camera to continuous focus if supported, otherwise use software 
    * auto-focus. Only works for API level >=9. 
    */ 
    /* 
    * Camera.Parameters parameters = camera.getParameters(); for (String f 
    * : parameters.getSupportedFocusModes()) { if (f == 
    * Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) { 
    * mCamera.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE); 
    * autoFocusCallback = null; break; } } 
    */ 

    // Install a SurfaceHolder.Callback so we get notified when the 
    // underlying surface is created and destroyed. 
    mHolder = getHolder(); 
    mHolder.addCallback(this); 

    // deprecated setting, but required on Android versions prior to 3.0 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
} 

public void surfaceCreated(SurfaceHolder holder) 
{ 
    // The Surface has been created, now tell the camera where to draw the 
    // preview. 
    try 
    { 
     mCamera.setPreviewDisplay(holder); 
    } 
    catch (Exception e) 
    { 
     if (!TWAppInfoManager.isProductionBuild()) 
      Log.d("DBG", "Error setting camera preview: " + e.getMessage()); 
    } 
} 

public void surfaceDestroyed(SurfaceHolder holder) 
{ 
    // Camera preview released in activity 
} 

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
{ 
    /* 
    * If your preview can change or rotate, take care of those events here. 
    * Make sure to stop the preview before resizing or reformatting it. 
    */ 
    if (mHolder.getSurface() == null) 
    { 
     // preview surface does not exist 
     return; 
    } 

    // stop preview before making changes 
    try 
    { 
     mCamera.stopPreview(); 
    } 
    catch (Exception e) 
    { 
     // ignore: tried to stop a non-existent preview 
    } 

    try 
    { 
     // Hard code camera surface rotation 90 degs to match Activity view 
     // in portrait 
     mCamera.setDisplayOrientation(90); 

     mCamera.setPreviewDisplay(mHolder); 
     mCamera.setPreviewCallback(previewCallback); 
     mCamera.startPreview(); 
     mCamera.autoFocus(autoFocusCallback); 
    } 
    catch (Exception e) 
    { 
     if (!TWAppInfoManager.isProductionBuild()) 
      Log.d("DBG", "Error starting camera preview: " + e.getMessage()); 
     } 
    } 
} 

此外代碼,要求用戶的權限,包括相機權限。

private void getPermissions() { 
    if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_CONTACTS}, 
       PERMISSIONS_REQUEST_READ_CONTACTS); 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.READ_CONTACTS)) { 
      // Show an explanation to the user 
     } 
    } 
    if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 
       PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)) { 
      // Show an explanation to the user 
     } 
    } 
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 
       PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION); 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) { 
      // Show an explanation to the user 
     } 
    } 
    if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 
     ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA}, 
       PERMISSIONS_REQUEST_CAMERA); 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.CAMERA)) { 
      // Show an explanation to the user 
     } 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { 
    switch (requestCode) { 
     case PERMISSIONS_REQUEST_READ_CONTACTS: 
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       getPermissions(); 
      } else { 
       Toast.makeText(this, "READ_CONTACTS Denied", Toast.LENGTH_SHORT) 
         .show(); 
      } 
     case PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: 
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       getPermissions(); 
      } else { 
       Toast.makeText(this, "READ_EXTERNAL_STORAGE Denied", Toast.LENGTH_SHORT) 
         .show(); 
      } 
     case PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION: 
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       getPermissions(); 
      } else { 
       Toast.makeText(this, "ACCESS_COARSE_LOCATION Denied", Toast.LENGTH_SHORT) 
         .show(); 
      } 
     case PERMISSIONS_REQUEST_CAMERA: 
      if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
       getPermissions(); 
      } else { 
       Toast.makeText(this, "CAMERA Denied", Toast.LENGTH_SHORT) 
         .show(); 
      } 
     default: 
      super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     } 
    } 
} 

任何有關這個問題的意見,將不勝感激。我想知道這是否與權限相關,或者QR閱讀器代碼中是否缺少某些內容。我對android開發相當陌生,幾天來我一直在解決這個問題。

(編輯)仍在尋找答案。我切換到新的camera2 API(因爲三星開發者頁面顯示他們正在使用該API)並且仍然有完全相同的問題。在三星平板電腦上運行良好,但在Galaxy s7手機上失敗。不能讓它顯示圖像預覽,它看起來像相機甚至沒有打開。有什麼建議麼?

回答

1

該問題位於QRCodeFragment。我認爲這個問題可能與已棄用的android.hardware.Camera軟件包有關,並且我使用camera2 API構建了一個新應用程序。但是,問題依然存在。這讓我相信這個問題根本與攝像頭代碼無關。我發現,通過改變這行代碼

ViewFactory.getInstance(m_context).scaleView((RelativeLayout) rootView.findViewById(R.id.QRRelativeLayout1)); 

private RelativeLayout layout; 

layout = (RelativeLayout) rootView.findViewById(R.id.QRRelativeLayout1); 

解決我的問題與相機預覽不顯示。該應用現在可以在所有三星設備上正常工作。我在研究這個GitHub項目時找到了答案:

https://github.com/Gutyn/camera2QRcodeReader