ZXingScannerFragment.StartScanning()在首次启动应用程序时显示黑屏

时间:2019-02-03 16:34:45

标签: c# android xamarin xamarin.android zxing

我有以下Fragment,可通过单击选项卡进行调用:

public class HomeFragment : Fragment
{
    private CustomZXingFragment scanFragment;

    public override void OnStart() => base.OnStart();

    public override void OnCreate(Bundle savedInstanceState) => base.OnCreate(savedInstanceState);

    public override void OnResume()
    {
        base.OnResume();

        var needsPermissionRequest = ZXing.Net.Mobile.Android.PermissionsHandler.NeedsPermissionRequest(Model.Model.MainActivityContext);
        if (needsPermissionRequest)
            ZXing.Net.Mobile.Android.PermissionsHandler.RequestPermissionsAsync(Activity)
                .ContinueWith((b) => ShowScanFragment());
        else
            ShowScanFragment();
    }

    public override void OnViewCreated(View view, Bundle savedInstanceState) => base.OnViewCreated(view, savedInstanceState);

    private void ShowScanFragment()
    {
        MobileBarcodeScanner.Initialize(Activity.Application);

        if (scanFragment == null)
        {
            scanFragment = new CustomZXingFragment();
            FragmentManager.BeginTransaction().Replace(Resource.Id.container, scanFragment).Commit();
        }

        Scan();
    }

    private void Scan()
    {
        var opts = new MobileBarcodeScanningOptions
        {

            PossibleFormats = new List<BarcodeFormat> {
                BarcodeFormat.QR_CODE,
            },
            UseNativeScanning = true,
            TryHarder = true,
        };

        scanFragment.StartScanning(scanFragment.DoneScanning, opts);
    }

我有以下ZXing fragment

public class CustomZXingFragment : ZXingScannerFragment
{
    public override View OnCreateView(LayoutInflater layoutInflater, ViewGroup viewGroup, Bundle bundle)
    {
        var view = base.OnCreateView(layoutInflater, viewGroup, bundle);
        var activity = (MainActivity)Model.Model.MainActivityContext;
        return view;
    }

    public void DoneScanning(Result scannedText)
    {
        // ...
    }
}

由于某种原因,只有在您第一次启动该应用程序时,相机才无法启动。它显示默认的红色水平线,但背景仅是黑色。如果我重新启动应用程序,它就可以正常工作。我从第一次启动(显示黑色背景)中获取了调试输出:

02-03 16:29:01.627 D/ZXing.Net.Mobile(21530): ZXingScannerFragment->OnResume exit
02-03 16:29:01.635 D/ViewRootImpl@d630583[MainActivity](21530): Relayout returned: oldFrame=[0,0][720,1280] newFrame=[0,0][720,1280] result=0x1 surface={isValid=true -885530624} surfaceGenerationChanged=false
02-03 16:29:01.652 D/SurfaceView(21530): Relayout returned: oldFrame=[0,0][0,0] newFrame=[0,48][720,1280] result=0x7 surface={Surface(name=null)/@0x8798822 isValid=true -918034432}
02-03 16:29:01.673 D/SurfaceView(21530): Relayout returned: oldFrame=[0,48][720,1280] newFrame=[0,48][720,1280] result=0x1 surface={Surface(name=null)/@0x8798822 isValid=true -925298688}

和第二个起点(效果很好):

02-03 16:30:38.284 D/ZXing.Net.Mobile(22786): ZXingScannerFragment->OnResume exit
02-03 16:30:38.293 D/ViewRootImpl@431432[MainActivity](22786): Relayout returned: oldFrame=[0,0][720,1280] newFrame=[0,0][720,1280] result=0x1 surface={isValid=true -878399488} surfaceGenerationChanged=false
02-03 16:30:38.316 D/SurfaceView(22786): Relayout returned: oldFrame=[0,0][0,0] newFrame=[0,48][720,1280] result=0x7 surface={Surface(name=null)/@0x393638a isValid=true -914219008}
02-03 16:30:38.316 D/ZXing.Net.Mobile(22786): Checking android.permission.CAMERA...
02-03 16:30:38.319 D/ZXing.Net.Mobile(22786): Checking Number of cameras...
02-03 16:30:38.320 I/ServiceManager(22786): Waiting for service media.camera...
02-03 16:30:38.324 I/art     (22786): Do partial code cache collection, code=23KB, data=28KB
02-03 16:30:38.324 I/art     (22786): After code cache collection, code=19KB, data=24KB
02-03 16:30:38.324 I/art     (22786): Increasing code cache capacity to 128KB
02-03 16:30:39.322 D/ZXing.Net.Mobile(22786): Found 2 cameras...
02-03 16:30:39.325 D/ZXing.Net.Mobile(22786): Found Back Camera, opening...
02-03 16:30:39.404 D/ZXing.Net.Mobile(22786): Selected Resolution: 960x720
02-03 16:30:39.412 D/ZXing.Net.Mobile(22786): Changing Camera Orientation to: 90
02-03 16:30:39.822 D/ZXing.Net.Mobile(22786): Selected Resolution: 960x720
02-03 16:30:39.831 D/ZXing.Net.Mobile(22786): Changing Camera Orientation to: 90
02-03 16:30:39.846 I/Choreographer(22786): Skipped 92 frames!  The application may be doing too much work on its main thread.
02-03 16:30:39.856 D/SurfaceView(22786): Relayout returned: oldFrame=[0,48][720,1280] newFrame=[0,48][720,1280] result=0x1 surface={Surface(name=null)/@0x393638a isValid=true -890101760}
02-03 16:30:42.144 I/art     (22786): Starting a blocking GC Explicit
02-03 16:30:42.150 D/Mono    (22786): GC_BRIDGE waiting for bridge processing to finish
02-03 16:30:42.198 I/art     (22786): Explicit concurrent mark sweep GC freed 4669(256KB) AllocSpace objects, 5(4MB) LOS objects, 39% free, 8MB/14MB, paused 532us total 54.160ms
02-03 16:30:42.201 D/Mono    (22786): GC_TAR_BRIDGE bridges 319 objects 388 opaque 66 colors 322 colors-bridged 319 colors-visible 319 xref 9 cache-hit 0 cache-semihit 0 cache-miss 3 setup 0.13ms tarjan 0.34ms scc-setup 0.23ms gather-xref 0.02ms xref-setup 0.02ms cleanup 0.12ms
02-03 16:30:42.201 D/Mono    (22786): GC_BRIDGE: Complete, was running for 59.51ms
02-03 16:30:42.201 D/Mono    (22786): GC_MAJOR: (LOS overflow) time 11.64ms, stw 12.98ms los size: 3072K in use: 765K
02-03 16:30:42.201 D/Mono    (22786): GC_MAJOR_SWEEP: major size: 1312K in use: 485K

如您所见,存在差异,但是我不知道为什么ZXing并没有在第一个中启动相机。权限很好,我已经检查过了。

有人可以帮我吗?

2 个答案:

答案 0 :(得分:1)

当ZXingScannerFragment在首次启动应用程序时显示黑屏时,我遇到了同样的问题。经过调查,我找到了补救办法。我只是在创建ZxingFragment的方法中将.Commit();替换为.CommitAllowingStateLoss();

SupportFragmentManager.BeginTransaction()
    .Replace(Resource.Id.fragment_container, _zXingScannerFragment)
    .CommitAllowingStateLoss(); 

我发现@pnavk关于摄像机授予许可的假设是正确的。即使在使用await PermissionsHandler.RequestPermissionsAsync(this);之后,PermissionsHandler.PermissionRequestTask也没有成功完成。

此问题的完整解决方案是使用第三方代码来维护授予权限的过程,而不是内置的ZXing。我检查了James Montemagno的PermissionsPlugin,它运作良好。但这需要进行过多的代码更改并添加其他插件,因此我决定使用简单的解决方案。也许对您有帮助。

答案 1 :(得分:0)

因为这仅是第一次发生,所以听起来像是由于调用RequestPermissionsAsync引起的。我假设您是第一次接受该许可,因此围绕needsPermissionRequest的条件第二次解析为false,并且未调用RequestPermissionsAsync,因此代码可以正常工作。

您应该对代码进行一些修改:

ZXing.Net.Mobile.Android.PermissionsHandler.RequestPermissionsAsync(Activity)
                .ContinueWith((b) => ShowScanFragment());

您应该await进行此async方法调用,而不要使用ContinueWith。正在background thread中而不是似乎引起您问题的UI线程中调用ShowScanFragment。

您还可以删除以下行:

var needsPermissionRequest = ZXing.Net.Mobile.Android.PermissionsHandler.NeedsPermissionRequest(Model.Model.MainActivityContext);

如果您选中ZXing source code,则在致电RequestPermissionsAsync时已经完成了此检查,因此您无需自己进行检查。

尝试这样修改您的OnResume方法:

public override async void OnResume()
{
    base.OnResume();

    var permissionGranted = await ZXing.Net.Mobile.Android.PermissionsHandler.RequestPermissionsAsync(Activity);
    if(permissionGranted) {
        ShowScanFragment();
    }else{
        //handle permission denied
    }
}