23

I have deployed an app in shinyapps.io and its working fine.

I am running the app for only 5 minutes, but when I checked the metrics it shows a running time for about 0.7 hours. I found that there is a default idle time of 15 minutes, which I have changed to 5 minutes (minimum). I also noticed that, even after closing the browser window of the shiny app, it still shows the app as running in my dashboard.

I assume that the app doesn't stop running when a browser window is closed and it will stop only when the idle time condition is met.

Is there a way to stop the shiny app when the browser window is closed? Would the following piece of code work in this instance?

session$onSessionEnded(function() {
    stopApp()
  })
DoubleYou
  • 1,057
  • 11
  • 25
Eka
  • 14,170
  • 38
  • 128
  • 212
  • 2
    you should ask this in the shinyapps users google group – DeanAttali Feb 10 '16 at 03:33
  • A [JavaScript event](http://shiny.rstudio.com/articles/js-events.html) and `stopApp()`? – alistaire Feb 10 '16 at 03:47
  • The right person to ask is definitely is @daattali as his example apps grey out after some time, it think its 15 mins – Pork Chop Feb 10 '16 at 09:17
  • 1
    I previously gave an answer that uses the exact code in your edit, I wonder if your solution was from me? :) Anyway, that code will terminate the app when the session ends. When you run an app locally in your browser, then closing the window definitely counts as a session ending. However, I'm very unfamiliar with shinyappsio, so I don't know for sure if it works like that in shinyapps or not. It's possible that it does, but to be sure I would ask in the shinyapps discussion board, or just try it and experiment to see what happens – DeanAttali Feb 10 '16 at 09:23
  • I got the code from google groups i dont know if it was yours. Unfortunately the code doesn't work in shinyappsio. I also tried `q("no")` with `stopApp` no results. I have to manually switch off the apps from dashboard . why I am worried is that just by visiting the apps url we are starting the app and it stops only after 5 minute of idle time. As i am using a free tier of 25 hours it takes a lot of valuable hours from the app :( – Eka Feb 10 '16 at 11:13

3 Answers3

23

I'm not aware of shinyapps.io, but in R (as your tag shows) you can indeed stop a shinyApp through the onSessionEnded. The following is a minimal working example.

rm(list=ls())

library(shiny)

doshiny <- function() {
  app=shinyApp(
    ui = fluidPage(
      textInput("textfield", "Insert some text", value = "SomeText")
    ),
    server = function(input, output, session) {
      session$onSessionEnded(function() {
        stopApp()
      })
    }
  )
  runApp(app)
}

openshiny <- function() {
  doshiny()
  print("Finished.")
}

openshiny()
DoubleYou
  • 1,057
  • 11
  • 25
  • 3
    This is a bad idea! If multiple users are connected to the app, then one user (or browser tab) exiting will cause everyone to be kicked off! – Joe Cheng Aug 07 '20 at 19:23
  • agree to @JoeCheng This is not good – zhang jing Mar 23 '22 at 15:46
  • 4
    While not the best solution for multiple users, it is one that closes (and stops) the app as the OP requested. The solution is one I implemented myself for locally running apps where I am the only user - and it works. If you do have a better idea that takes multi user into account, I would suggest posting a correct answer instead of posting "bad idea" or "not good". – DoubleYou Mar 24 '22 at 16:49
8

I found this excellent code which does the job. Basically, you do like so:

library(shiny)
library(shinyjs)

jscode <- "shinyjs.closeWindow = function() { window.close(); }"

ui <- fluidPage(
  useShinyjs(),
  extendShinyjs(text = jscode, functions = c("closeWindow")),
  actionButton("close", "Close window")
)

server <- function(input, output, session) {
  observeEvent(input$close, {
    js$closeWindow()
    stopApp()
  })
}

shinyApp(ui, server)

Note though that closing the browser window through JavaScript may be prohibited. But this is another discussion.

Community
  • 1
  • 1
untill
  • 1,513
  • 16
  • 20
3

I have added this inactivity JS code to help me with some of my shiny apps which are IDLE. The code is pretty much self explanatory where I track down the mouse movements and clicks. Note that this app will close after 5 seconds.

library(shiny)
library(leaflet)

inactivity <- "function idleTimer() {
  var t = setTimeout(logout, 5000);
  window.onmousemove = resetTimer; // catches mouse movements
  window.onmousedown = resetTimer; // catches mouse movements
  window.onclick = resetTimer;     // catches mouse clicks
  window.onscroll = resetTimer;    // catches scrolling
  window.onkeypress = resetTimer;  //catches keyboard actions

  function logout() {
    window.close();  //close the window
  }

  function resetTimer() {
    clearTimeout(t);
    t = setTimeout(logout, 5000);  // time is in milliseconds (1000 is 1 second)
  }
}
idleTimer();"


ui <- fluidPage(
  tags$script(inactivity),  
  actionButton("recalc","recalc"),
  leafletOutput("mymap")

)

server <- shinyServer(function(input,output,session){

  points <- eventReactive(input$recalc, {
    cbind(rnorm(40) * 2 + 13, rnorm(40) + 48)
  }, ignoreNULL = FALSE)

  output$mymap <- renderLeaflet({
    leaflet() %>%
      addProviderTiles(providers$Stamen.TonerLite,options = providerTileOptions(noWrap = TRUE)) %>% 
      addMarkers(data = points())
  })

})
runApp(list(ui = ui, server = server))
Pork Chop
  • 28,528
  • 5
  • 63
  • 77
  • 1
    Hey @Pork Chop, in your server.R you have input$recalc. Where is this input$recalc coming from? I do not see any user input with id = "recalc". Thanks. – Jordan Wrong Oct 04 '19 at 04:18
  • @JordanWrong I've added the button, it was arbitrary as it wasnt needed for this question – Pork Chop Oct 04 '19 at 07:21