[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"blog-content-flutter-offline-playback-for-video-player":3},"\u003Cp>\u003Cem>This is the follow-up to \u003Ca href=\".\u002Fflutter-packages-and-plugins-a-quick-primer\">Flutter Packages and Plugins: A Quick Primer\u003C\u002Fa>.\u003C\u002Fem>\u003C\u002Fp>\n\u003Cp>In this story we will cover how I approached adding offline playback of HLS streams to one of our mobile apps.\u003C\u002Fp>\u003Chr>\u003Cp>Last story I promised to write about modifying an endorsed federated plugin in Flutter — so here we go.\u003Cbr>Along the way we will learn about alternative repositories to pub.dev and how to utilize them, as well as utilizing pigeon for type safe PlatformChannel communication.\u003C\u002Fp>\u003Ch3 id=\"step-1-idea-and-research\">Step 1: Idea and Research\u003C\u002Fh3>\u003Cp>As already noted, we use HLS for playback in our app.\u003Cbr>The first thought that came to my mind was: \"I'll just download the m3u8 playlist and all relevant chunks to some place on the filesystem, that should be fairly easy.\"\u003C\u002Fp>\u003Cp>Ha, of course not.\u003C\u002Fp>\u003Cp>While this approach works on Android, you quickly find out that it does not on iOS.\u003Cbr>See following references:\u003Cbr>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F101166\" rel=\"nofollow noopener\">https:\u002F\u002Fgithub.com\u002Fflutter\u002Fflutter\u002Fissues\u002F101166\u003C\u002Fa>\u003Cbr>\u003Ca href=\"https:\u002F\u002Fdeveloper.apple.com\u002Fforums\u002Fthread\u002F69357\" rel=\"nofollow noopener\">https:\u002F\u002Fdeveloper.apple.com\u002Fforums\u002Fthread\u002F69357\u003C\u002Fa>\u003C\u002Fp>\u003Cp>It turns out there is a dedicated API not only in the iOS SDK but also in the Android SDK for this task, which is not implemented by any open source player atm (afaik), despite my fork ;-)\u003C\u002Fp>\u003Ch3 id=\"step-2-getting-familiar-with-the-native-apis\">Step 2: Getting familiar with the native API's\u003C\u002Fh3>\u003Cp>This step is mostly about reading docs and trying the official samples.\u003Cbr>One very viable approach is to write a very simple application which does just the minimal work to utilize the necessary APIs.\u003C\u002Fp>\u003Cp>Once you do that, you will gather enough knowledge to procede with the real implementation.\u003C\u002Fp>\u003Cp>I used following resources to get an understanding of what to do and how to do it:\u003Cbr>\u003Ca href=\"https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Farchive\u002Fdocumentation\u002FAudioVideo\u002FConceptual\u002FMediaPlaybackGuide\u002FContents\u002FResources\u002Fen.lproj\u002FHTTPLiveStreaming\u002FHTTPLiveStreaming.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002FTP40016757-CH11-SW3\" rel=\"nofollow noopener\">https:\u002F\u002Fdeveloper.apple.com\u002Flibrary\u002Farchive\u002Fdocumentation\u002FAudioVideo\u002FConceptual\u002FMediaPlaybackGuide\u002FContents\u002FResources\u002Fen.lproj\u002FHTTPLiveStreaming\u002FHTTPLiveStreaming.html#\u002F\u002Fapple_ref\u002Fdoc\u002Fuid\u002FTP40016757-CH11-SW3\u003C\u002Fa>\u003Cbr>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fgoogle\u002FExoPlayer\u002Ftree\u002Frelease-v2\u002Fdemos\u002Fmain\" rel=\"nofollow noopener\">https:\u002F\u002Fgithub.com\u002Fgoogle\u002FExoPlayer\u002Ftree\u002Frelease-v2\u002Fdemos\u002Fmain\u003C\u002Fa>\u003C\u002Fp>\u003Ch3 id=\"step-3-implementing-the-flutternative-bridge\">Step 3: Implementing the flutter\u002Fnative bridge\u003C\u002Fh3>\u003Cp>Originally I wanted to implement the offline feature as part of a separate plugin based on the video_player plugin, but I couldn't figure out how to share objects in a good way, where I could keep changes to video_player either non-invasive or ideally not make changes to video_player at all.\u003Cbr>So I ended up adding methods for download management to the video_player interface instead. Which is invasive but at least does not require an additional plugin and was easy to do.\u003C\u002Fp>\u003Ch4 id=\"pigeon\">Pigeon\u003C\u002Fh4>\u003Cp>The video_player plugin is using the Pigeon package to create type safe messages for the PlatformChannel.\u003C\u002Fp>\u003Cp>While it looked complicated at a first glance, it's actually fairly easy to use: You create your message, run the pigeon command and it will put glue code to the correct places.\u003Cbr>Read more here: \u003Ca href=\"https:\u002F\u002Fpub.dev\u002Fpackages\u002Fpigeon\" rel=\"nofollow noopener\">https:\u002F\u002Fpub.dev\u002Fpackages\u002Fpigeon\u003C\u002Fa>\u003C\u002Fp>\u003Ch3 id=\"step-4-adding-the-native-implementation\">Step 4: Adding the native implementation\u003C\u002Fh3>\u003Cp>Once you can talk between the flutter and native code, it's time to add the platform specific native implementations.\u003Cbr>There is not much to explain here, if you have iOS background in swift\u002Fobjective-c or kotlin\u002Fjava you will know what to do, if not, well welcome to the club you have to fight your way through :-)\u003C\u002Fp>\u003Cp>You can find the full sourcecode here: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fa1rwulf\u002Fflutter_packages\u002Ftree\u002Ffeature_offline-playback\" rel=\"nofollow noopener\">https:\u002F\u002Fgithub.com\u002Fa1rwulf\u002Fflutter_packages\u002Ftree\u002Ffeature_offline-playback\u003C\u002Fa>\u003C\u002Fp>\u003Ch3 id=\"step-5-publishing-the-package-and-add-it-to-your-own-application\">Step 5: Publishing the package and add it to your own application\u003C\u002Fh3>\u003Cp>For those that checked out the code, you'll see there are some hacky parts included, so instead of renaming the plugin and publishing it to \u003Ca href=\"https:\u002F\u002Fpub.dev\u002F\" rel=\"nofollow noopener\">https:\u002F\u002Fpub.dev\u002F\u003C\u002Fa> I decided to use an alternative pub.dev implementation for my usecase.\u003C\u002Fp>\u003Cp>After a bit of research I decided to go for \u003Ca href=\"https:\u002F\u002Fcloudsmith.io\u002F\" rel=\"nofollow noopener\">https:\u002F\u002Fcloudsmith.io\u003C\u002Fa> which turned out to be quite easy to use.\u003Cbr>Just register and create your repository, flutter already allows usage of \u003Cstrong>third party pub.dev\u003C\u002Fstrong> implementations using the \u003Cstrong>\u003Cem>publish_to\u003C\u002Fem>\u003C\u002Fstrong> directive in your plugin. To reference a privately hosted plugin, there is the \u003Cstrong>\u003Cem>hosted\u003C\u002Fem>\u003C\u002Fstrong> directive.\u003C\u002Fp>\u003Cp>Here is an example:\u003Cbr>\u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fa1rwulf\u002Fflutter_packages\u002Fcommit\u002F705f7492efb4bbbf5be5157196a5e2ad69a683b1\" rel=\"nofollow noopener\">https:\u002F\u002Fgithub.com\u002Fa1rwulf\u002Fflutter_packages\u002Fcommit\u002F705f7492efb4bbbf5be5157196a5e2ad69a683b1\u003C\u002Fa>\u003C\u002Fp>\u003Cp>If you want to give the package a try, feel free to use either video_player directly or our custom chewie version that depends on our video_player fork: \u003Ca href=\"https:\u002F\u002Fcloudsmith.io\u002F~seadev-studios-gmbh\u002Frepos\u002Fseadev\u002Fpackages\u002Fdetail\u002Fdart\u002Fchewie\u002F1.7.2\u002Fa=noarch\u002F\" rel=\"nofollow noopener\">https:\u002F\u002Fcloudsmith.io\u002F~seadev-studios-gmbh\u002Frepos\u002Fseadev\u002Fpackages\u002Fdetail\u002Fdart\u002Fchewie\u002F1.7.2\u002Fa=noarch\u002F\u003C\u002Fa>\u003C\u002Fp>\u003Ch3 id=\"future\">Future\u003C\u002Fh3>\u003Cp>Eventually I will pick up the endavour to rework the code and make an effort to upstream it to \u003Cstrong>video_player\u003C\u002Fstrong> or create a more offical package on \u003Cstrong>pub.dev\u003C\u002Fstrong> to include offline playback, but for the time being, it serves my usecase pretty well.\u003C\u002Fp>\u003Cp>I hope you enjoyed the read and it will help you do your own forks of official packages.\u003Cbr>It was my very first modification of a flutter package, so don't be afraid to take on the challenge and implement new features to existing packages, even if you cannot make it generic enough to be upstreamed right away.\u003C\u002Fp>"]