IOS stops browser background processes

0
How to prevent IOS from stopping JS when browser is set to background?   Currently building a web app where authentication is integrated with another external app. In order to authenticate the app sends a security code to the exteral app, where it must be confirmed. The issue then happens when going back to browser, whether it be Chrome, Safari or some other. Mendix throws a generic error which says: com.mendix.systemwideinterfaces.MendixRuntimeException: org.eclipse.jetty.io.EofException     at com.mendix.util.classloading.Runner$.withContextClassLoader(Runner.scala:23) Caused by: org.eclipse.jetty.io.EofException: null     at org.eclipse.jetty.io.SocketChannelEndPoint.flush(SocketChannelEndPoint.java:116)     at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:422)     at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:275)     at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:254)     at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:386)     at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:821)     at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:232)     at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:214)     at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:584)     at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:1055)     at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:1132)     at org.eclipse.jetty.server.HttpOutput.channelWrite(HttpOutput.java:270)     at org.eclipse.jetty.server.HttpOutput.close(HttpOutput.java:623)     at java.base/sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:341)     at java.base/sun.nio.cs.StreamEncoder.close(StreamEncoder.java:161)     at java.base/java.io.OutputStreamWriter.close(OutputStreamWriter.java:258)     at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.close(WriterBasedJsonGenerator.java:1028)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.$anonfun$close$1(JsonGeneratorWrapper.scala:25)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.$anonfun$close$1$adapted(JsonGeneratorWrapper.scala:25)     at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:575)     at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:573)     at scala.collection.AbstractIterable.foreach(Iterable.scala:933)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.close(JsonGeneratorWrapper.scala:25)     at com.mendix.webui.jsonserialization.ResultSerializer.close(ResultSerializer.scala:21)     at com.mendix.webui.requesthandling.ClientRequestHandler.processRequest(ClientRequestHandler.scala:80)     at com.mendix.externalinterface.connector.RequestHandler.doProcessRequest(RequestHandler.java:37)     at com.mendix.external.connector.MxRuntimeConnector.$anonfun$processRequest$1(MxRuntimeConnector.scala:54)     at com.mendix.external.connector.MxRuntimeConnector.$anonfun$processRequest$1$adapted(MxRuntimeConnector.scala:54)     at com.mendix.util.classloading.Runner$.withContextClassLoader(Runner.scala:20)     at com.mendix.external.connector.MxRuntimeConnector.processRequest(MxRuntimeConnector.scala:54)     at com.mendix.basis.impl.MxRuntimeImpl.processRequest(MxRuntimeImpl.scala:221)     at com.mendix.m2ee.appcontainer.server.handler.RuntimeServlet.service(RuntimeServlet.scala:40)     at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)     at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)     at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170)     at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)     at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)     at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570)     at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1383)     at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543)     at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1305)     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)     at org.eclipse.jetty.server.Server.handle(Server.java:563)     at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)     at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)     at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)     at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)     at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)     at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)     at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:416)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:385)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:272)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.lambda$new$0(AdaptiveExecutionStrategy.java:140)     at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)     at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)     at java.base/java.lang.Thread.run(Thread.java:834) Caused by: java.io.IOException: An existing connection was forcibly closed by the remote host     at java.base/sun.nio.ch.SocketDispatcher.writev0(Native Method)     at java.base/sun.nio.ch.SocketDispatcher.writev(SocketDispatcher.java:55)     at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:182)     at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:130)     at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:496)     at java.base/java.nio.channels.SocketChannel.write(SocketChannel.java:507)     at org.eclipse.jetty.io.SocketChannelEndPoint.flush(SocketChannelEndPoint.java:110)     at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:422)     at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:275)     at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:254)     at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:386)     at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:821)     at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:232)     at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:214)     at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:584)     at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:1055)     at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:1132)     at org.eclipse.jetty.server.HttpOutput.channelWrite(HttpOutput.java:270)     at org.eclipse.jetty.server.HttpOutput.close(HttpOutput.java:623)     at java.base/sun.nio.cs.StreamEncoder.implClose(StreamEncoder.java:341)     at java.base/sun.nio.cs.StreamEncoder.close(StreamEncoder.java:161)     at java.base/java.io.OutputStreamWriter.close(OutputStreamWriter.java:258)     at com.fasterxml.jackson.core.json.WriterBasedJsonGenerator.close(WriterBasedJsonGenerator.java:1028)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.$anonfun$close$1(JsonGeneratorWrapper.scala:25)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.$anonfun$close$1$adapted(JsonGeneratorWrapper.scala:25)     at scala.collection.IterableOnceOps.foreach(IterableOnce.scala:575)     at scala.collection.IterableOnceOps.foreach$(IterableOnce.scala:573)     at scala.collection.AbstractIterable.foreach(Iterable.scala:933)     at com.mendix.webui.jsonserialization.JsonGeneratorWrapper.close(JsonGeneratorWrapper.scala:25)     at com.mendix.webui.jsonserialization.ResultSerializer.close(ResultSerializer.scala:21)     at com.mendix.webui.requesthandling.ClientRequestHandler.processRequest(ClientRequestHandler.scala:80)     at com.mendix.externalinterface.connector.RequestHandler.doProcessRequest(RequestHandler.java:37)     at com.mendix.external.connector.MxRuntimeConnector.$anonfun$processRequest$1(MxRuntimeConnector.scala:54)     at com.mendix.external.connector.MxRuntimeConnector.$anonfun$processRequest$1$adapted(MxRuntimeConnector.scala:54)     at com.mendix.util.classloading.Runner$.withContextClassLoader(Runner.scala:20)     at com.mendix.external.connector.MxRuntimeConnector.processRequest(MxRuntimeConnector.scala:54)     at com.mendix.basis.impl.MxRuntimeImpl.processRequest(MxRuntimeImpl.scala:221)     at com.mendix.m2ee.appcontainer.server.handler.RuntimeServlet.service(RuntimeServlet.scala:40)     at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)     at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)     at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)     at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170)     at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)     at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)     at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)     at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)     at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1570)     at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)     at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1383)     at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)     at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)     at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1543)     at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)     at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1305)     at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)     at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)     at org.eclipse.jetty.server.Server.handle(Server.java:563)     at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)     at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)     at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)     at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)     at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)     at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)     at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:416)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:385)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:272)     at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.lambda$new$0(AdaptiveExecutionStrategy.java:140)     at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)     at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)     at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)     at java.base/java.lang.Thread.run(Thread.java:834)   To my understanding this means that IOS stopped the JS from running all together. This means that the user trying to login is not logged in. I did some research on Apple developer forums and came up with this: https://developer.apple.com/forums/thread/85066 Is this a viable solution to the problem, because they usually refer to apps in the post, meaning native from my understanding. Or is there another easier solution?   Creating a native app is not on the table at the moment.
asked
1 answers
0

Hello,

Unfortunately, there is no way to prevent iOS from stopping JavaScript execution when the browser is set to the background. This behavior is a security feature implemented by iOS to protect user privacy and battery life.

When an app is sent to the background, iOS will pause all processes and background tasks to conserve battery and processing power. As a result, any JavaScript execution within a browser tab will be paused, which could lead to issues like the one you're experiencing.

One solution to this issue is to use a native mobile app instead of a web app. Native apps can use features like background processing to continue running tasks even when the app is not in the foreground.

If using a web app is a requirement, you may need to redesign your app to work within the limitations of iOS background execution. For example, you could save the authentication code to local storage and resume the authentication process when the user returns to the app. You could also use push notifications or other background features to update the user when the authentication process is complete.

Overall, it's important to design your app with the limitations of the platform in mind to ensure a seamless user experience.
Regards,
Serhiy

answered