home_widget | Observable Flutter #57
[Music] hello everyone and welcome to another episode of observable flutter I'm your host Craig leens and today we are going to be exploring the home widget package and all of the finishing touches all of the spit and polish that that can put on your flutter app to help it feel like the true native iOS or Android app that it is so I'm pretty excited to get into this I think these are kind of that I'm a big believer in the 8020 rule where the first 20% of your effort gets you 80% of the way there and then it's all of those those final details to see2 that last 20% of result that takes the final 80% of effort and the home widget package I think really expedites a part of that so I'm pretty excited to explore this um do recall folks that this is the flutter community and we are all here to treat each other Great learn some cool Tech and then get back to our lives so let's do that today's guest is the author of The Home widget package it would be inappropriate to have anyone else on to discuss it so Anton Boris he's worked with folks from Google before I'll let him explain some of that in just a second when uh Anton introduces himself so Anon welcome to observable flutter would you like to say a few words hello hello H yes um hi I'm Anton I'm based in Hamburg in Germany I work at 1A 5 um and as you mentioned I'm doing the home wiget package this is yeah exciting I'm I'm glad that you uh I'm glad glad that we're here talking about this so I teased a little bit a second ago that you had worked with some folks from Google before on this specifically from from the flutter team can you share a little bit about about that story and how it culminated in that big Cod Lab at IO connect am I remembering that correctly I I'm not sure it was at I connect was definitely codl um so yeah so I start Ed with home widget like I think now four years ago almost um and um when this went along and then I did other things because like time and then one day Leah back when she was still at Google uh approached me um because she wanted to do a Cod lab on it and had an idea of rendering flutter widgets through home widget which I guess we'll talk about in a minute as well uh and then uh through that whole journey there was the Cod lab um on the Google site um home widget was package of the week as well um which is a great video series I can recommend really um and then through this I um got more involved in the flutter Community went to a lot of conferences um uh and then really really enjoy that part of the the whole flut Community uh great I was just listening to you and trying to edit this setting so we could get socials up and then I realized that my social Blue Sky still shows before I added my domain so I'll worry about that in a second um okay yeah so you had uh so you've built out this package and worked with Leah on it a bit obviously she's over at flutter flow now and and we miss Leah dearly but flutter flow is a great place for her as well and um there's some some great questions in the chat that I think we are the appropriate place to start here where is the chat how a computer oh flutter forward um yes so Eric I I was saying to you a second ago Anton that Eric helped Leah present it but I guess you only talked with Leah but Eric was also very heavily involved so let's start from the absolute Bare Bones beginning here olami Ng asks what is the home widget for so what are we even talking about yes so I realized quite quite soon that it's it's really hard to to talk about home widget and home screen widgets in the flutter context without getting super confusing because everything is a widget except home widget I suppose um so so hom screen widgets uh you can really imagine at these helpers um on your home screen so I think really good examples is always like if you have your weather app that can show multiple like the weather forecast for a couple of days um on Android the clock is technically a home screen widget so basically everything you can place on your home screen widget uh on your home screen uh that is not just an app icon um and so this is really really helpful um because you can do a lot more stuff with with the hes screen widget and see a lot more information of your app um then you can convey through the app symbol alone and then um in the last year or so I think it's gotten more and more important also with product owners uh I I feel uh to have homes SCH midges because they got like a lot more serious um since Apple made them also interactive um so I think another really nice example for homes schol widgets um is like to-do list for example um that you can see like your recent to-do list list like your top five next toos and then you can just tick them off directly um on the hom screen m without having to go into the app to to actually complete the task yeah interesting I actually did not know that they had become interactive that's cool and I what was your reaction when you saw that feature announced and you I'm sure immediately understood you you had a lot of blanks to fill in what will the function name be that I have to implement but like you immediately understood the expansion of the complexity of your package when you saw that I mean the the good thing in that way was basically that on Android as far as I can tell since always home screen widgets have been interactive um and soared there was there was everything in place and on Android um home widget was already supporting interactivity and it then was just the course of watching um WWDC each year and seeing are they going to make homescreen videos on iOS interactive this year no uh next year the same question again and then I think it was in 20 what was it I think 22 I think they made The Homeschool or 20 or actually might might have even been last year I think it may have been only last year with iOS 17 um that they made it interactive and then it was clear for me that okay now I have to do to support it um which was a bit of a challenge because I'm my background before I did FL out both on the Android site so I always felt a bit more familiar with these Concepts um but got it working um and it's working super nicely and I think the solution I came up with is actually super great because um you can actually now call do code through home widget so um especially if you have a home screen widget for both platforms um You can call the dot code um from both sides um because I guess we we should tell this to everybody who gets excited to just say okay let's build home screen widget with FL um it's not super easy to do it with flatter directly because both platforms have a lot of limitations around homes screen widgets so in terms of how big can they be um in terms of really like size on dis um what can you actually display on this so it's not possible unfortunately to have um a flatter app really running inside of a homescreen widget um and like update intervals it's really unclear how often you can update a widget some people say it like once every 15 minutes but then again you can do it quicker but also you don't know whether they updated the widget for you or not um so it's really not ideal um and you have to do a bit of native code um but but still I think that as much flutter and that code you can use um the the bet is so you said It's tricky to do this with flutter and do you mean that is even with the package or if someone were to try to do it without the package I mean you you can totally do it without the package so in the end the the widgets you have to think about them as they are bundled really as like separate to your app like an app inside your app so on on um iOS for example it's really a separate Target you have to completely work with um and so what and you have to unfortunately do these things um on the native side in Native configurations this is just the limitations that the operating systems um have for these um what home widget um home widget um supports though is that really that it simplifies the way that you can send data from your app to the widgets um that you can trigger updates um of the widget form fletter um and then also I wrote a lot of documentation um to really like point you to the direction where do I have to click an Android Studio to make certain things work or hopefully work um because I think in the end um it's it's all doable and it it always sounds a bit scary to um to do oh no I have to to go into Android Studio or even worse into xcode and do some stuff on the native side um but I really think it's like you mentioned it's it's worth it for the benefits that it brings your product um your users um and I guess we'll do some some live coding later as well I think it's um it's not it's it sounds scary but it's not actually that scary and I personally think it's also like great to still like look at okay like how does this work on on the native side of things like in Swift UI in um in Android with jetpack and then um also like learn to love hot reload um again like like because you you will lose some some benefits um while developing a home screen widget and so when you get back to the flutter side of things and you can use S reload again um this is then you fell in love with hot whe just like the first time all right I'm super excited to see this come together and I've got a lot of I've got a lot of questions that I think are probably just you know they're only going to be answered by the actual code so it is potentially time to start building something out I know you've got your screen shared here is there anything else you'd like to say or any other setup that is maybe important to share before we start building um no so maybe quickly because I mentioned it earlier a bit about render flutter widgets um because I think this is quite the cool thing that Leah initially came up and then we worked on together um is that as I mentioned you can't display everything um inside of the home screen widget so you can only use certain components um certain features from the Native side of things one thing you can use however is images and so um what home widget offers is that you can pass any flut widget to home widget and then home widget take a screenshot of that widget um and send that to the native site and then it says you um the documentation says you how what you need to do in order to display then this image um on the home screen widget so if you have like a super fancy flutter widget you buil um you can then use that um screenshot of this um to display on the home screen widget and I think this helps a lot um to really get get started like super quickly as well yeah yeah and one of the so that that was my understanding of how it had always worked which is of course a little I I I I can't imagine off the top of my head exactly how that would mesh with an interactive widget but I'm sure we'll see that as we go so that's one question that is already you know is brewing in the back of my mind or I guess the front of my mind the other question and this is I think just a function of how both Android and and the folks at Apple for iOS design the API but from a flutter perspective right everything is declarative we just have unless there's a multi- window situation right you just have one which tree one main method one entry point and that declarative Loop is just going at all times and then anytime you need something this this feels imperative to me right the the operating system the host platform comes in and it's like hey got a home widget for me and it's like maybe the app's not even running when that happens you know so we're registering some other entry point in the background and you know I'm I'm curious what that actually looks like in practice so those are the two biggest questions that I have that I I'd really like to see or I'd like to explore I do have some star questions here so some have been answered does home widget need native code certainly does and I think we're going to see some of that um a question about performance which let's kind of cue unless it's a very simple answer we can cue this up for when we're looking at the code uh but this is a good question that I we should get to at some point and um yeah handful of folks also asking about flutter and production so that's an event that will be next week it's a live stream so there there there will be a live Q&A after the event for about 30 minutes or something and then but mainly flutter and production is you know the flutter team trying to tell a story about how flutter is ready for production apps of any size so we hope you'll okay but enough about that and and try to find if you find an extended or remote version so I'll be I think a lot of the flutter meeps are doing live streams so there will be for example in Hamburg um there will be one so for those in in the north of Germany um should come to flut Hamburg next week as well yeah absolutely there's those viewing parties I think will be pretty fun yeah I'm uh I'm always impressed by the FL community's ability to self-organize you know dozens 100 however many viewing parties all around the world it's pretty pretty darn cool so okay let's start building so your screen is here and we are looking at our app yes so um I thought let's let's use this this example I like the counter app as an example because most people know these example apps and so um let's first set us the goal that we have our counter widget and we can see what our current count or the last count is on a home screen widget on Android so it's basically everything is still the same um I did a a bit that the counter is nullable here and like a variable here um but what we what we can do first um because we'll we we are talking to home widget on platform channels so everything is a bit asynchronous so we make that method asynchronous um and as I said earlier is home widget handles the the data transfer because you have to think of your app lives here and then the home screen widget is like a more or less a second app it's like a separate process so um home widget offers a way to really have a nice data transfer between the widget the app um so let's see we can say that our counter value um we can say wait and then from home widget um by the way for completeness sakes um what you need to do flatter package you add the package to your dependencies and then we can say um get our widget data and then we use our counter um this is like a key that we will then be reusing on the on the native side again and then what we also can do we can say we give it a default value that if there's no uh widget data yet saved um or the user deleted all the data um then we we use zero um then we can say our new value that should be counter value let's let's use the exclamation point in this case um and we'll add one and then oh copilot is already helping me out thanks copilot so um we can say uh save so so we do get widget data to get data that's stored with home widget and we use Save widget data to save widget um to to save data to the widget and then um we can say update widget and here cop it is not as helpful um and we use the name um and and let's call this um um observable widget and where we'll need to reuse this name and will explain a bit later because we have to remember this name on the native side okay so I have a couple questions you said that counter is a string that we're going to reuse on the native side so there's no setup needed here there's no like other decare declaration file or config or anything where you establish counter like you could do ASDF some random string here you then just have to remember it on the native side that's all yes so um the way this works um is under the hood home widget uses um shared preferences on on Android and user defaults on iOS um which is the the same technology that um the shared preferences package for example also uses so it's a it's a really simple key value storage um and this is a a straightforward thing um that you can just use any string I think it's a string yes yeah okay if I can do it with any of no it's a it's a string yeah okay so you have did you so do does the home widget package make use of pigeon or or did you just write these method channels yourself I'm I'm guessing yes I'm I'm writing them myself um because as at least when I um started with home widget pigeon was I'm not sure if pigeon was even around or if it was like super super experimental and like with the yeah don't don't really use this yet and I'm also not not sure um back then at least it was that um I think pigeon wasn't bir directional um I think you couldn't I think you can only use method channels but no event channels um and um home widget uses both so I see okay so right now I did the the method channels myself yeah got it so first you're you're saving data so I'm guessing like get widget data and save widget data they are not actually using any kind of platform channels they're just saving to local to to Shared preferences and then is that yes or no I mean it's it's a no because so technically even if you use the shared preference package they use method channels to to talk with the site I mean I'm not sure if they might be migrated to ffi but uh so it's on the side of things um but I'm I'm also using like my own implementation of it to have really a separation of so that the widget data is not like mixed with other shared preferences you you might have yeah okay all right that's that's super Mak sense yeah so you didn't but you but you did right the M you just said okay so you've got share you've got a platform channel invocations here but they're actually not they're closer to Shared preferences maybe you're adding some name spaces or something you're just writing data that will be used later and then I'm guessing update widget is poking the native side and saying hey run run the method and then we got the method has to exist on the native side yes so well well it's so it's not really a method that needs to exist on the native site so um basically the both on Android and iOS um there are basically managers um for these home screen widgets um and what we basically or what home widget under the hood does for update widget is says to the operating system hey operating system um there's new data available for this widget observable widget or there other ways to to Define these um and basically and this is this is the the thing that I mentioned earlier you'll never know and the operating system doesn't let you know if it actually updated the widget so it might be that you say yeah please update this widget and the operating system says yes we'll do um but never actually does um okay so it's UDP not TCP yeah basically okay fire and forget all right cool so we've called these methods what do we do next um now we we go to the I mean we we can I guess uh use use with that so um right now ah I need to I added a new channel added this new so we have to run this one time fresh because the didn't know about home widget yet um so what we expect or at least I expect is that when we run it the first time it should count up from zero and then if we had restart it it should be I guess if we we move this make it nil null first um then the second time we count we should actually start with the count that we had so there's something upset here what H we wouldn't be doing it live if we didn't have an error so yes so um it's complaining that it doesn't have this widget that it can't update so it will complain if it can't find a widget to update so I suppose if way to out yeah one way to know that it tried to do something that is true okay so you can see the data is counting up and then if we if we do a h restart can see we we continue the count so the value is really St been persisted nice so let's get into the native side um and we'll need to do a couple of things um first so we'll start by adding a dependency on glands or jetpack glands which is basically so jetpack is everything with declarative UI on Android um so jetpack compose for example and then glance is the the package in Android that is used for homescreen widgets so um the even as a native Android developer you can't just use exactly the same codes and components um on a home screen widget that you can do um in your in your other app um so we'll need this um as a dependency so it's the build grader file of the app and then we'll add the dependency on on glance and then we'll need more things because yay invid um need to have build feature enabled I thought this declaration was just going to be the word build feature with no please build my feature that would be that would be really nice and then I'm pretty sure if we do this it will fail I don't want to update grade right now let me let me cheat a bit and actually cheating is the only way to live so um well I was goingon to ask I'll I'll just chitchat while you uh work on this so just ignore me if I'm distracting it finished oh it worked it worked I think oh great so what was the issue I think it I think it was uh this this compos option thing um that we had to add as well this is why everyone loves Gradle files so much yeah it's it's really really fun I did a workshop at the at the deest in London recently and somebody was using Gradle 2 and I let's let's just say I have to look into supporting Gradle 2 with home widget um oh boy as oh boy Randall said uh it would be nice if the boiler plate boiler plates could be automated perhaps with an installable bin tool that sounds like an incredibly challenging engineering task in itself it's so my this is this got bumped up my my internal road map a lot recently because we as you'll soon see we'll have to create a bit more boiler plate even but I believe a lot of these things could be um automated with Mason bricks so I'm never not sure if you had uh Felix yet on the show to talk talk about Mason oh yeah he was uh over two years ago probably an early gas yeah so yeah basically Mason is like a tool to automate boiler plates um I would say on a really high level it can do a lot more than this um but it's it's really great for for generating boiler plates um but then again how good it would be to figure out which of these things you'll need based on your Gradle version um remains probably to be seen um but um but yeah definitely and the hard part is like if they already have the compose options block with other things in it then you only need to add the key and like you know it's just oh goodness what a nightmare very very hard I think any anytime you have to open the Gradle file it's just like oh this isn't why I went into this [Laughter] career uh okay so so compos ready have our dependencies so once again as I mentioned often times doing something on the native SES makes you really appreciate stuff on flutter so just compare this this whole setup at nightmare to running pup at good great boy praise be yes so um next up we'll need a configuration file which um is a resource XML file and we can just call this configuration um and then we have really confusing UI so um I've not helped you by requesting the biggest font you've ever used um so we are having an app widget provider um and so this is for example the initial layout before the operating system has done anything with it and there the Android they they provide like a glance default loading layout which is like just a loading spinner on the on the middle of the screen which they propose in their documentation to use and I feel like that makes a lot of sense um you can Define stuff like your minimum and maximum Heights um so because on on Android homescreen widgets at least from both launchers I know um they are um fully resizable um and like you can free from them like on on iOS you have like four or five different sizes you can choose from MH but on Android um we'll soon see you can drag them around um and resize them how you want and this way you can restrict this a bit in terms of like making sure that your layout actually would work isn't totally totally Bonkers yeah um let's see if I'm not sure which more potential values are required but I'm sure it will let us know um but this is the configuration file and this is like a good example of what would be like super easily um be um hello asra uh simplified and and be possible with with Mason for example to automate adding this file y yep um and so now we go into our first cotlin file and this is now our AB widget and so what the app widget is um is basically the definition of the the view um so this should extend um the plance [Music] appdet and then remember when we added that the the glance oh sorry the the glance app widget this is coming from glance are you meant when we added glands or when we oh no I was just being silly I said I remember when we added that you're good you're good um and so we need to overwrite a function called provide glands um which so uh which will return basically the compos version of a widget tree um so we can say provide content and then we can say this is our glance content with context and something called current state and we can write as a composable function called glance content which will take in context and our current state and here the first time home widget comes around again um with the home widget gland state so um what what you mentioned earlier about like you can potentially have multiple widgets um on the home screen of different kinds um different apps or same app can have multiple different widgets um and basically what what happens is that whenever the operating system system feels like it or you can kindly request the operating system to to update the widget um the operating system will call um this provide glance method with a new so-called State um and the funny thing about glands is still relatively fresh in the stable version and before 1.0 it was really or there was not really that much documentation um on the official Android doc site um or even worse there was outdated documentation um and it was really unclear okay what do I actually need to do in order to have a a nice State um and so um or what actually needs to go into the state um however after like some stti overflow searches I finally found found the solution and was able to to wrap this quite nicely into home widget that um home widget can take care of all the state handling and give you with an object that you can actually use and use your um data that you sent there from flatter um so we have this home rigid glan State and we'll need to overwrite um something called the state definition and we'll have our home WID gland state definition yeah there is a there is a fair amount of of native code to write here uh Miss construct so but now we are in this glance content which you can think about um basically as your build method coming from the flutter set of things um so as I mentioned earlier I think I managed a nice solution to get to your widget data that you sent through flatter in this home widget Clan State um and thing is that on this current State you have now a variable called preferences and so these preferences are basically the shared preferences that home widget is saving data into um so we can say our counter can say from our preferences get an INT and this here is our counter key that we defined or used in here okay all right so basically we we store INF flatter we restore and and get data with the key counter and then in our build method more or less um we get this with the counter variable and we'll need to provide it a default value here as well and then we can say notice that there's no return I don't know why in cotland there doesn't need to be a return in here um but basically the last statement is treat as a return which yeah there's a fair amount of flut flutter feels a bit weird though yeah I i' personally not really a fan of the push for across all languages to like remove every single possible bit of like technically you don't need it typing it's like yeah but it does tell me stuff and I can imagine that it's there yes but just can I have the return keyword I don't know maybe I'm a dinosaur but that's my thinking on it yeah Randall of course with the Pearl update Pearl does that as well I know a lot of languages do it's it's not my favorite anytime I see it but maybe maybe I'm just a dinosaur so I went ahead and write a bit of jet compost code and it's it's really weird to write like doart code or flutter code and then directly afterwards write compos code because it's it's super super similar so basically a box is the equivalent of a container and then you have a column as well but you don't Define your child children with like a children and then a list it's like this block and then bonus points if you do the same thing in Swift UI at the same time so you have another language to care about and yeah so that would be what the H stack in Swift UI it's the H and v stack yes so um oh v stack right I can't horizontal vertical left right my brain's not good at those things yes um we are almost done with native code almost we'll need um so this is basically our appdet this defines what is actually in the home screen widget um but um the operating system doesn't talk to an app widget directly um but talks some some entry point it talks to a so-called receiver and so this one we now this will be our receiver and we call this one observable widget and this is the name that if we uncomment this line again will be used here again so um with the name um you talk to the receiver um there are different options if you you can for example Define different names depending on how you name things you can Define different names for your Android widget and your iOS widget um also on Android um it uses like reflection to find the receiver based on this name so you have to make sure that you provide the correct package because it's cotlin is really close to Java and so you have like packages that are really really important um so um you can also Define this through home widget to make updating easier um and so once again so this is the receiver um and this needs to be of a special kind in order to work with the home widget gland State um but um home widget provides you what you'll need so you need to extend the home widget glance widget receiver um and then we can give it our observable um AB widget that we defined earlier and then we we are good so what happens is basically when the um operating system says Okay I want to add a home screen widget it will go to the receiver and say hey receiver I want to add a new widget of your kind to the home screen and then um the receiver will say here you go here's my observable app widget um it will add this to the home screen and then when there are updates for the EP widget um the receiver will say okay I'm responsible for this instance of the the widget um and I will take this update that you requested and pass this along um to the app widget all right okay all right feels like we've almost plugged in all the wires here almost so what we now need to do is basically tell our app hey app we have this receiver that can handle home screen widgets so we have to go into our manifest um and then in our so what I told earlier it basically lives next to your app so it lives next to the activity the activity is what launches the the flutter view um so we'll have um a receiver which is our observable widget um and we need to export this because otherwise Android will complain um and then some intense filters and this is a app all right in that string you just typed that was there's nothing there about your names or your app path that always exactly that yes at least this is what I have in my notes I hope it is actually what what need to be in there um and then the thing that we need to that is coming from from us um is basically we so this one this wasn't from us but what we need to say is basically our resource and this is where we started when we entered the native side is basically we defined this this XML configuration file for the for the sizing um this one we basically we tell it so um the steps needed let's let's do like a a run through this you'll need a dependency on glands to be able to use glands okay because we we could do everything in XML layouts but I don't think anybody would want this uh we'll need a configuration XML file um we'll need our widget that is responsible for defining how things should look like with our um build method more or less we'll need a receiver to have the operating system send stuff to and say please receive this update and handle this update and then we have to tie basically everything together in the Manifest and right in theory if we run the app we should it just might work it it may work what are our betting odds here that it's going to work so our app is still running this is good yeah great start much better than still count it still it still remembers where we were and also notice I commented this line again in and it didn't crash yet so we we still can count so let's go the device off let's go to the home screen long press widgets and we see our home widget Workshop okay and by the way if you all of the the stuff the preview image that's here the name here these are all things you can Define in this XML configuration file okay um because basically this is where the operating system will look into okay like okay which widgets do I have so we long press and it's really really tiny yeah but I mean I'm not sure if you can see it I can see 11 it says 11 on it so you go back to F that it says also now I distinctly recall you setting a minimum size of 100 by 100 digital pixels yes but this is this is wa let me this is this you see this outline around this this is this is 100 by 100 but we can go into the widget again and so it's I think I mean I don't know I ship it I think is good looks nice it's exactly what our designer wanted um so I think technically this has a uh has basically the yeah that's the background ah Phil Phil next size that's that's that sounds good um gray is wondering if it's Phil content as well I don't know much about compos so I'm using I think it's I think it's Phil Max size is basically what was Phil content in the XML days or maybe not well it still says 11 so it didn't update it still says 11 that is you may be suffering from the yeah restart Theos will get around to it when it gets around to it problem maybe maybe it oh it says 14 oh there you go and fills the one another another version the designer will be happy with yes I'm not sure why it's not updating maybe ah you know why it's not updating and didn't complain because it it didn't save on envious so let's let's then then do the um let's figure out what the modifier is to or is it alignment like what's the vertical alignment so yeah while you're doing that so it's the text is smaller than the smallest size but the actual space allocated to the widget itself was not smaller than the minimum size so now it's is now this is a function of actually specifying the layout correctly to use the available size um then let's do something like now I do presume at some point we we will be providing the content for the widget via flutter code uh you mean the the Rend flutter widget this this layout that we're doing here do we have to do this in compose are we able to do this in flutter we have to do it in compose unfortunately so um because even these ones these columns and boxes they are not from the regular jetpack compos they are from glands interesting because so if you like technically as far as I know glands is also just translating the composed widgets into what's in the um XML wordware called remote views and it really is like a super super tiny tiny subset of of aable which it's like text vertical layouts horizontal layouts Stacks I believe these are interesting basically what's what's available so how does this mix with the thing that we talked about earlier where flutter code would submit a widget and take a picture of it and then use that how how does this all fit together that's let's first verify that now it actually works so the alignment apparently didn't work but it's now saying 17 can you see this I can it's small but I can see it anyone watching on their phone will just have to trust us and 18 19 19 yeah we're cooking it's my guess is that the basically the um it making the column as small as it needs to be and and th this didn't really maybe we can use the same modifier let's apparently not anyways I think adding an image is a lot nicer than than what we currently try so we can go back to flutter um and then let's just use the same method because we have everything else set up here so um for example we could say our cool widget and yeah just R it in the center maybe let's let's see let's see when we when we get back to compos later um so our um we could say let's let's make this a container let's give it some width and some some height um so what's your what's your favorite color for material probably orange I like orange yeah then let's let's let's do like an orange container and then um let's put an icon in there and then what's Dash there's flutter Dash and then so basically have a container with some color um I can already tell this will be really exactly like our designer wanted us to to have something like this yeah now now would be the time to wrap it in a center widget I think yeah maybe yeah we can we can W this this I guess with the center spare no expense go um so what we do is we say home widget um render flutter widget it needs a widget and it can really be any widget it doesn't need to be a widget that's in your widget tree okay um so um you can really use any widget you like and and don't need to be in a in a specific content and it needs a key and this is this key is the same kind of key that we had to use for the counter um so we can say this should be Dash as the key and again we have to remember this when we want to access this data again okay now when you said the same kind of key the kind of key was just a string yeah right it's a it's a string and it's the the same principle that we use a key to to know what's going on yeah okay um so what wend flutter widget does is basically it's it's creating the the wend object for this W or with this widget and capturing it and storing it as an image and then later um when we access this key again on the native side um we will have it as a path to an image so this is already everything we'll need so we'll increment our counter then we build our beautiful Dash widget and then we call render flutter widget and then we still have our update widget afterwards so don't forget to save this time yeah that's helpful and so what we do is basically we say our path um to the image we say from our preferences get a string we call it Dash and if we don't see switching between the languages I only double quotes obviously yeah it's not possible semic color um so we we get the string um to our image path and then let's is there something there's no Center cool uh oh there there was a center ah there is apparently there is a center in glance maybe it's the WR let's let's wor about this later so our image path and so this is syntax from cotland to basically check is this null and if it isn't um then we have this code block here where we have a variable called it we can rename it as well that we know isn't null is not null yeah yeah it's not null and so we create a bitmac factory and we say decode our files from from it um so we we get our file from the path and then we say our image and then we say image provider and the bit map and then one thing I I quite like about what Android does in terms of accessibility is that they really tell you they give you this that you need to provide the content description for it which I think is is really nice um can say just Dash so in theory this should already be all it took so while this is building what we did create a widget render the widget and then use the image yeah show the image so we have to obviously press the button and then can see a really really tiny Dash um so let's let's let's see if we can that's good now you gave the container oh well it was actually kind of small numbers you said like a width of 46 and a height of 23 maybe that those are those Dimensions but I was expecting a little bigger I mean yeah I guess we can just make it like this yeah there we go there now we're talking also I I used this which which might screw us a bit with like image scaling um but we have to we have to stop our app and then run the app again because doesn't give us things like what do we start all right this is a good question we we've talked about this a bit in the past but worth revisiting why are you using an image you passed a widget from flutter and then you're inherit you know you're receiving image on the Android side so let's revisit how this works from super high so um basically we we are not allowed by the operating system to actually show flutter or run flutter inside of the homescreen widgets and so home widget can take your flatter widget take a screenshot of it store it and then you basically trick the system by showing this image um instead um and this this is really really helpful for for a lot of things to to not have to rebuild basically everything yeah ah this is bigger we have a we have a overflow point which I believe is coming from flutter yes definitely yeah that's a very very flutter so this is now You' mentioned that these things could be resized so that feels kind of tricky to you you can't use a layout builder for this if it can be arbitrarily resize because it's just an image so how how do you get around that yes I'm wondering it might be that I can't resize this actually because I think I missed or I didn't provide like an specific argument in here oh okay um but this is I guess a a good thing that you can basically with this um Define your sizes maybe we we just answered this solution to to the problem you were just describing um that yes um I suppose in in that sense it's similarly to how you have to be able to handle responsive layouts and different size factors in flut as well because it might be that um your user is using it on an inid phone where they can change the sizes of them or is using an iPad app on Mac OS for example and and resizes the window yeah so on on on iOS it's a bit easier because you have really just a subset of I think four or five sizes um and you can then you can Define layouts for for each of these sizes differently or separately um um but yeah on Android I'm pretty sure that in this brid you can get the um the current size of it but I would have to to look up exactly how you can get the current size okay but you I would I would really think that you should be able to have something like a layout Builder to know what is your layout and then set stuff accordingly so maybe on the flutter side you'd have to supply you just have to have some structured approach to this where you have a few different aspect ratio and sizes that you're explicitly going to have break points on and you might have to write quite a few different images from the flutter side and then you pull out the specific ones that you need on the native side by the way I think I know where this this overflow is coming from because when a flut widget has a default size of 200 by 200 and so if I give it a bigger size um it will be better okay all right and if if only we would have run this so the the cool thing now is that now that um we have all the native setup that we need like we we show the the image in a beautiful way and we have a perfect design here um is that when we when we update things after it's running um we can use a and our beloved friend so now it's not overflowing anymore and then if we if we say blue and we we reload this and then TR like it didn't update automatically because we we didn't send it your image but if we then trigger this again we now have a blue image very nice and so if you reiz it what happens I'm curious let's and no matter how broken it is I promise we don't have to actually fix it I just am curious what will happen so I think I think this one is the one that was missing aha um so and and my theory is that it it would still probably fit the whole screen because what I did here was I give it a fil Max size modifier um I guess that content scale is the name for what we all know as fit um so let's just say fill bounds which is probably the same as uh fit. cover and flutter so I really like that it's it's all the same but different yeah because nobody can agree on what to call anything ah yeah it's it's a really really skinny de now yeah but now we can resize it actually and you can see it's so the reason yeah so the reason that Dash is getting contorted is because you're just rendering one image and then the image is being stretched to whatever aspect ratio the widget is on it yes and it's it says fill bound so I I suppose that if we say I think fit is probably the more reasonable and then I guess no I've made this no Square so it will be it will work a lot better with the with the [Music] icon so send a new image so yeah so now we can see that it basically fils the whole viewport obviously we should have um probably scale Dash accordingly yeah but it's all right nice so we've sent both specific data and flutter layout and that does feel like a complete demo obviously for any real W you know for any real widget you would combine those two but that's pretty clearly a thing that you would just do in the uh nice a thing that you would do in either the image that you send where you would you know maybe put the counter instead of the dash logo you put the value of the counter or or in Jetpack compose You' combine things as needed cool one thing maybe to note um with the generating the images so um it depends always a bit obviously on your use cases um so there is the an issue that so the way that flutter or home widget captures the widget is through um the when objects from um. UI uhhuh uh and those can't render the images when the app is not running unfortunately okay so there's no background updating of these so if it's if it's like fully in the background for example if you want to do it through like some interactive element on the widget you can through the interactive element still for example count up um but you can't basically have if you have an image that gets updated with with your counter value um that unfortunately is not possible however um what you can do it's a lot more work or not a lot more but basically that you have the the elements fixed and then you do the compositing of putting the number in relation to the generated image um that you do on the native side yeah yeah and that would be one way to to approach this yeah but but really I believe for for a lot of use cases um and if you know EX for example beforehand like what states do I or will I reach um from this interactive elements and you can then still use the render flutter widget to to render your things beforehand makes sense cool so that there are requests in the in the chat for an interactive or a demo of an interactive widget it is okay if you are not prepared to demo that but what what does that take what does that look like um I think we should be able to it's it sounds more I have to find the correct notes but to what extent are your notes the packages documentation um it's actually so so my notes are my notes or the the workshop that I did at at several deathfest um couple of weeks ago um so the document what I noticed to that is um Parts where the documentation is lacking um but I will um hopefully in the Christmas time when when when there's time um I I may get to to update more of these um um of the um actual documentation around the findings I had but in principle all the information that I'm I'm showing here is available through the documentation as well gotcha cool great so yeah time do we have actually for the interactive set we can spend could we do it in 20 minutes yes great so um we'll need couple of things the first thing is basically a callback function that um the widget can can call um so we can say um this is our home widget um callback and this takes an optional u in um and so um this UI is something that we can later on the native side we can provide so basically when we click on an element like we can for example soon make it that if we click on dash it actually counts up um we can say basically in that D we can say Okay um I clicked on dash but we could also say a different viy for I clicked on the number um to in this call back figure out where did the user click and what should I do with it um so interesting what we'll need to do is we make sure that the that this is known as an entry point for for that to be be called because this will also work when the app is totally killed theoretically because it can it can spin up a new flut engine in the background and and call this thing okay so and here um we can let's just copy a lot of this code here um I will remove the whole render widget here because as I said earlier this is not really clear or this is not we don't always know whether it will be working because we don't know in what state flatter is if it can actually capture widgets right now um but we can still do the same thing so our call back basically the same thing get our widget data save the widget data oh count up yeah right right and update the widget and then so we have um a call back and then what we'll need to do is basically we'll need to say home widget register interactivity call back and we give it our call back so some important notes on how this cor looks is it basically needs to be an entry point for that so it has to be static and public okay um but that is basically all of the requirements so we create our callback function and we register an inter of CC all right and so this the the actual logic that's going to be executed for this interactivity is back in Dart code and that I think is certainly preferable to us flutter developers obviously you must also be able to do it on the native side because they're not assuming the flutter exists that was that was the the the the easy and the flut we we soon have to get back into the native Parts got it um but there's again like documentation um around this what you need to actually do um because it it works in a similar way to the to the widget itself so we actually this time last time we ended in the Manifest um this time we we start in the Manifest um and so we'll need a new receip reer and our receiver is actually coming from home widget so this is this is it's confusing because it's the same package pre prefix as as the rest of the app because it's also my package prefix but this is actually coming from the package so you would also if you would build this you would also use um this this background receiver um and again we need to have it exported so the so Andro knows about this um and then it needs an intent filter with another action um and this needs to be also exactly needs to be again comes from home widget um it's basically um the background action so that that the app knows that it's it can handle this and then we need service um which is also coming from home widget which um needs to have a permission and this is now coming at least from Android so these are all basic things that um it's a very helpful hint expected receiver what did that say expected receiver does not require permission expected receiver does not require permission it basically gives me a warning line that nothing is needed is wrong so I always as a kid always thought it would be very funny to just call my friends and tell them that like I couldn't you know I was like hey I'm busy I can't like hang out today and when we had no plans it it's just like a totally random calling hey I'm busy today by the way okay bye and like that feels like the error message that we just got yeah yeah so um that's already it in the Manifest basically saying hey app here's this service from or here's this service from home widget or from my app that can hand or that's that has this receiver and can handle this intent this is basically registering this in the app um and then we need to create an action call back so and and here we will create us an intent and this one is a it's a home widget background intent and we get our broadcast pass in the context and then we pass in our UI so we can say and this can be really any any UI string you that you want we can say increment and then we have the intent and we we send it so this is an action callback um because you you don't just call methods in in gland um you do it via these actions so we can wrap um surround this with the widget so weird here they say by the way surround with container right but it's box elsewhere it's a box oh it's actually a box that's funny what if they just copied the code tell me you copied flutter without tell me you right exactly that's exactly what I was gonna say so um it's again another modifier so everything in glance seems to be modifiers like the the background setting the background setting some sizing it's all them why modifiers so one of these modifiers is a clickable and then we can say that we want to run our interactive action and so um basically we have we say surround the image with a box and when you click on the box run the Callback of this interactive action okay and then our interactive action says on action creates a background intent from home widget which is of the format that we registered in the Manifest before and then that is fired off home widget will be called again on the receiver side of things knowing that there was this this intent fired off um it will take this UI and go back into flutter and call our call back here and so in theory if we run this we should be able to click on dash and we should see the number go up and we did not take 20 minutes no this was 11 by my account quite good so we are at 32 we clicked it and we are at 33 that was fast and it's but it's launching a whole maybe it's caching it well it depends so if there's if there's a flutter engine running it'll use it um I use that okay um but for example what we can do is we can so we at 35 the phone or something yeah we can we can basically so we cleared our app our app is not running it takes a bit longer but as you can see still it's still counted up nice so even even if you if you have users and we have a lot of these users that are closing all of the apps in the app dra even those can still like use the interactive widget dang and so pretty cool the cool thing is also given that this thing is is called or is we defined the the call back in D sure on iOS we have to Define our layouts um in Swift UI but we have a relatively similar approach um like the the ideas behind um how um both platforms handles interactive stuffs using like this intent to say basically from the outside like from the widget say to the main app hey here's something please handle this um It's relatively similar like if we were if we would have done the demo in iOS it would have taken us around the same amount of time as well to do the um the integration on on iOS and then we can use the same call call back um to actually do the the logic operation that we want on both Android and iOS cool nice man that is that is pretty neat and uh Sai with a A pun that I really quite apprec appreciate you were asking questions about you know other bit of functionality and then at the end incremental progress indeed because we just incremented the number from the Native side well let me see uh I'm going to return to the questions that I have queed up we may have gotten to almost all of these oh here's an off-topic one that was asked a full hour ago and I immediately started because I was also interested and then there was more there were echos in the chat requesting that the question be surfaced but I didn't want to interrupt you so Now's the Time tell us about your keyboard oh um it's an hhkb uh type 2s silent in a nor case it's not the Cherry board at the moment ah okay yeah I my ear is not sharp enough to you it's like oh those are brown switches oh those are red those are but uh I did think that it sounded it's topa switch it's not no cherries Whoa man I I've never even heard of that switch type before a lot of them all right so let's see I'm gonna read through these o
2024-12-21 13:47