Skip to content

Flutter demo application for Apple TV (tvos) using custom Flutter engine

License

Notifications You must be signed in to change notification settings

LibertyGlobal/flutter-tvos-demo

Repository files navigation

Flutter app on Apple TV

Flutter for Apple TV

A modification of the Flutter engine test application to demonstrate that Flutter applications run on Apple TV

This project (and Liberty Global repositories referred to) are for testing purposes only!

Flutter and the related logo are trademarks of Google LLC We are not endorsed by or affiliated with Google LLC.

Approach:

  • Engine:
  • Framework
    • No modifications in "flutter" tool (/framework)
    • Platform tvos not supported, ios target cannot be used because without modifications it would the use wrong SDK(ios) to compile the application
  • Application
    • Changes compared to ios application setup:
      • Modified main storyboard
      • Icon set for tvos
      • Custom script to compile application which replaces code_backend.sh in the “build phases” step. This script is based on scripts from the engine test application which only use tools from the engine. The normal script cannot be used because it used the standard “flutter” tool which does not support tvos.
    • Copy generated resources from real ios app target. The test app target actually overwrites the ios build to use the resources.
    • Change targets for application and pods to ‘tvos’ and set minimum OS version to 12.0

Known limitations

  • Not all pods will compile. ios target is used and some API's are not supported by tvos. E.g. WebView
  • No debugging capabilities
  • No Apple TV look and feel widgets, no integration of virtual keyboard, ...
  • Resource monitoring is not supported by tvos (using flutter tools)

Known Issues

  • When a debug version is installed on a simulator or Apple TV device, then the app will not load when selected on screen. It will only load from the xcode debugger. This is not an issue for release builds. This has most likely to do with the fact that the app is trying to connect to 127.0.0.1 which is not started because the flutter tools are not used.

Supported devices

  • Apple tvOS 12.0 or later

Workarounds

  • Disabled fork commands etc. in process_macos.cc
  • Disabled fatal error in kernel_translation_helper.cc, still to be investigated what the root cause is

Setting up engine / development environment

Compiling the engine

  • The script will build 5 targets for TVOS in the src/out folder:
    • ios_debug_unopt, ios_debug_sim_unopt, ios_release, host_debug_unopt and host_release release
  • Note: Fectching all repositories and compiling the engine for Apple TV (all targets) requires at leaste 29Gb of free diskspace!
  • Run in /engine/src/ script sh ninja_build.sh (located in script folder, see ninja_build.sh)
    • Add paramter clean for a full rebuild.
    • Note: The --no-lto flag can be removed on host systems with minimum 32Gb
  • Based on: https://github.com/flutter/flutter/wiki/Compiling-the-engine. The problem with the order described on this wiki is that the generated files for the host point to the ios/tvos sdk instead of macos

Compiling application

  • 1st build real ios target to make sure the resources(images, fonts, ...) are generated by the flutter tools and can be used for tvos
    • Open ios/Runner.xcworkspace and set signing team and bundle identifier
    • Run command: flutter build ios
  • Note: the application will regardless of the target, always be compiled to /build/ios/Release-iphoneos. The main reasone for this is that the resouces generated by the normal ios build are located here and are re-used.
    • This means that if any of the resource will change, added or removed that normal ios build must be done first. In order to do this, the step below must be un done first!
  • Rename tvos folder to ios
    • Flutter tools assume the folder name is ios. Flutter pub get will fail if the folder has a different name!
    • Run command: sh scripts/switch_target.sh tvos
    • (to switch back to ios: sh scripts/switch_target.sh ios)
  • Run command: flutter pub get
  • Go to ios folder
  • Install/get cocoa pods
    • Run command: pod install
    • Pods target is automatically corrected from ios to tvos in podfile post_install step
  • Set path to local compiled flutter engine in FLUTTER_LOCAL_ENGINE (src folder) enviroment variable
  • Copy flutter framework to pods
    • Run command: sh ../scripts/copy_framework.sh debug_sim
    • Copies debug simulator version. The correct version (debug, sim, release/archive) will be copied during app compilation
    • Unfortunately this is a manual step, because the pods are compiled first as a dependency by xcode and there is no hook in the xcode build process before this to automatically copy the right frame work to be used based on the selected target
  • Open in ios folder Runner.xcworkspace
    • In settings, set signing team and bundle identifier
    • Set path to local compiled flutter engine in FLUTTER_LOCAL_ENGINE (src folder)
    • e.g. FLUTTER_LOCAL_ENGINE = <your local path to flutter engine>/engine/src
    • alternatively run: sed -i '' "s#FLUTTER_LOCAL_ENGINE[[:space:]]=[[:space:]].*;#FLUTTER_LOCAL_ENGINE = \"${FLUTTER_LOCAL_ENGINE}\";#g" Runner.xcodeproj/project.pbxproj
  • Build app for device debug, simulator or archive (see switching target below)

Common issues

  • Engine

    • 3.3.10: in case compilation of libpng.pngread.o fails. Replace src/third_party/libpng/pngread.c with file pngread.c from patches folder
      • this only happens with newer compilers/SDK's
      • ../../third_party/libpng/pngread.c:3455:26: error: variable 'row' set but not used [-Werror,-Wunused-but-set-variable]
                 `png_bytep row = png_voidcast(png_bytep, display->first_row);
        
  • Application

    • If compilation fails because of this reason:
      Showing Recent Messages
      Ignoring file /Users/../tvos-demo/ios/Flutter/Flutter.framework/Flutter, building for tvOS Simulator-x86\_64 but attempting to link with file built for tvOS-arm64
      Undefined symbol: _OBJC_CLASS_$_FlutterError
      Undefined symbol: _OBJC_CLASS_$_FlutterMethodChannel
      Undefined symbol: _FlutterMethodNotImplemented
      • When switching between targetes (simulator <=> debug/release), then the correct framework must be copied / updated
      • This can be solved by copy the correct version of the framework to the flutter folder
        • sh scripts/copy_framework.sh <target> <path to local flutter engine>
        • Targets: debug, debug_sim, release
    • Switching between targets: simulator(debug), debug (on Actual AppleTV device) & Release/archive
      • First "Clean build folder" in Xcode
      • Copy to be used framework (See above)
      • Build / Archive
    • Distribution / Validation in Organizer fails
      • Check if both ios_deployment_target & MinimumOSVersion in the engine and app match. Both must be 12.0!
        • The info.plist file is copied from the engine to the flutter.framework folder and contains 12.0

Contributors

Jürgen Wölke, Prikshit Chahar, Andrei Lesnitsky
v2.0.4: Aleksandr Denisov, Oleksandr Prokhorenko, Maksim Nazaruk, Andrei Kulbeda
v2.10.3: Aleksandr Denisov, Maksim Nazaruk, Andrei Kulbeda
v3.3.10: Aleksandr Denisov, Andrei Kulbeda, Jürgen Wölke v3.10.6: Eldar Pikunov, Jürgen Wölke