fluttertizensamsung-smart-tvtizen-native-apptizen-studio

Remote Control in Flutter Tizen Native TV App


We have developed a Flutter native app for Tizen, featuring two webviews that load YouTube.com and Netflix.com, covering the entire screen in splits. We have successfully deployed and run the app on the TV, with the webviews loading properly. However, we are facing an issue where we cannot use the TV’s remote control to navigate through the content in the webviews. Interestingly, when we connect an external mouse via USB, we can see the cursor, and navigation works seamlessly.

We are seeking guidance on how to add a cursor, similar to the one in the Internet/Browser app, that can be used to navigate through the content in the webviews.

Any assistance or suggestions would be greatly appreciated.


Solution

  • for anyone seeing these answer in feature check the how-to-use-the-remote-control-in-flutter-or-activate-a-controller-on-the-tv and raw-key-board-listener-flutter ,because by the time you read this answer this already posted answer may have added some better points.

    now 1st you need to listen for remote control events in the flutter app and then look for the events and do the performance accordingly .

    in the below code i tried to answer you question but i have not tried the below code by self so pleas comment the result if it solves the issue or not ,so that other can have ease .

        RawKeyboardListener(
          focusNode: FocusNode(),
          onKey: (RawKeyEvent event) {
          if (event is RawKeyDownEvent) {
            if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
              //code to mov cursor to up
            } else if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
              //mov cursor to down
            } else if (event.logicalKey == LogicalKeyboardKey.arrowLeft) {
              //mov cursor to left
            } else if (event.logicalKey == LogicalKeyboardKey.arrowRight) {
              //mov cursor to right
            }
          }
        },
          child: WebView(WebViewController _controller;
    
    WebView(
      onWebViewCreated: (WebViewController controller) {
        _controller = controller;
      },
    )
    
    
    _controller.scrollBy(x: deltaX, y: deltaY);
          ),)
    

    as i already said i did not run and check the code so i welcome any edit or suggestion from any one .

    EDIT:

    for perform select/click event use the below approch;

        if(event is RawKeyUpEvent){//as far as i know it should be in RawKeyUpEvent but if did not work then try to log the event 
    //or simply try with RawKeyDownEvent  
        if(event.logicalKey == LogicalKeyboardKey.select){
        //perform click logic
        }
        } 
    

    you can put this code in the same onKey: (RawKeyEvent event) if else logic to use.

    as a addon/alternat to above answer please take a look at following block (from LogicalKeyboardKey-class and adding it here to make sure feature ability of this content).

    RawKeyEvent: the keyboard event object received by widgets that listen to keyboard events.

    Focus.onKey: the handler on a widget that lets you handle key events.

    RawKeyboardListener: a widget used to listen to keyboard events (but not handle them).

        import 'package:flutter/foundation.dart';
        import 'package:flutter/material.dart';
        import 'package:flutter/services.dart';
        
        /// Flutter code sample for [LogicalKeyboardKey].
        
        void main() => runApp(const KeyExampleApp());
        
        class KeyExampleApp extends StatelessWidget {
          const KeyExampleApp({super.key});
        
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(title: const Text('Key Handling Example')),
                body: const MyKeyExample(),
              ),
            );
          }
        }
        
        class MyKeyExample extends StatefulWidget {
          const MyKeyExample({super.key});
        
          @override
          State<MyKeyExample> createState() => _MyKeyExampleState();
        }
        
        class _MyKeyExampleState extends State<MyKeyExample> {
          // The node used to request the keyboard focus.
          final FocusNode _focusNode = FocusNode();
          // The message to display.
          String? _message;
        
          // Focus nodes need to be disposed.
          @override
          void dispose() {
            _focusNode.dispose();
            super.dispose();
          }
        
          // Handles the key events from the Focus widget and updates the
          // _message.
          KeyEventResult _handleKeyEvent(FocusNode node, RawKeyEvent event) {
            setState(() {
              if (event.logicalKey == LogicalKeyboardKey.keyQ) {
                _message = 'Pressed the "Q" key!';
              } else {
                if (kReleaseMode) {
                  _message =
                      'Not a Q: Pressed 0x${event.logicalKey.keyId.toRadixString(16)}';
                } else {
                  // As the name implies, the debugName will only print useful
                  // information in debug mode.
    //pass the if else logic here for/as key press event you want to
    
                  _message = 'Not a Q: Pressed ${event.logicalKey.debugName}';
                }
              }
            });
            return event.logicalKey == LogicalKeyboardKey.keyQ
                ? KeyEventResult.handled
                : KeyEventResult.ignored;
          }
        
          @override
          Widget build(BuildContext context) {
            final TextTheme textTheme = Theme.of(context).textTheme;
            return Container(
              color: Colors.white,
              alignment: Alignment.center,
              child: DefaultTextStyle(
                style: textTheme.headlineMedium!,
                child: Focus(
                  focusNode: _focusNode,
                  onKey: _handleKeyEvent,
                  child: ListenableBuilder(
                    listenable: _focusNode,
                    builder: (BuildContext context, Widget? child) {
                      if (!_focusNode.hasFocus) {
                        return GestureDetector(
                          onTap: () {
                            FocusScope.of(context).requestFocus(_focusNode);
                          },
                          child: const Text('Click to focus'),
                        );
                      }
                      return Text(_message ?? 'Press a key');
                    },
                  ),
                ),
              ),
            );
          }
        }
    

    going through native/flutter could be helpful .