我正在更新使用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手機上失敗。不能讓它顯示圖像預覽,它看起來像相機甚至沒有打開。有什麼建議麼?