dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.28k stars 1.76k forks source link

Connecting or Disconnecting Physical Barcode Reader is triggering App Return to Initial Index Page #18618

Closed lasithalankajeewa closed 4 months ago

lasithalankajeewa commented 1 year ago

Description

When using a physical barcode reader on the Android version of the .NET MAUI Blazor app, the application unexpectedly returns to the initial index page when attempting to connect or disconnect the barcode reader to the android device. This behavior occurs consistently, disrupting the expected flow of the application and causing inconvenience to the user experience.

Steps to Reproduce

When Connecting the Barcode Reader

  1. Open the .NET MAUI Blazor app on an Android device.
  2. Navigate from the initial index page to another page within the app.
  3. Connect a physical barcode reader via Bluetooth or wired connection.
  4. Observe that the app returns to the initial index page instead of staying on the intended page.

When Disconnecting the Barcode Reader

  1. Open the .NET MAUI Blazor app on an Android device.
  2. Navigate from the initial index page to another page within the app.
  3. Disconnect the physical barcode reader.
  4. Observe that the app returns to the initial index page instead of staying on the intended page.

Link to public reproduction project repository

https://github.com/lasithalankajeewa/Scanner-Test-BL.git

Version with bug

7.0.86

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 13

Did you find any workaround?

No response

Relevant log output

[ViewRootImpl@e140a31[MainActivity]] stopped(true) old = false
[ViewRootImpl@e140a31[MainActivity]] WindowStopped on com.companyname.scanner_test_bl/crc643fd2fa3dc4204a9f.MainActivity set to true
[MSHandlerLifeCycle] removeMultiSplitHandler: no exist. decor=DecorView@dfde0bd[MainActivity]
[OpenGLRenderer] setSurface called with nullptr
[OpenGLRenderer] setSurface() destroyed EGLSurface
[OpenGLRenderer] destroyEglSurface
[ViewRootImpl@e140a31[MainActivity]] dispatchDetachedFromWindow
[InputTransport] Input channel destroyed: 'eaf1493', fd=185
[DecorView] [INFO] isPopOver=false config=true
[DecorView] updateCaptionType: isFloating=false isApplication=true hasWindowDecorCaption=false this=DecorView@2e3403b[]
[DecorView] setCaptionType = 0, this = DecorView@2e3403b[]
[DecorView] getCurrentDensityDpi: from real metrics. densityDpi=340 msg=resources_loaded
[DecorView] setWindowBackground: isPopOver=false color=ffffffff d=android.graphics.drawable.ColorDrawable@30aecb1
[cr_DWTrigger] updateDWServiceStatus() : isEnabled = true
[cr_DWTrigger] updateDWServiceStatus() : isEnabled = true
[MSHandlerLifeCycle] check: return. pkg=com.companyname.scanner_test_bl parent=null callers=com.android.internal.policy.DecorView.setVisibility:4487 android.app.ActivityThread.handleResumeActivity:5491 android.app.servertransaction.ResumeActivityItem.execute:54 android.app.servertransaction.ActivityTransactionItem.execute:45 android.app.servertransaction.TransactionExecutor.executeLifecycleState:176 
[MSHandlerLifeCycle] removeMultiSplitHandler: no exist. decor=DecorView@2e3403b[]
[SurfaceSyncer@9b984ad] new SurfaceSyncer() = android.view.ViewRootImpl.<init>:1168 android.view.ViewRootImpl.<init>:1304 android.view.WindowManagerGlobal.addView:530 android.view.WindowManagerImpl.addView:170 android.app.ActivityThread.handleResumeActivity:5512 
[NativeCustomFrequencyManager] [NativeCFMS] BpCustomFrequencyManager::BpCustomFrequencyManager()
[InsetsController] onStateChanged: InsetsState: {mDisplayFrame=Rect(0, 0 - 2560, 1600), mDisplayCutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]} cutoutPathParserInfo={CutoutPathParserInfo{displayWidth=0 displayHeight=0 physicalDisplayWidth=0 physicalDisplayHeight=0 density={0.0} cutoutSpec={} rotation={0} scale={0.0} physicalPixelDisplaySizeRatio={0.0}}}}, mRoundedCorners=RoundedCorners{[RoundedCorner{position=TopLeft, radius=28, center=Point(28, 28)}, RoundedCorner{position=TopRight, radius=28, center=Point(2532, 28)}, RoundedCorner{position=BottomRight, radius=28, center=Point(2532, 1572)}, RoundedCorner{position=BottomLeft, radius=28, center=Point(28, 1572)}]}  mRoundedCornerFrame=Rect(0, 0 - 2560, 1600), mPrivacyIndicatorBounds=PrivacyIndicatorBounds {static bounds=Rect(2466, 0 - 2560, 51) rotation=1}, mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_LEFT_GESTURES, mFrame=[0,0][0,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_RIGHT_GESTURES, mFrame=[2560,0][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_MANDATORY_GESTURES, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_MANDATORY_GESTURES, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_TAPPABLE_ELEMENT, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_TAPPABLE_ELEMENT, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_IME, mFrame=[0,0][0,0], mVisible=false, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_EXTRA_NAVIGATION_BAR, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=true} } host=com.companyname.scanner_test_bl/crc643fd2fa3dc4204a9f.MainActivity from=android.view.ViewRootImpl.setView:1739
[ViewRootImpl@53863e2[MainActivity]] setView = com.android.internal.policy.DecorView@2e3403b TM=true
[DecorView] isDeviceLocked = false
[MSHandlerLifeCycle] check: return. pkg=com.companyname.scanner_test_bl mode=fullscreen op=true locked=false callers=com.android.internal.policy.DecorView.setVisibility:4487 android.app.Activity.makeVisible:6819 android.app.ActivityThread.handleResumeActivity:5556 android.app.servertransaction.ResumeActivityItem.execute:54 android.app.servertransaction.ActivityTransactionItem.execute:45 
[MSHandlerLifeCycle] removeMultiSplitHandler: no exist. decor=DecorView@2e3403b[MainActivity]
[ViewRootImpl@53863e2[MainActivity]] performTraversals params={(0,0)(fillxfill) sim={adjust=pan} ty=BASE_APPLICATION wanim=0x1030309
[ViewRootImpl@53863e2[MainActivity]]   fl=81810100
[ViewRootImpl@53863e2[MainActivity]]   pfl=12020040
[ViewRootImpl@53863e2[MainActivity]]   bhv=DEFAULT
[ViewRootImpl@53863e2[MainActivity]]   fitSides= naviIconColor=0
[ViewRootImpl@53863e2[MainActivity]]   sfl=100000}
[ViewRootImpl@53863e2[MainActivity]] performTraversals mFirst=true windowShouldResize=true viewVisibilityChanged=false mForceNextWindowRelayout=false params={(0,0)(fillxfill) sim={adjust=pan} ty=BASE_APPLICATION wanim=0x1030309
[ViewRootImpl@53863e2[MainActivity]]   fl=81810100
[ViewRootImpl@53863e2[MainActivity]]   pfl=12020040
[ViewRootImpl@53863e2[MainActivity]]   bhv=DEFAULT
[ViewRootImpl@53863e2[MainActivity]]   fitSides= naviIconColor=0
[ViewRootImpl@53863e2[MainActivity]]   sfl=100000}
[ViewRootImpl@53863e2[MainActivity]] updateBlastSurfaceIfNeeded mBlastBufferQueue=null isSameSurfaceControl=false
[BLASTBufferQueue] new BLASTBufferQueue, mName= ViewRootImpl@53863e2[MainActivity] mNativeObject= 0xb400006d9687d5b0 sc.mNativeObject= 0xb400006d2685adb0 caller= android.view.ViewRootImpl.updateBlastSurfaceIfNeeded:2939 android.view.ViewRootImpl.relayoutWindow:9990 android.view.ViewRootImpl.performTraversals:3919 android.view.ViewRootImpl.doTraversal:3151 android.view.ViewRootImpl$TraversalRunnable.run:11068 android.view.Choreographer$CallbackRecord.run:1321 android.view.Choreographer$CallbackRecord.run:1329 android.view.Choreographer.doCallbacks:930 android.view.Choreographer.doFrame:859 android.view.Choreographer$FrameDisplayEventReceiver.run:1303 
[BLASTBufferQueue] update, w= 2560 h= 1600 mName = ViewRootImpl@53863e2[MainActivity] mNativeObject= 0xb400006d9687d5b0 sc.mNativeObject= 0xb400006d2685adb0 format= -1 caller= android.graphics.BLASTBufferQueue.<init>:84 android.view.ViewRootImpl.updateBlastSurfaceIfNeeded:2939 android.view.ViewRootImpl.relayoutWindow:9990 android.view.ViewRootImpl.performTraversals:3919 android.view.ViewRootImpl.doTraversal:3151 android.view.ViewRootImpl$TraversalRunnable.run:11068 
[ViewRootImpl@53863e2[MainActivity]] Relayout returned: old=(0,0,2560,1600) new=(0,0,2560,1600) req=(2560,1600)0 dur=7 res=0x3 s={true 0xb400006e28534560} ch=true seqId=0
[OpenGLRenderer] eglCreateWindowSurface
[ViewRootImpl@53863e2[MainActivity]] mThreadedRenderer.initialize() mSurface={isValid=true 0xb400006e28534560} hwInitialized=true
[ViewRootImpl@53863e2[MainActivity]] reportNextDraw android.view.ViewRootImpl.performTraversals:4473 android.view.ViewRootImpl.doTraversal:3151 android.view.ViewRootImpl$TraversalRunnable.run:11068 android.view.Choreographer$CallbackRecord.run:1321 android.view.Choreographer$CallbackRecord.run:1329 
[ViewRootImpl@53863e2[MainActivity]] Setup new sync id=0
[ViewRootImpl@53863e2[MainActivity]] Setting syncFrameCallback
[ViewRootImpl@53863e2[MainActivity]] registerCallbacksForSync syncBuffer=false
[ViewRootImpl@53863e2[MainActivity]] Received frameDrawingCallback syncResult=0 frameNum=1.
[ViewRootImpl@53863e2[MainActivity]] Setting up sync and frameCommitCallback
[BLASTBufferQueue] [ViewRootImpl@53863e2[MainActivity]#1](f:0,a:0,s:0) onFrameAvailable the first frame is available
[ViewRootImpl@53863e2[MainActivity]] Received frameCommittedCallback lastAttemptedDrawFrameNum=1 didProduceBuffer=true
[OpenGLRenderer] CFMS:: SetUp Pid : 17203    Tid : 17255
[Parcel] Expecting binder but got null!
[ViewRootImpl@53863e2[MainActivity]] onSyncComplete
[ViewRootImpl@53863e2[MainActivity]] setupSync seqId=0 mSyncId=0 fn=1 caller=android.view.ViewRootImpl$$ExternalSyntheticLambda11.accept:6 android.window.SurfaceSyncer.lambda$setupSync$1$android-window-SurfaceSyncer:168 android.window.SurfaceSyncer$$ExternalSyntheticLambda1.accept:8 android.window.SurfaceSyncer$SyncSet.checkIfSyncIsComplete:495 android.window.SurfaceSyncer$SyncSet.markSyncReady:454 android.window.SurfaceSyncer.markSyncReady:191 android.view.ViewRootImpl.performTraversals:4538 
[ViewRootImpl@53863e2[MainActivity]] reportDrawFinished seqId=0 mSyncId=-1 fn=1 mSurfaceChangedTransaction=0xb400006d56840c50
[ViewRootImpl@53863e2[MainActivity]] mThreadedRenderer.initializeIfNeeded()#2 mSurface={isValid=true 0xb400006e28534560}
[cr_DWTrigger] updateDWServiceStatus() : isEnabled = true
[cr_DWTrigger] updateDWServiceStatus() : isEnabled = true
[InputMethodManager] startInputInner - Id : 0
[InputMethodManager] startInputInner - mService.startInputOrWindowGainedFocus
[ViewRootImpl@53863e2[MainActivity]] Resizing android.view.ViewRootImpl@bfcdc2e: frame = [0,0][2560,1600] reportDraw = false forceLayout = false syncSeqId = 0
[ViewRootImpl@53863e2[MainActivity]] MSG_WINDOW_FOCUS_CHANGED 1 0
[InsetsController] onStateChanged: InsetsState: {mDisplayFrame=Rect(0, 0 - 2560, 1600), mDisplayCutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]} cutoutPathParserInfo={CutoutPathParserInfo{displayWidth=0 displayHeight=0 physicalDisplayWidth=0 physicalDisplayHeight=0 density={0.0} cutoutSpec={} rotation={0} scale={0.0} physicalPixelDisplaySizeRatio={0.0}}}}, mRoundedCorners=RoundedCorners{[RoundedCorner{position=TopLeft, radius=28, center=Point(28, 28)}, RoundedCorner{position=TopRight, radius=28, center=Point(2532, 28)}, RoundedCorner{position=BottomRight, radius=28, center=Point(2532, 1572)}, RoundedCorner{position=BottomLeft, radius=28, center=Point(28, 1572)}]}  mRoundedCornerFrame=Rect(0, 0 - 2560, 1600), mPrivacyIndicatorBounds=PrivacyIndicatorBounds {static bounds=Rect(2466, 0 - 2560, 51) rotation=1}, mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_LEFT_GESTURES, mFrame=[0,0][0,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_RIGHT_GESTURES, mFrame=[2560,0][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_MANDATORY_GESTURES, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_MANDATORY_GESTURES, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_TAPPABLE_ELEMENT, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_TAPPABLE_ELEMENT, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_EXTRA_NAVIGATION_BAR, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=true} } host=com.companyname.scanner_test_bl/crc643fd2fa3dc4204a9f.MainActivity from=android.view.ViewRootImpl$ViewRootHandler.handleMessageImpl:6805
[ViewRootImpl@53863e2[MainActivity]] handleResized, msg = 4 frames=ClientWindowFrames{frame=[0,0][2560,1600] display=[0,0][2560,1600] parentFrame=[0,0][0,0] parentClippedByDisplayCutout=false} forceNextWindowRelayout=false displayId=0 resizeMode=-1 frameChanged=false displayFrameChanged=false configChanged=false displayChanged=false
[InsetsController] onStateChanged: InsetsState: {mDisplayFrame=Rect(0, 0 - 2560, 1600), mDisplayCutout=DisplayCutout{insets=Rect(0, 0 - 0, 0) waterfall=Insets{left=0, top=0, right=0, bottom=0} boundingRect={Bounds=[Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0), Rect(0, 0 - 0, 0)]} cutoutPathParserInfo={CutoutPathParserInfo{displayWidth=0 displayHeight=0 physicalDisplayWidth=0 physicalDisplayHeight=0 density={0.0} cutoutSpec={} rotation={0} scale={0.0} physicalPixelDisplaySizeRatio={0.0}}}}, mRoundedCorners=RoundedCorners{[RoundedCorner{position=TopLeft, radius=28, center=Point(28, 28)}, RoundedCorner{position=TopRight, radius=28, center=Point(2532, 28)}, RoundedCorner{position=BottomRight, radius=28, center=Point(2532, 1572)}, RoundedCorner{position=BottomLeft, radius=28, center=Point(28, 1572)}]}  mRoundedCornerFrame=Rect(0, 0 - 2560, 1600), mPrivacyIndicatorBounds=PrivacyIndicatorBounds {static bounds=Rect(2466, 0 - 2560, 51) rotation=1}, mSources= { InsetsSource: {mType=ITYPE_STATUS_BAR, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_LEFT_GESTURES, mFrame=[0,0][0,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_RIGHT_GESTURES, mFrame=[2560,0][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_MANDATORY_GESTURES, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_MANDATORY_GESTURES, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_TOP_TAPPABLE_ELEMENT, mFrame=[0,0][2560,51], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_BOTTOM_TAPPABLE_ELEMENT, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_IME, mFrame=[0,0][0,0], mVisible=false, mInsetsRoundedCornerFrame=false}, InsetsSource: {mType=ITYPE_EXTRA_NAVIGATION_BAR, mFrame=[0,1498][2560,1600], mVisible=true, mInsetsRoundedCornerFrame=true} } host=com.companyname.scanner_test_bl/crc643fd2fa3dc4204a9f.MainActivity from=android.view.ViewRootImpl$ViewRootHandler.handleMessageImpl:6818
[ViewRootImpl@53863e2[MainActivity]] ViewPostIme key 0
[ViewRootImpl@53863e2[MainActivity]] ViewPostIme key 1
[scanner_test_bl] Explicit concurrent copying GC freed 20037(1045KB) AllocSpace objects, 1(16KB) LOS objects, 58% free, 4312KB/10MB, paused 26us,20us total 12.581ms
[InputTransport] Input channel destroyed: 'ClientS', fd=96
[OpenGLRenderer] setSurface called with nullptr
[InputTransport] Input channel destroyed: 'ClientS', fd=205
Eilon commented 1 year ago

Hi @lasithalankajeewa , that sounds quite odd. Is the app actually doing anything with the barcode scanner? Or it's just a simple app that has nothing to do with the scanner, but somehow connect/disconnect of the scanner causes the app to navigate? (I didn't see any code in the app that actually uses the scanner device, but perhaps I missed it.)

ghost commented 1 year ago

Hi @lasithalankajeewa. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

lasithalankajeewa commented 1 year ago

Hi @Eilon ,

Thank you for looking into this. I completely understand the confusion. Unfortunately, I am unable to share the full application as it is proprietary to my company. However, I have created a sample application to demonstrate the issue, and it seems to replicate the same behavior.

In this sample application, I have added a button to the index page that navigates to the counter.razor page. Whenever a barcode scanner is connected or disconnected from counter.razor page to the Android device, the app returns to the initial index.razor page. i don't know whether it is returning to index.razor or complete restart the app . This behavior is very similar to what occurs in the actual application, even without explicit code related to the scanner.

I hope this provides some clarity regarding the issue. Please let me know if there are any further details or specific information that would be helpful for solve this.

Eilon commented 1 year ago

@lasithalankajeewa got it, understood. As long as the bug repros with the app you showed, that's fine. The thing is, because it's not actually using the bar code scanner, I have a hard time imagining how the two could possibly interact with each other.

Does connecting/disconnecting the bar code scanner cause some sort of command to be sent to the device that could cause navigation? Like some browser navigation event?

Could you add some code to the app to see if it is fully restarting instead of just a navigation?

Unfortunately with this bug I don't see how we could reproduce this locally without the bar code scanner so we'll likely need more information to understand where the issue is.

ghost commented 1 year ago

Hi @lasithalankajeewa. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

lasithalankajeewa commented 1 year ago

Hi @Eilon , Thank you for your understanding. I have conducted extensive testing with various Android devices and different barcode scanners, and the issue persists across all of them. This leads me to believe that it might be related to the input method change on the Android device when the barcode scanner is connected, essentially switching from the virtual keyboard to the barcode reader. Similarly, disconnecting the scanner could trigger a switch from the barcode reader back to the virtual keyboard. This is just a thought. I might be completely wrong.

I have also included the log output pertaining to this particular occurrence in "Relevant log output" section. While I find these logs puzzling, I am hopeful that you might be able to identify some relevant insights from them.

In addition, I am keen to understand if any specific segments of the code need further scrutiny or modification. If there are particular sections or functionalities that you suggest I should focus on, please do let me know.

Eilon commented 1 year ago

@lasithalankajeewa interesting. Were you able to determine if it's the app crashing, or just doing some navigation internally? I didn't see anything in the log that looked like a crash to me, but I'm not familiar with a lot of Android things.

ghost commented 1 year ago

Hi @lasithalankajeewa. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

lasithalankajeewa commented 1 year ago

@Eilon I don't think it's crashing. It just navigated to the initial page. This is happening in android only. Windows version working fine

Eilon commented 1 year ago

@lasithalankajeewa OK that's good to know. Can you test with a regular WebView as well and see what happens? Instead of BlazorWebView, use a regular WebView and point it to an arbitrary URL, like https://bing.com, then when it loads navigate in it to some page. Then do the barcode connect/disconnect and see if it causes the regular WebView to navigate.

lasithalankajeewa commented 1 year ago

@Eilon where should i change this WebView and URL? can you mention the file location?

Eilon commented 1 year ago

@lasithalankajeewa I'm suggesting to temporarily change your app (or just create a new app) with only a regular WebView set to a web page, use it to navigate, and then try the bar code reader. I'm trying to understand if this issue is related to a conflict between all webviews and the bar code reader.

ghost commented 1 year ago

Hi @lasithalankajeewa. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

lasithalankajeewa commented 1 year ago

@Eilon I tried the WebView. Same happened as BlazorView. If you want to look what i implemented, I have created the WebView in the https://github.com/lasithalankajeewa/Scanner-Test-BL.git this git repository(same repo) as a separate branch,

Eilon commented 1 year ago

@lasithalankajeewa interesting. Then I strongly suspect it's something that the bar code reader itself is doing, perhaps by sending fake keypresses to the OS, which if it happens to be on a WebView, causes a navigation to happen. I think sending keypresses is how some bar code readers work - they register themselves as a 'keyboard' and then when you scan bar codes they 'type in' the numbers that they detect.

Now I'm even wondering if the same thing happens in a regular web browser without .NET MAUI at all. If you open Chrome on the device, load any site, navigate (click links, etc.), and then do the bar code reader connect/disconnect, does that cause the navigation to happen? If so, then I suggest contacting the manufacturer of the bar code reader.

lasithalankajeewa commented 12 months ago

@Eilon I tried it on the chrome browser. But nothing happened in the Chrome browser. Also, I tried to use different barcode scanner devices as well. in there also same navigation issue happened. So, I don't think it's happened because of barcode scanner device. This is a big issue for my MAUI Hybrid app

lasithalankajeewa commented 11 months ago

@Eilon Any updates?

konradzuse commented 9 months ago

This is expected behaviour. Disconnecting/Connecting the barcode scanner is acting as a Physical keyboard as you correctly described.

Doing this will cause the app the recycle, the same as if the device language was changed.

The problem with navigation you are seeing is that the app doesn't restore the navigation state when it is stopped and restarted. You will observe the same behaviour if the app is moved to the background and stopped by the system, then switching back to the app.

lasithalankajeewa commented 9 months ago

@konradzuse yes you are correct. The same thing happening when the language changed. Do you have any solution to fix the issue?

konradzuse commented 9 months ago

As far as I know there isn't a built in solution. Maybe this is handled if you're using Shell navigation?

In my app, I have to handle OnSleep/OnResume, and save and restore the app's state manually. It's a mess of interfaces on each page, and json serialisation steps.

When the app restores, the user sees each page of the navigation stack drawing one over the next. It's not very slick, but it works.

mattleibow commented 6 months ago

If this is related to the scanner triggering an app recycle, is there no flags you can set KeyboardHidden in the list of things in ConfigurationChanges of the activity attribute:

[Activity(..., ConfigurationChanges = ... | ConfigChanges.KeyboardHidden)]
jnalley20 commented 6 months ago

I did notice this issue in .NET7 and it seems to have gotten worse in .NET8. The issue I'm facing in .NET8 is that the app goes to a black screen when a Bluetooth keyboard is connected or disconnected from the Android device. I'm having this issue with an app that I just recently updated to .NET8 from 7. That app does not seem to have any issue with being placed in the background... This issue happens with a fresh .NET8 Blazor MAUI project. This issue does not seem to happen with a fresh .NET7 Blazor MAUI project but it does send you to the home page.

jnalley20 commented 6 months ago

If this is related to the scanner triggering an app recycle, is there no flags you can set KeyboardHidden in the list of things in ConfigurationChanges of the activity attribute:

[Activity(..., ConfigurationChanges = ... | ConfigChanges.KeyboardHidden)]

This comment almost helped me solve my problem. I needed both (ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden) to ignore when a keyboard was added or removed.

mattleibow commented 4 months ago

I am going to close this as resolved using Android's designed things. Android likes to refresh activities at will, and these are the ways to say no to it.