You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用shinyMobile开发的Shiny应用能否上架谷歌Play及苹果App Store?

能否将shinyMobile开发的Shiny应用发布到谷歌Play商店和苹果App Store?

我用shinyMobile包开发了一款Shiny应用,之前开发的都是常规Shiny应用,现在想知道能不能把这个shinyMobile应用作为普通应用发布到谷歌Play商店和苹果App Store。我试过相关操作,但没找到满意的解决方案。以下是我的应用代码:

library(shinyMobile)

if(interactive()){
  library(shiny)
  library(shinyMobile)
  library(shinyWidgets)
  
  shinyApp(
    ui = f7Page(
      title = "Tab layout",
      f7TabLayout(
        tags$head(
          tags$script(
            "$(function(){
               $('#tapHold').on('taphold', function () {
                 app.dialog.alert('Tap hold fired!');
               });
             });
             "
          )
        ),
        panels = tagList(
          f7Panel(title = "Left Panel", side = "left", theme = "light", "Blabla", effect = "cover"),
          f7Panel(title = "Right Panel", side = "right", theme = "dark", "Blabla", effect = "cover")
        ),
        navbar = f7Navbar(
          title = "Tabs",
          hairline = FALSE,
          shadow = TRUE,
          leftPanel = TRUE,
          rightPanel = TRUE
        ),
        f7Tabs(
          animated = FALSE,
          swipeable = TRUE,
          f7Tab(
            tabName = "Tab1",
            icon = f7Icon("envelope"),
            active = TRUE,
            f7Shadow(
              intensity = 10,
              hover = TRUE,
              f7Card(
                title = "Card header",
                f7Stepper(
                  "obs1",
                  "Number of observations",
                  min = 0,
                  max = 1000,
                  value = 500,
                  step = 100
                ),
                plotOutput("distPlot1"),
                footer = tagList(
                  f7Button(inputId = "tapHold", label = "My button"),
                  f7Badge("Badge", color = "green")
                )
              )
            )
          ),
          f7Tab(
            tabName = "Tab2",
            icon = f7Icon("today"),
            active = FALSE,
            f7Shadow(
              intensity = 10,
              hover = TRUE,
              f7Card(
                title = "Card header",
                f7Select(
                  inputId = "obs2",
                  label = "Distribution type:",
                  choices = c(
                    "Normal" = "norm",
                    "Uniform" = "unif",
                    "Log-normal" = "lnorm",
                    "Exponential" = "exp"
                  )
                ),
                plotOutput("distPlot2"),
                footer = tagList(
                  f7Button(label = "My button", href = "https://www.google.com"),
                  f7Badge("Badge", color = "orange")
                )
              )
            )
          ),
          f7Tab(
            tabName = "Tab3",
            icon = f7Icon("cloud_upload"),
            active = FALSE,
            f7Shadow(
              intensity = 10,
              hover = TRUE,
              f7Card(
                title = "Card header",
                f7SmartSelect(
                  inputId = "variable",
                  label = "Variables to show:",
                  c("Cylinders" = "cyl",
                    "Transmission" = "am",
                    "Gears" = "gear"),
                  multiple = TRUE,
                  selected = "cyl"
                ),
                tableOutput("data"),
                footer = tagList(
                  f7Button(label = "My button", href = "https://www.google.com"),
                  f7Badge("Badge", color = "green")
                )
              )
            )
          )
        )
      )
    ),
    server = function(input, output) {
      output$distPlot1 <- renderPlot({
        dist <- rnorm(input$obs1)
        hist(dist)
      })
      
      output$distPlot2 <- renderPlot({
        dist <- switch(
          input$obs2,
          norm = rnorm,
          unif = runif,
          lnorm = rlnorm,
          exp = rexp,
          rnorm
        )
        
        hist(dist(500))
      })
      
      output$data <- renderTable({
        mtcars[, c("mpg", input$variable), drop = FALSE]
      }, rownames = TRUE)
    }
  )
}

可行的解决方案

  • 核心逻辑:Shiny应用本质是Web应用,要发布到应用商店,需将其封装进原生App的WebView容器中,同时处理Shiny的服务端依赖——要么把Shiny服务器部署在云端让App远程访问,要么用shinylive将应用全前端化,实现离线运行。

  • 谷歌Play商店打包步骤:

    1. 用Android Studio创建原生Android项目,通过WebView组件加载你的Shiny应用云端部署地址(比如shinyapps.io、自有服务器)。
    2. 配置网络权限、WebView缓存策略等,优化加载速度和原生体验。
    3. 按照Google要求生成签名APK/App Bundle,提交至Play商店审核。
    4. 若用shinylive,可将生成的静态文件放入Android项目的assets目录,让WebView加载本地文件实现离线运行。
  • 苹果App Store打包步骤:

    1. 用Xcode创建iOS项目,通过WKWebView加载Shiny应用的云端地址或shinylive静态文件。
    2. 注意苹果审核规则:单纯封装Web应用可能被拒,需确保App具备原生增强功能(比如调用设备传感器、本地存储),或Web应用本身有独特价值。
    3. 完成权限配置、签名、隐私政策上传等流程后,提交至App Store Connect审核。
  • 关键注意事项:

    • 云端部署的Shiny应用需保证稳定性和访问速度,避免影响App用户体验。
    • 使用shinylive前,要确认应用所有功能都支持前端运行(部分复杂R包可能不兼容),可先通过shinylive::export()生成静态文件测试。
    • 提交前务必查阅应用商店最新开发者指南,避免因不符合规则被拒。

内容的提问来源于stack exchange,提问作者neves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:15:07