<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hosam Hasan</title>
    <description>The latest articles on DEV Community by Hosam Hasan (@hosamhasan).</description>
    <link>https://dev.to/hosamhasan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F139745%2Fce262668-6ffb-4395-a38f-185e8a348d46.jpg</url>
      <title>DEV Community: Hosam Hasan</title>
      <link>https://dev.to/hosamhasan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hosamhasan"/>
    <language>en</language>
    <item>
      <title>Handling Firebase Notifications in Flutter: Practical Tips</title>
      <dc:creator>Hosam Hasan</dc:creator>
      <pubDate>Sun, 14 Jan 2024 15:48:06 +0000</pubDate>
      <link>https://dev.to/hosamhasan/handling-firebase-notifications-in-flutter-practical-tips-12oi</link>
      <guid>https://dev.to/hosamhasan/handling-firebase-notifications-in-flutter-practical-tips-12oi</guid>
      <description>&lt;p&gt;I was assigned the task of handling system notifications for medication reminders. The notifications will include two actions: &lt;strong&gt;Take&lt;/strong&gt; and &lt;strong&gt;Skip&lt;/strong&gt;. The notification should function in all app states, including &lt;strong&gt;foreground&lt;/strong&gt;, &lt;strong&gt;background&lt;/strong&gt;, and &lt;strong&gt;terminated&lt;/strong&gt;. Let's begin with these basic requirements and add more as we progress.&lt;/p&gt;

&lt;p&gt;This blog will serve as a QA form for the challenges I faced while implementing this functionality.&lt;/p&gt;

&lt;p&gt;Tools helped me along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://mockoon.com/"&gt;Mockoon&lt;/a&gt; - Used as a logging server instead of using &lt;code&gt;print&lt;/code&gt; in the console.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/oauthplayground"&gt;Google Dev Playground&lt;/a&gt; - Used for obtaining an auth token to use Google APIs for sending notifications.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hoppscotch.io/"&gt;Hoppscotch&lt;/a&gt; - HTTP client used for sending notifications through the Google API.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What libraries should use to achieve this functionality ?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/firebase_messaging"&gt;&lt;code&gt;firebase_messaging&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://pub.dev/packages/flutter_local_notifications"&gt;&lt;code&gt;flutter_local_notifications&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://pub.dev/packages/permission_handler"&gt;&lt;code&gt;permission_handler&lt;/code&gt;&lt;/a&gt; .&lt;/p&gt;

&lt;h3&gt;
  
  
  How to listen to remote notification in all app states ?
&lt;/h3&gt;

&lt;p&gt;1- Ensure that notification permission is configured and granted&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// in AndroidManifist.xml add this permession&lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;uses-permission android:name="android.permission.POST_NOTIFICATIONS" /&amp;gt;&lt;/span&gt;
&lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Initialize Firebase in the &lt;code&gt;main&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Firebase&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3- Configure notification callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onBackgroundMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_onBackgroundMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;FirebaseMessaging&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;onMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_onForegroundMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- Implement notification callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nd"&gt;@pragma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'vm:entry-point'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_onBackgroundMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_onForegroundMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RemoteMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_onBackgroundMessage&lt;/code&gt;: Triggered when the app receives a remote notification in the background and terminated.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_onForegroundMessage&lt;/code&gt;: Triggered when the app receives a remote notification in the foreground.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't forget &lt;code&gt;@pragma('vm:entry-point')&lt;/code&gt; for the background callback to work properly. Now we can show notifications with actions in all states.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Hint&lt;/strong&gt;&lt;/em&gt;: Sometimes, &lt;code&gt;FirebaseMessaging&lt;/code&gt; callbacks don't work properly without calling &lt;code&gt;FirebaseMessaging.instance.getToken()&lt;/code&gt; first.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to add actions to remote notifications ?
&lt;/h3&gt;

&lt;p&gt;We can't add actions to notification directly using &lt;code&gt;firebase_messaging&lt;/code&gt; package only, we need to use &lt;code&gt;flutter_local_notifications&lt;/code&gt; to implement this functionally&lt;/p&gt;

&lt;p&gt;1- Initialize and configure &lt;code&gt;flutter_local_notifications&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// call this function in main&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;configLocalNotification&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;FlutterLocalNotificationsPlugin&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;InitializationSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;android:&lt;/span&gt; &lt;span class="n"&gt;AndroidInitializationSettings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'@mipmap/ic_launcher'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nl"&gt;onDidReceiveNotificationResponse:&lt;/span&gt; &lt;span class="n"&gt;_onForegroundNotificationResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;onDidReceiveBackgroundNotificationResponse:&lt;/span&gt; &lt;span class="n"&gt;_onBackgroundNotificationResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Implement action callbacks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_onForegroundNotificationResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NotificationResponse&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nd"&gt;@pragma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'vm:entry-point'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;_onBackgroundNotificationResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NotificationResponse&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_onForegroundNotificationResponse&lt;/code&gt;: Triggered when the app receives a notification action in the foreground.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_onBackgroundNotificationResponse&lt;/code&gt;: Triggered when the app receives a notification action in the background and terminated.
Don't forget &lt;code&gt;@pragma('vm:entry-point')&lt;/code&gt; for background callback to work properly.
Now we can show notification with actions in all states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3- Receive &lt;strong&gt;&lt;em&gt;silent remote notifications&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;data-only notifications&lt;/em&gt;&lt;/strong&gt; from the backend and then show local notifications with actions once the device receives remote notifications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"android"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HIGH"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4- Show local notifications with actions on &lt;code&gt;_onBackgroundMessage&lt;/code&gt; and &lt;code&gt;_onForegroundMessage&lt;/code&gt; callbacks using the &lt;code&gt;FlutterLocalNotificationsPlugin.show(...)&lt;/code&gt; method.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to redirect the user to a specific page if the app was opened from a notification tap?
&lt;/h3&gt;

&lt;p&gt;Call &lt;code&gt;FlutterLocalNotificationsPlugin().getNotificationAppLaunchDetails()&lt;/code&gt; in the &lt;code&gt;main&lt;/code&gt; function to know if the app was opened from a notification or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to bring app to foreground when app receives remote notification on background or terminated state ?
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;android_intent_plus&lt;/code&gt; and &lt;code&gt;package_info_plus&lt;/code&gt; will help us achieve this feature:&lt;/p&gt;

&lt;p&gt;1-  Make sure that &lt;code&gt;SYSTEM_ALERT_WINDOW&lt;/code&gt; permission is granted&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// Used to show full app notifcation on lock screen&lt;/span&gt;
 &lt;span class="n"&gt;Permission&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;systemAlertWindow&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- use android &lt;code&gt;Intent&lt;/code&gt; to open or bring app to foreground&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_bringAppToForeground&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;PackageInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fromPlatform&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;packageName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;packageName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AndroidIntent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="s"&gt;'android.intent.action.MAIN'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;flags:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;FLAG_ACTIVITY_NEW_TASK&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nl"&gt;category:&lt;/span&gt; &lt;span class="s"&gt;'android.intent.category.LAUNCHER'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;arguments:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'args'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'run flutter app automatically from notification'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nl"&gt;package:&lt;/span&gt; &lt;span class="n"&gt;packageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;componentName:&lt;/span&gt; &lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="si"&gt;$packageName&lt;/span&gt;&lt;span class="s"&gt;.MainActivity'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;launch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;we need to check &lt;code&gt;arguments&lt;/code&gt; on app start to check if app was opened automatically from background&lt;/li&gt;
&lt;li&gt;Also if we need to bring app to foreground when screen in locked we need to add &lt;code&gt;USE_FULL_SCREEN_INTENT&lt;/code&gt; permission to manifest, and config main activity
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;uses-permission&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.permission.USE_FULL_SCREEN_INTENT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;&amp;lt;!-- add this keys to activity --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt;
    &lt;span class="err"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;android:showWhenLocked=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;android:turnScreenOn=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;To check if app was launched using the android &lt;code&gt;Intent&lt;/code&gt; we need to check launch &lt;code&gt;arguments&lt;/code&gt; using &lt;a href="https://pub.dev/packages/launch_args"&gt;&lt;code&gt;launch_args&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://pub.dev/packages/"&gt;&lt;code&gt;receive_intent&lt;/code&gt;&lt;/a&gt; package or simply implement native android function and call it using method channel and call it in &lt;code&gt;main&lt;/code&gt; function
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;getIntentArgs&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;?{&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extras&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;map&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mutableMapOf&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;?&amp;gt;();&lt;/span&gt;
     &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;keySet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt;  &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;map&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;_methodChannel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MethodChannel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'channel_name'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;getIntentArgs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;argsResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_methodChannel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invokeMapMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'getIntentArgs'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argsResult&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to close app once user responds to notification if app was opened from notification ?
&lt;/h3&gt;

&lt;p&gt;Using the &lt;a href="https://pub.dev/packages/flutter_exit_app"&gt;&lt;code&gt;flutter_exit_app&lt;/code&gt;&lt;/a&gt; package to close the app completely whenever we want.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Display App-Specific UI when Receiving Notifications in Foreground or Background?
&lt;/h3&gt;

&lt;p&gt;While reacting to notification events in the foreground has no challenges since all listeners are registered in the &lt;em&gt;&lt;strong&gt;main isolate&lt;/strong&gt;&lt;/em&gt;, the complexity arises when dealing with background events. To address this, a communication mechanism between the &lt;em&gt;&lt;strong&gt;main isolate&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;other isolates&lt;/strong&gt;&lt;/em&gt; becomes essential.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;IsolateNameServer&lt;/code&gt; API comes to our rescue in establishing straightforward isolate communication. We achieve this by registering the &lt;code&gt;UIIsolateCommunicationChannel&lt;/code&gt; in the main thread using the &lt;code&gt;forceRegister&lt;/code&gt; method. Additionally, the &lt;code&gt;listen&lt;/code&gt; function facilitates the reception of data through this channel, making use of the &lt;code&gt;send&lt;/code&gt; method to communicate with the &lt;code&gt;UIIsolateCommunicationChannel&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UIIsolateCommunicationChannel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_receivePort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ReceivePort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'ui_isolate'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;register&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerPortWithName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;_receivePort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;forceRegister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;isRegistered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerPortWithName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;_receivePort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isRegistered&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removePortNameMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerPortWithName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;_receivePort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sendPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;StreamSubscription&lt;/span&gt; &lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_receivePort&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;listener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lookupPortByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;unregister&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;removePortNameMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isRegistered&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;IsolateNameServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;lookupPortByName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Hints&lt;/em&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supported types for communication channel &lt;a href="https://api.dart.dev/stable/3.2.0/dart-isolate/SendPort/send.html"&gt;Link&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Also, make sure to use primary constructors from &lt;code&gt;List&lt;/code&gt; and &lt;code&gt;Map&lt;/code&gt; to pass them through communication channel to work on release mode . &lt;a href="https://github.com/flutter/flutter/issues/113183#issuecomment-1285473165"&gt;issue reference&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;UIIsolateCommunicationChannel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toList&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt; &lt;span class="c1"&gt;// fails in release mode ❌&lt;/span&gt;
&lt;span class="n"&gt;UIIsolateCommunicationChannel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;//  ✅&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Not the End
&lt;/h3&gt;

&lt;p&gt;I hope this small journey has been helpful for you.&lt;br&gt;
Stay tuned for the IOS implementation  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs/cloud-messaging/concept-options"&gt;https://firebase.google.com/docs/cloud-messaging/concept-options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification"&gt;https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://api.flutter.dev/flutter/dart-ui/IsolateNameServer-class.html"&gt;https://api.flutter.dev/flutter/dart-ui/IsolateNameServer-class.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/flutter/introducing-background-isolate-channels-7a299609cad8"&gt;https://medium.com/flutter/introducing-background-isolate-channels-7a299609cad8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/firebase/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example"&gt;https://github.com/firebase/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications/example"&gt;https://github.com/MaikuB/flutter_local_notifications/tree/master/flutter_local_notifications/example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>fcm</category>
      <category>notifications</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Pub.dev How to choose the right package</title>
      <dc:creator>Hosam Hasan</dc:creator>
      <pubDate>Fri, 26 May 2023 22:24:33 +0000</pubDate>
      <link>https://dev.to/hosamhasan/pubdev-how-to-choose-the-right-package-3i64</link>
      <guid>https://dev.to/hosamhasan/pubdev-how-to-choose-the-right-package-3i64</guid>
      <description>&lt;p&gt;If you're struggling to choose the right package from Pub.dev's vast library of over 35K packages, this article will guide you through the process.&lt;/p&gt;

&lt;p&gt;It's important to remember that once you've added a package to your project, it's your responsibility to keep up with updates and news related to that package. So, choosing the right package is crucial.&lt;/p&gt;

&lt;p&gt;Here are the steps to follow:&lt;/p&gt;

&lt;h3&gt;
  
  
  1.  Define Your Problem
&lt;/h3&gt;

&lt;p&gt;Start by defining your problem accurately and specifying your expectations for the package. Be clear about how you want the package to solve your problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Check Flutter and Dart API Before You Browse Pub.dev
&lt;/h3&gt;

&lt;p&gt;Before diving into Pub.dev, check the Flutter and Dart API. You may find that the solution you need is already available in the SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Consider the Platforms You're Supporting
&lt;/h3&gt;

&lt;p&gt;Make sure to read the package documentation carefully, as some features may not work on all platforms, even if the package can be compiled on all platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Packages Metrics :
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Documentation and Testing&lt;/strong&gt;&lt;br&gt;
Read the package documentation and check its quality and clarity. Look for examples and check the testing coverage and quality of the tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Code Quality&lt;/strong&gt;&lt;br&gt;
Take a tour inside the code and check the style and quality of the code. Evaluate the complexity and readability of the code and consider how you can contribute to it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Package History&lt;/strong&gt; &lt;br&gt;
Check the update history and change logs to see how the package has evolved over time. This can give you an idea of how active the package is and whether it's being actively maintained.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transitive dependency&lt;/strong&gt;&lt;br&gt;
Check the transitive dependencies and evaluate how heavy they are in maintenance. This can help you avoid packages with unnecessary dependencies that may add to the complexity of your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community Activity&lt;/strong&gt;&lt;br&gt;
Check the issues section in GitHub and see how issues are being handled. Also, check the PRs and their acceptance criteria. Look for other community channels on Discord, Telegram, and other platforms to gauge the health of the community.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Popularity&lt;/strong&gt; &lt;br&gt;
Consider the package's popularity, as indicated by GitHub stars and Pub.dev metrics (likes, Pub Points, and Popularity).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Test Before Implementation
&lt;/h3&gt;

&lt;p&gt;it's essential to test it first. Create a proof of concept or a test app to see if the package solves your problem as expected. This will help you avoid potential issues and ensure that the package is the right fit for your project.&lt;/p&gt;

&lt;p&gt;In conclusion, choosing the right package from Pub.dev's extensive library can be challenging. By following these steps and considering these metrics, you can make the right choice and find a package that meets your needs and helps you achieve your project goals.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>pub</category>
      <category>package</category>
    </item>
    <item>
      <title>Package Flutter Linux App Into AppImage Part 2</title>
      <dc:creator>Hosam Hasan</dc:creator>
      <pubDate>Mon, 05 Jul 2021 19:30:14 +0000</pubDate>
      <link>https://dev.to/hosamhasan/package-flutter-linux-app-into-appimage-part-2-1c5o</link>
      <guid>https://dev.to/hosamhasan/package-flutter-linux-app-into-appimage-part-2-1c5o</guid>
      <description>&lt;h2&gt;
  
  
  Now, We are ready to build our first Flutter AppImage app 🚀
&lt;/h2&gt;

&lt;p&gt;Firstly , we will change our working directory to the project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;flutter_appimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Then follow these steps:
&lt;/h4&gt;

&lt;p&gt;1- Create folder  &lt;em&gt;&lt;code&gt;AppDir&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;AppDir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2- Generate the YAML recipe file required to build the AppImage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;appimage-builder &lt;span class="nt"&gt;--generate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this command will prompt some questions. Here is the final output :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO:Generator:Searching AppDir
? ID &lt;span class="o"&gt;[&lt;/span&gt;Eg: com.example.app]: com.example.flutter_appimage
? Application Name: Flutter AppImage
? Icon: flutter_appimage_icon
? Executable path relative to AppDir &lt;span class="o"&gt;[&lt;/span&gt;usr/bin/app]: flutter_appimage
? Arguments &lt;span class="o"&gt;[&lt;/span&gt;Default: &lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: &lt;span class="nv"&gt;$@&lt;/span&gt;
? Version &lt;span class="o"&gt;[&lt;/span&gt;Eg: 1.0.0]: latest
? Update Information &lt;span class="o"&gt;[&lt;/span&gt;Default: guess]: guess
? Architecture: x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you will notice a new file &lt;code&gt;AppImageBuilder.yml&lt;/code&gt;  added to the root directory of our project.&lt;/p&gt;

&lt;p&gt;Wait a second, What the hack this &lt;code&gt;flutter_appimage_icon&lt;/code&gt; comes from 🙄🤔&lt;/p&gt;

&lt;p&gt;Stop rubbing your head. Here is why :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;copy your favorite icon to the root directory and make sure its extension is &lt;code&gt;SVG&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rename you icon to &lt;code&gt;flutter_appimage_icon.svg&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Now, let's open &lt;code&gt;AppImageBuilder.yml&lt;/code&gt; and edit some stuff:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;add starting script that will delete old &lt;code&gt;AppDir&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;rm -rf AppDir | &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;
   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir AppDir&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;add after bundling scripts to add the Flutter App to the bandle
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;AppDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;after_bundle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp build/linux/x64/release/bundle/flutter_appimage AppDir&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp -r build/linux/x64/release/bundle/lib/. AppDir/lib&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp -r build/linux/x64/release/bundle/data AppDir&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cp flutter_appimage_icon.svg AppDir/usr/share/icons/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;gtk3&lt;/code&gt; required for flutter app also define the repositories  where dependencies  comes from
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;pacman&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Architecture&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x86_64&lt;/span&gt;
      &lt;span class="na"&gt;repositories&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https://mirror.rackspace.com/archlinux/$repo/os/$arch&lt;/span&gt;
        &lt;span class="na"&gt;extra&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;https://mirror.rackspace.com/archlinux/$repo/os/$arch&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gtk3&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt; &lt;span class="c1"&gt;# I don't know why we need but build fails without it  &lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;perl&lt;/span&gt; &lt;span class="c1"&gt;# I don't know why we need but build fails without it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alright, Here is the moment we have been waiting for:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;appimage-builder &lt;span class="nt"&gt;--skip-test&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁🥁.....................Voila 🥳🥳🥳🥳🥳&lt;/p&gt;

&lt;p&gt;New file added to the root directory &lt;code&gt;Flutter AppImage-latest-x86_64.AppImage&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Flutter Counter App packaged in AppImage.&lt;/p&gt;

&lt;p&gt;But wait a second ...... not again 😫.&lt;/p&gt;

&lt;p&gt;The bundled AppImage file is about 225 MB , your kidding me  😠.&lt;/p&gt;

&lt;p&gt;I know the bundle size needs some optmization , I wil pospone this to part 3. &lt;/p&gt;

&lt;h4&gt;
  
  
  References :
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://appimage-builder.readthedocs.io/en/latest/examples/flutter.html"&gt;Flutter Application — appimage-builder 0.8.8 documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://flutter.dev/docs/get-started/install/linux"&gt;Linux install - Flutter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://flutter.dev/docs/deployment/linux"&gt;Build and release a Linux app to the Snap Store - Flutter&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  GitHub :
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hosamkora/Flutter_AppImage"&gt;GitHub - hosamkora/Flutter_AppImage: Sample app for packaging Flutter Linux app into AppImage using AppImage Builder&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>flutter</category>
      <category>appimage</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Package Flutter Linux App Into AppImage Part 1</title>
      <dc:creator>Hosam Hasan</dc:creator>
      <pubDate>Mon, 05 Jul 2021 19:27:13 +0000</pubDate>
      <link>https://dev.to/hosamhasan/package-flutter-linux-app-into-appimage-part-1-2agj</link>
      <guid>https://dev.to/hosamhasan/package-flutter-linux-app-into-appimage-part-1-2agj</guid>
      <description>&lt;p&gt;Flutter is one of the fastest-growing cross-platform UI frameworks with a great and powerful community which has a great part of Flutter success.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.ubuntu.com%2Fv1%2F29985a98-ubuntu-logo32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.ubuntu.com%2Fv1%2F29985a98-ubuntu-logo32.png" title="" alt="assets.ubuntu.com/v1/29985a98-ubuntu-logo32.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lately, Flutter announced desktop support including Linux which got the attention of big corporates like Canonical (Publisher of Ubuntu), and lately announced that they are rebuilding Ubuntu Desktop Installer using Flutter.&lt;/p&gt;

&lt;p&gt;Flutter official docs also have a section on how to build and package Flutter Linux app in Snap (Linux Universal Package Manager) and ship it to Snap Store. &lt;a href="https://flutter.dev/docs/deployment/linux" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So it will be interesting if we tried to package Flutter Apps using another universal package manager which is AppImage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirments :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Linux OS (I will use Manjaro)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Flutter with Linux config enabled ( assuming you have latest flutter stable version )&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AppImage Tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AppImage Builder&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Install AppImage Tool and AppImage Builder
&lt;/h4&gt;

&lt;p&gt;1- Install required deps&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Sy&lt;/span&gt; python-pip python-setuptools binutils patchelf desktop-file-utils gdk-pixbuf2 wget fakeroot strace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - Install Apimage Tool&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;wget https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage &lt;span class="nt"&gt;-O&lt;/span&gt; /usr/local/bin/appimagetool
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/appimagetool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Install AppImage Builder&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;appimage-builder
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Create and build Flutter Linux app
&lt;/h4&gt;

&lt;p&gt;1 - install required deps for building flutter linux app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Sy&lt;/span&gt; clang cmake ninja pkgconf gtk3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - Enable Flutter linux desktop configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flutter config &lt;span class="nt"&gt;--enable-linux-desktop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 -  Create flutter project  &lt;code&gt;flutter_appimage&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;flutter create flutter_appimage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Build Linux App&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;flutter_appimage &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; flutter build linux&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Now, We are good to go to build the AppImage 🥳
&lt;/h2&gt;

</description>
      <category>flutter</category>
      <category>appimage</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
