2016-08-02 26 views
0

Ich aktualisiere eine App, die einen QR-Reader verwendet, um den Benutzer auf bestimmte Websites zu protokollieren. Diese App wurde ursprünglich vor zwei oder drei Jahren geschrieben und ich arbeite daran, sie mit neueren APIs wie Marshmallow kompatibel zu machen. Bis jetzt funktioniert es gut auf allen Geräten, die ich mit Ausnahme von Samsung-Geräten getestet habe. Wenn ich versuche, die Scanneraktivität zu starten, ist die Anzeige leer und es wird keine Bildvorschau angezeigt, und die Kamera reagiert nicht, wenn ich zum Fokussieren auf den Bildschirm tippe. Während ich tippe, zeigt das Logcat diese zwei Zeilen an.Samsung Handys laufen Marshmallow wird nicht angezeigt QR Reader

Dieses Problem tritt nur bei Samsung-Geräten auf, die Marshmallow verwenden Ich habe ein Samsung-Handy mit Lollipop getestet und die App hat keine Probleme.

Die Klasse, die den QR-Scan verarbeitet.

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; 
     } 
} 

} 

Die Kamera Vorschauklasse.

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()); 
     } 
    } 
} 

Auch der Code, der den Benutzer nach Berechtigungen fragt, einschließlich der Kamera-Erlaubnis.

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); 
     } 
    } 
} 

Jeder Einblick in dieses Problem würde geschätzt werden. Ich würde gerne wissen, ob dies mit Berechtigungen zusammenhängt oder ob etwas im QR-Code fehlt. Ich bin ziemlich neu in der Android-Entwicklung und habe dieses Problem seit einigen Tagen behoben.

(EDIT) Immer noch auf der Suche nach Antworten. Ich wechselte zur neuen camera2-API (da die Samsung-Entwickler-Seite zeigte, dass sie diese API nutzten) und habe immer noch das exakt gleiche Problem. Funktioniert gut auf Samsung-Tablets, schlägt aber auf dem Galaxy S7 Telefon fehl. Es wird nicht angezeigt, dass eine Bildvorschau angezeigt wird und es sieht so aus, als ob die Kamera nicht eingeschaltet wird. Irgendwelche Vorschläge?

Antwort

1

Das Problem wurde in QRCodeFragment gefunden. Ich dachte, das Problem könnte mit dem veralteten android.hardware.Camera-Paket zusammenhängen, und ich habe eine neue App mit der camera2-API erstellt. Das Problem bestand jedoch weiterhin. Dies führte mich zu der Annahme, dass das Problem nicht mit dem Kamera-Code zusammenhing. Ich fand, dass durch diese Codezeile

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

zu

private RelativeLayout layout; 

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

mein Problem mit der Kamera Vorschau gelöst werden nicht angezeigt. Die App funktioniert jetzt auf allen Samsung-Geräten einwandfrei. Ich fand die Antwort während des Studiums dieses GitHub-Projekts:

https://github.com/Gutyn/camera2QRcodeReader