使用 DisplayManager 或 MediaRouter 实现 Flutter 多屏

Dan*_*nha 2 android display-manager flutter mediarouter presentation-api

我正在 Flutter 中开发一个应用程序,该应用程序应该在具有两个屏幕的 POS上运行。它基本上是一个通过 HDMI 电缆连接到另一个屏幕的平板电脑。

我的问题是,我在屏幕一侧运行的任何内容也会出现在客户端的屏幕上,我需要隐藏它并显示其他内容(例如促销)。

我已经成功地使用Android 演示 API来使用它(它只能在 Android 上运行)。我在某处读到我也可以使用媒体路由器来实现它。

但我想做的是运行 Flutter 的两个引擎,每个显示器上一个,或者控制 Flutter 中每个显示器中显示的内容。问题是我没有找到任何关于如何在 Flutter 上执行此操作的库或有用的文章。

有人知道我将如何实现这一目标吗?如果我做不到,我将不得不使用原生 Android 创建一个全新的项目。

Dan*_*nha 5

对于那些可能面临这个问题的人,我终于找到了解决方法。我仍在使用Android Presentation API,现在我正在为客户端显示创建一个新引擎。我用FlutterView解决了这个问题解决了这个问题,这还很新。它基本上用于在 Native 应用程序中渲染 Flutter。但在我们的例子中,它将在另一个屏幕上渲染我们的项目。

\n\n

我尚未解决的唯一问题是这两个引擎是完全不同的应用程序。所以,如果您正在使用Provider来管理应用程序状态,则您将拥有两个或更多实例,每个实例一个,并且其中一个实例中所做的更改不会反映其他实例。

\n\n

就我而言,我将使用 Socket.io 解决它,但您也可能使用Method Channel解决它解决它。理想情况下,它应该只有一种状态,但现在这就是我所拥有的。

\n\n

这是我解决这个问题的代码:

\n\n

MainActivity.ktAndroid/app/src/main/kotlin 中的

\n\n
package com.example.fsj_pdv\n\nimport android.content.Context\nimport android.hardware.display.DisplayManager\nimport android.os.Build\nimport android.os.Bundle\nimport androidx.annotation.NonNull;\nimport io.flutter.embedding.android.FlutterActivity\nimport io.flutter.embedding.engine.FlutterEngine\nimport io.flutter.plugins.GeneratedPluginRegistrant\n\nclass MainActivity: FlutterActivity() {\n    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {\n        GeneratedPluginRegistrant.registerWith(flutterEngine);\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setSecondDisplay()\n    }\n\n    private fun setSecondDisplay() {\n        try {\n            // Versions before Jelly Bean doesn\'t support it\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n                val manager = applicationContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager\n\n                // Busca os monitores dispon\xc3\xadveis\n                val displays = manager.displays\n\n                // Verifica se foi encontrado mais de um monitor. Caso encontre, instancia a Activity de Presentation\n                if (displays.size > 1) {\n                    val display = displays[1]\n                    val handler = PresentationHandler(this, display)\n                    handler.show()\n                }\n            }\n        } catch (e: Throwable) {\n            println(e.message)\n            e.printStackTrace()\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我为解决问题而创建的类(在同一文件夹中)。这个类的目的基本上是设置我们的演示显示并选择将包含我们的 FlutterView 的内容视图。

\n\n
package com.example.fsj_pdv\n\nimport android.annotation.TargetApi\nimport android.app.Presentation\nimport android.content.Context\nimport android.os.Build\nimport android.os.Bundle\nimport android.view.Display\nimport io.flutter.embedding.android.FlutterView\nimport io.flutter.embedding.engine.FlutterEngine\nimport io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint\n\n\n@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)\nclass PresentationHandler(outerContext: Context?, display: Display?) : Presentation(outerContext, display) {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        // Instantiate a FlutterEngine.\n        val flutterEngine = FlutterEngine(context)\n\n        // Configure an initial route.\n        flutterEngine.navigationChannel.setInitialRoute("/cliente")\n\n        // Start executing Dart code to pre-warm the FlutterEngine.\n        flutterEngine.dartExecutor.executeDartEntrypoint(DartEntrypoint.createDefault())\n\n        setContentView(R.layout.presentation_view)\n\n        val flutterView: FlutterView = findViewById(R.id.flutter_presentation_view)\n        flutterView.attachToFlutterEngine(flutterEngine)\n    }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后,创建一个简单的布局,它将在第二个/外部显示器中呈现我们的应用程序。这是我的布局(presentation_view.xml):

\n\n
package com.example.fsj_pdv\n\nimport android.content.Context\nimport android.hardware.display.DisplayManager\nimport android.os.Build\nimport android.os.Bundle\nimport androidx.annotation.NonNull;\nimport io.flutter.embedding.android.FlutterActivity\nimport io.flutter.embedding.engine.FlutterEngine\nimport io.flutter.plugins.GeneratedPluginRegistrant\n\nclass MainActivity: FlutterActivity() {\n    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {\n        GeneratedPluginRegistrant.registerWith(flutterEngine);\n    }\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setSecondDisplay()\n    }\n\n    private fun setSecondDisplay() {\n        try {\n            // Versions before Jelly Bean doesn\'t support it\n            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {\n                val manager = applicationContext.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager\n\n                // Busca os monitores dispon\xc3\xadveis\n                val displays = manager.displays\n\n                // Verifica se foi encontrado mais de um monitor. Caso encontre, instancia a Activity de Presentation\n                if (displays.size > 1) {\n                    val display = displays[1]\n                    val handler = PresentationHandler(this, display)\n                    handler.show()\n                }\n            }\n        } catch (e: Throwable) {\n            println(e.message)\n            e.printStackTrace()\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n