<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Anum Amin on Medium]]></title>
        <description><![CDATA[Stories by Anum Amin on Medium]]></description>
        <link>https://medium.com/@anum.amin?source=rss-1e422595a7c0------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*cliKVOAFreIdqh_O5eXDNA.jpeg</url>
            <title>Stories by Anum Amin on Medium</title>
            <link>https://medium.com/@anum.amin?source=rss-1e422595a7c0------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 10 Apr 2026 06:45:32 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@anum.amin/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Switch Navigation Stacks with Decompose in KMP]]></title>
            <link>https://medium.com/@anum.amin/switch-navigation-stacks-with-decompose-in-kmp-a28e5563da14?source=rss-1e422595a7c0------2</link>
            <guid isPermaLink="false">https://medium.com/p/a28e5563da14</guid>
            <category><![CDATA[kotlin-multiplatform]]></category>
            <category><![CDATA[navigation]]></category>
            <category><![CDATA[decompose]]></category>
            <dc:creator><![CDATA[Anum Amin]]></dc:creator>
            <pubDate>Wed, 10 Jan 2024 19:24:47 GMT</pubDate>
            <atom:updated>2024-01-10T19:24:47.144Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JJ3sbV1638voUouE" /><figcaption>Photo by <a href="https://unsplash.com/@vonshnauzer?utm_source=medium&amp;utm_medium=referral">Egor Myznik</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><blockquote>This article assumes that you already have basic knowledge about Decompose.</blockquote><p>I have found <a href="https://github.com/arkivanov/Decompose">Decompose</a> a great navigation library for both Compose Multiplatform and KMP with native UI so far. It operates on BLoC (Business Logic Component) pattern — those who have worked on Flutter may already know about it. The individual component is responsible for managing the state and events for the corresponding screen similar to viewModels in Android.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*VwCYU19-IaMP44k4.png" /><figcaption>From Flutter’s bloc library</figcaption></figure><p>Its a common practice in mobile applications to group different flows in separate navigation graphs or storyboards or different modules. Lets assume we have an application with 3 main flows as follows:</p><p>1- When user launches app for the first time, he is shown splash and onboarding <strong>[Landing Flow]</strong></p><p>2- User can login/signup in the app. Should be able to go from onboarding. <strong>[Authentication Flow]</strong></p><p>3- After login, main app contents are displayed. You can call it Home Screen<strong> [Main Flow]</strong></p><p>Our requirement is that we should be able to switch between different flows. In order to achieve it via Decompose, each flow will be managed by a <strong>NavigationStack</strong> inside Parent Component.</p><p>According to <a href="https://arkivanov.github.io/Decompose/component/overview/">Documentation</a>,</p><blockquote>A component is just a normal class that encapsulates some logic and possibly another (child) components. Every component has its own lifecycle, which is automatically managed by Decompose. So everything encapsulated by a component is scoped.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5OsHUuZGA4z_FFBsUSjkQA.png" /><figcaption>App components hierarchy</figcaption></figure><p>Consider Landing Component, Auth Component and Main Component as three parent components in same hierarchy managing their own screens and navigation stack. Only one navigation stack can be displayed at a time from the root.</p><p>Main Component can be anything — Drawers + Tabs or simple content screens. In the diagram above, I have portrayed the main screen having bottom navigation [tabs].</p><h3>Implementation</h3><p>For the sake of brevity, I will explain Landing and Root components. Auth and Main can be created just like Landing. In order to get an idea about bottom navigation content management with Decompose, check their <a href="https://github.com/arkivanov/Decompose/tree/master/sample">sample</a> especially <a href="https://github.com/arkivanov/Decompose/blob/master/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/root/DefaultRootComponent.kt">DefaultRootComponent</a> and <a href="https://github.com/arkivanov/Decompose/blob/master/sample/shared/compose/src/commonMain/kotlin/com/arkivanov/sample/shared/root/RootContent.kt">RootContent</a>.</p><p>Create <strong>LandingComponent</strong> interface holding navigation state information. Here a sealed class <strong>LandingChild</strong> is declaring classes for all the screens that will be accessed in the Landing flow. They will hold component information for corresponding screen.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a1cb15645aec61934a8de33a1b059c59/href">https://medium.com/media/a1cb15645aec61934a8de33a1b059c59/href</a></iframe><p>Its implementation will be responsible to manage the navigation for the landing flow and provide Child for the screen requested.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c77046547a5018b7c9c8eadaf564c0c3/href">https://medium.com/media/c77046547a5018b7c9c8eadaf564c0c3/href</a></iframe><p>Now lets create a Application Root component having information about main flows of the application. It also contains navigation methods that can be called by Landing and Auth Components in order to request navigation to another stack.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0190893f3463151d28c1b107fdac9b65/href">https://medium.com/media/0190893f3463151d28c1b107fdac9b65/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e10cda8ea92fd417c5d85fdc1affed17/href">https://medium.com/media/e10cda8ea92fd417c5d85fdc1affed17/href</a></iframe><p>Now here comes the interesting part, how to switch the stacks. In Android or Compose Multiplatform you can do this by:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0513a1de9cc76e4924ad0b554f9830f2/href">https://medium.com/media/0513a1de9cc76e4924ad0b554f9830f2/href</a></iframe><p>If you are creating UI layers natively like SwiftUI, Desktop, web etc then each platform needs to implement their own routing mechanism.</p><p>Finally, the <strong>RootContent</strong> can be used as:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/62deb9cce8c2b02d55af91c0ad86311e/href">https://medium.com/media/62deb9cce8c2b02d55af91c0ad86311e/href</a></iframe><p>What navigation library you are using for your KMP app? You can let me know in the comments.</p><p>Happy coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a28e5563da14" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[When not to use Shared ViewModel]]></title>
            <link>https://medium.com/@anum.amin/when-not-to-use-shared-viewmodel-43d12bf33dd0?source=rss-1e422595a7c0------2</link>
            <guid isPermaLink="false">https://medium.com/p/43d12bf33dd0</guid>
            <category><![CDATA[activity]]></category>
            <category><![CDATA[fragments]]></category>
            <category><![CDATA[viewmodelscope]]></category>
            <category><![CDATA[viewmodel]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Anum Amin]]></dc:creator>
            <pubDate>Thu, 01 Dec 2022 09:52:12 GMT</pubDate>
            <atom:updated>2022-12-01T09:52:12.137Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="Photo by &lt;a href=”https://unsplash.com/@kkalerry?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText&quot;&gt;Klara Kulikova&lt;/a&gt; on &lt;a href=”https://unsplash.com/s/photos/sharing?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText&quot;&gt;Unsplash&lt;/a&gt;" src="https://cdn-images-1.medium.com/max/1024/1*02bEAV-Wb-HHlo3DCJoQHw.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@kkalerry?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Klara Kulikova</a> on <a href="https://unsplash.com/s/photos/sharing?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>View Models are encouraged by Google to share data between fragments in an activity. Although it is a good approach, but easy to be misused if not taken care of.</p><p>I am going to highlight two cases which I came across, and think that Shared ViewModels actually created bad code smell and bugs in the code that needed to be refactored later. So if you really want to use in such cases, do think if it is the correct way or there is an alternative.</p><h4>ViewModel in Single Activity Architecture</h4><p>Imagine you have an app with single activity architecture. In order to share same data across multiple fragments, you decided to make viewModel shared.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/adcca8a9c0b590872ab03053b8e921ca/href">https://medium.com/media/adcca8a9c0b590872ab03053b8e921ca/href</a></iframe><p>If UserViewModel is declared as shared with activity scope, it becomes a <strong>singleton</strong>. It is good to keep your viewModel scoped. Both Androidx and Koin facilitates to help you scope them to parent fragment or navigation graph. This will make sure that viewModel is destroyed once scope is no longer valid.</p><h4>Problematic with Flows</h4><p>Flows can sometime cause issues if used with shared viewModel.</p><p>Suppose, you have a Bottom sheet that shows product variants list against a product. On selection of variant, you emit event, so that caller fragment can know about selection. Please do note that we cannot use <strong>sharedViewModel</strong> with <strong>requireParentFragment</strong> in navigation graph, since dialog is treated as a separate fragment.</p><p>Here the simplified code shows the loading of data, and passing event to viewModel on selection.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/87a5cd5307d72def7b7ef7784198a3b7/href">https://medium.com/media/87a5cd5307d72def7b7ef7784198a3b7/href</a></iframe><p>This view model is shared between caller <strong>ProductFragment</strong> and <strong>ProductVariantBottomSheet</strong>. On variant selection, ProductFragment is notified of changes via <strong>selectedVariant</strong> flow.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/55148f0d54b7a3c86f62649fc2383646/href">https://medium.com/media/55148f0d54b7a3c86f62649fc2383646/href</a></iframe><p>Here are entities for the reference used in viewModel.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/af5bbd46a005d1d43d9c7b53d71d078e/href">https://medium.com/media/af5bbd46a005d1d43d9c7b53d71d078e/href</a></iframe><p>When you go away from <strong>ProductVariantBottomSheet</strong>, fragment is destroyed but viewModel isn’t. Therefore, if you will show this dialog for another product, it will emit previous value of <strong>variantsUiState </strong>before new data is fetched. After response is received from API, new data is populated. User will see stale/invalid variants for a while, which will be replaced by fresh ones after few seconds.</p><p>This will work if you want to display one time cached data from viewModel. But in case you need to fetch the data every time, it will be bad user experience since user will see its old data temporarily. Or in order to handle such thing, you will have to either clear the UI state of flow or hide the screen contents unless fresh data is loaded. Either way I feel it is escape from a bad practice and not a proper solution.</p><p>May be if it’s SharedFlow, you might think to adjust replay values here. But trust me, it will get messier as codebase will grow with bugs.</p><h3>Recommendation</h3><p>In order to communicate between fragments, use <strong>setFragmentResultListener</strong> whenever possible. It’s clean and safe with no side effects discovered so far.</p><p>Another Android’s old school approach would be to use repository as a mediator data holder (may be a cold flow) that can cache the value, and emit it to the subscriber when available.</p><p>Happy coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43d12bf33dd0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ActivityResultLauncher Crash — Can only use lower 16 bits for requestCode]]></title>
            <link>https://medium.com/@anum.amin/activityresultlauncher-crash-can-only-use-lower-16-bits-for-requestcode-7a4fc5ea5eb0?source=rss-1e422595a7c0------2</link>
            <guid isPermaLink="false">https://medium.com/p/7a4fc5ea5eb0</guid>
            <dc:creator><![CDATA[Anum Amin]]></dc:creator>
            <pubDate>Tue, 15 Sep 2020 19:49:33 GMT</pubDate>
            <atom:updated>2020-09-15T19:49:33.511Z</atom:updated>
            <content:encoded><![CDATA[<h3>ActivityResultLauncher Crash — Can only use lower 16 bits for requestCode</h3><p>I was trying a new way of writing runtime permissions on Android. It amazed me how precise the code has become, and you do not need to write hundreds of lines of boilerplate code.</p><p>In case you are trying to acquire permission from the user using new <em>ActivityResultLauncher</em> and <em>ActivityResultContracts</em>, you may get the crash mentioned in the title. As a solution, it is necessary to include following dependencies together even if they do not look relevant to each other, yet fixes the crash.</p><pre>implementation &#39;androidx.activity:activity-ktx:1.2.0-alpha08&#39;<br>implementation &#39;androidx.fragment:fragment:1.3.0-alpha08&#39;</pre><p>Thanks to <a href="https://stackoverflow.com/a/62775427/437146">Saurabh</a> for pointing out. In case you would like to acquire multiple permissions at a time from the user, you can use the following code:</p><pre>val multiplePermissions = <strong>registerForActivityResult</strong>(ActivityResultContracts.RequestMultiplePermissions()) { map -&gt;</pre><pre>//Callback received what we used to get in onRequestPermissionsResult</pre><pre><strong>}</strong></pre><pre>multiplePermissions.launch(<em>arrayOf</em>(<br>Manifest.permission.<em>CAMERA</em>, Manifest.permission.<em>WRITE_EXTERNAL_STORAGE</em>, Manifest.permission.<em>READ_EXTERNAL_STORAGE</em>))</pre><p>Looks cool. Right? Happy Coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7a4fc5ea5eb0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Swift Pod Library in Objective C Project]]></title>
            <link>https://medium.com/@anum.amin/swift-pod-library-in-objective-c-project-c6d1c5af997d?source=rss-1e422595a7c0------2</link>
            <guid isPermaLink="false">https://medium.com/p/c6d1c5af997d</guid>
            <category><![CDATA[cocoapods]]></category>
            <category><![CDATA[objective-c]]></category>
            <category><![CDATA[swift]]></category>
            <dc:creator><![CDATA[Anum Amin]]></dc:creator>
            <pubDate>Wed, 24 Oct 2018 19:57:42 GMT</pubDate>
            <atom:updated>2018-10-24T19:57:42.206Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/900/1*Z31Pm2ifT8arC5bRdb4clA.jpeg" /></figure><p>If you are a person working on legacy Objective C projects like me, you might have to use Swift 3rd party libraries available online. Detecting Swift files in Objective C projects doesn’t work smoothly as expected. Therefore one has to make sure that all the steps have been correctly followed.</p><p>Here I am mentioning couple of points that could help you get through the process swiftly.</p><ol><li>Make sure you uncomment <strong>use_frameworks!</strong> in pod file.</li><li>Check in <strong>Build settings</strong> <strong>&gt; Header Search Paths, </strong>Pods folder is added as recursive search.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d1JwUlQ3x-J7s615NTxCIw.png" /></figure><p><em>3. Objective-C bridging Header </em>is present in the project and included in Build Settings. If not, then you can simply add a Swift file, Xcode will ask to configure for you. Say Yes!</p><p>4. Make sure after installing pods, you clean and compile code once.</p><p>5. To access swift file from pod, you have to use:</p><p><strong>#import “&lt;Classname&gt;-Swift.h”</strong></p><p>For example, if you are using <a href="https://github.com/ninjaprox/NVActivityIndicatorView">NVActivityIndicatorView</a>, you would end up with:</p><p><strong>#import “NVActivityIndicatorView-Swift.h”</strong></p><h3>Side Note</h3><p>If you are accessing manually added Swift file in Objective C code, just use:</p><p><strong>#import “&lt;YourProjectName&gt;-Swift.h”</strong></p><p>You can confirm Filename in <strong>Build Settings &gt; Objective-C Generated Interface Header Name.</strong></p><p>Happy Coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c6d1c5af997d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[React Native: Integrating Push Notifications using FCM]]></title>
            <link>https://medium.com/@anum.amin/react-native-integrating-push-notifications-using-fcm-349fff071591?source=rss-1e422595a7c0------2</link>
            <guid isPermaLink="false">https://medium.com/p/349fff071591</guid>
            <category><![CDATA[firebasecloudmessaging]]></category>
            <category><![CDATA[react-native-firebase]]></category>
            <category><![CDATA[push-notification]]></category>
            <category><![CDATA[react-native]]></category>
            <category><![CDATA[fcm]]></category>
            <dc:creator><![CDATA[Anum Amin]]></dc:creator>
            <pubDate>Sun, 15 Jul 2018 19:44:58 GMT</pubDate>
            <atom:updated>2020-07-16T06:26:31.036Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/667/1*9b6q0_c26pf9_diOgvRwHA.jpeg" /></figure><p>Recently, I integrated push notifications in my react native app using <a href="https://github.com/invertase/react-native-firebase">react-native-firebase</a>. I came across many challenges during the process of integration to successful implementation, so I thought to share steps with everyone here.</p><p><strong>Note [as of year 2020]: </strong>This article is 2 years old. RnFirebase has released a much stable version that supports react native 0.60 along with autolinking. I will recommend to check out their <a href="https://rnfirebase.io/messaging/usage">guide</a> first. You can surely follow this tutorial in case you have any concerns. Cheers! 🙂</p><h3>Create Application On Console</h3><p>First create an application on <a href="https://console.firebase.google.com">Firebase console</a>. Follow steps in Cloud Messaging Section, add iOS and Android apps as per your requirement.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ToGirV7x1igt23AGl8WZXA.png" /><figcaption>Cloud Messaging Section — Firebase</figcaption></figure><p>Make sure your google-services.json and GoogleService-Info.plist are placed in correct folders.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1020/1*8O1Y6RE6Gh2ECEuiAlcZ2w.jpeg" /><figcaption>Correct Placement of Google Services files</figcaption></figure><p><strong>Android</strong></p><p>Configure gradle files. Please use the latest firebase dependencies available while following this tutorial. You can find official FCM guide <a href="https://firebase.google.com/docs/cloud-messaging/android/client">here</a>. For your reference, my gradle files are as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bd14622f1e46c75ca79b55eb6ad6898d/href">https://medium.com/media/bd14622f1e46c75ca79b55eb6ad6898d/href</a></iframe><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e5f24bcd9c22d9c1fbe55017d4549143/href">https://medium.com/media/e5f24bcd9c22d9c1fbe55017d4549143/href</a></iframe><p><strong>iOS</strong></p><ol><li>In Firebase console, you have to include either <strong>APNs Authentication Key</strong> or <strong>APNs Certificate</strong> in <strong>Project Settings</strong> <strong>&gt; Cloud Messaging</strong> in order to receive push notifications. Creation of push certificate is out of scope in this tutorial, so here is a nice <a href="https://medium.com/@ankushaggarwal/generate-apns-certificate-for-ios-push-notifications-85e4a917d522">link</a> for your reference :)</li></ol><blockquote>Note: You need two separate push certificates. One for Sandbox Environment (Development Certificate) and other for Production (Distribution Certificate). Both should be uploaded to Firebase Console.</blockquote><p>2. Turn on following two capabilities in Xcode. Make sure these are turned on in certificates as well created in step 1.</p><p>a) Push Notifications</p><p>b) Background Modes - Check only Remote Notifications</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/701/1*7_iXN53EFpp1GcKSvqgqXg.jpeg" /></figure><blockquote>Make sure you open &lt;YourProject&gt;.xcworkspace file using Xcode instead of &lt;YourProject&gt;.xcodeproj.</blockquote><p>3. Open <strong>Podfile</strong> and edit its contents as follows:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/01471be9c44a0b86bca1224c8548f4e8/href">https://medium.com/media/01471be9c44a0b86bca1224c8548f4e8/href</a></iframe><p>If you haven’t setup pods before, please follow guide from <a href="https://guides.cocoapods.org/using/using-cocoapods">here</a>. If you face any error, you can check official <a href="https://firebase.google.com/docs/cloud-messaging/ios/client">FCM guide</a>.</p><h3>Install Firebase Module</h3><p>Run following command in root folder of your react project.</p><pre>npm install --save react-native-firebase</pre><p>You can link firebase node module with native applications using following command:</p><pre>react-native link react-native-firebase</pre><p>Here I will be linking firebase node module with native platforms manually without <strong>react-native link</strong>, since it avoids mess and incomplete bindings most of the times. Moreover, if you are face any issues after linking, you can confirm steps from below that everything is included correctly in native platforms.</p><p><strong>Android Setup</strong></p><ol><li>Edit <strong>MainApplication.java</strong>:</li></ol><pre>import io.invertase.firebase.RNFirebasePackage;<br>import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;                       import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;</pre><pre>@Override<br>protected List&lt;ReactPackage&gt; getPackages() {<br>  return Arrays.&lt;ReactPackage&gt;asList(<br> new MainReactPackage(),<br> new RNFirebasePackage(),<br> new RNFirebaseMessagingPackage(),<br> new RNFirebaseNotificationsPackage()<br> );                               <br>}</pre><p>2. Add these lines in<strong> settings.gradle</strong></p><pre>include &#39;:react-native-firebase&#39;                       project(&#39;:react-native-firebase&#39;).projectDir = new File(rootProject.projectDir, &#39;../node_modules/react-native-firebase/android&#39;)</pre><p>3. In app <strong>build gradle</strong>, add dependency:</p><pre>dependencies {<br>   compile(project(&#39;:react-native-firebase&#39;)) {   <br>       transitive = false<br>   }<br>   // ... other dependencies listed<br>}</pre><p>Sync gradle. You should be good to go for Android. At this point, we can quickly test notification on Android Device from Firebase Console.</p><blockquote>Make sure your application is in background while testing, so that Firebase can automatically deliver to notification tray.</blockquote><p>To test on console:</p><p>a) Go to <strong>Cloud Messaging</strong> section on left Pane.</p><p>b) Click on <strong>Send your first message</strong>.</p><p>c) Enter text, Select your app in <strong>User Segment </strong>and click <strong>Send Message</strong> button. You should be able to receive notification.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Bf3BN4a48I062iHajPcvlg.png" /></figure><p><strong>iOS Setup</strong></p><ol><li>In Project Navigator, right click Libraries &gt; Add Files To &lt;YourProject&gt;. Navigate to &lt;YourProject&gt;/node_modules/react-native-firebase/ios/. Select <strong>RNFirebase.xcodeproj</strong> and click Add button.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JeXn0nOb0lwL_5Q5r9bLgw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/832/1*ag7Q4I5OtMGp9vj8Qo5Klg.png" /></figure><ol><li>Go to Build Phases. Click on the “+” under “Link Binary With Libraries” to add a new library. Add <strong>UserNotifications.framework</strong>. This framework is required since iOS 10 for push notifications handling.</li><li>Again click “+”, select <strong>libRNFirebase.a</strong> and add it. If you are unable to find it, clean and build project.</li><li>Go to Build Settings, find Header Search Path, double click its value and press “+” button. Add following line there:</li></ol><pre>$(SRCROOT)/../node_modules/react-native-firebase/ios/RNFirebase</pre><p>Use “Cmd +Shift + Enter + K” keys to clear cache and then build project. Now firebase dependencies should be recognized by xcode.</p><p>4. In <strong>AppDelegate</strong>:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9feb8a13a50dcfa8548cf3698b2eaa72/href">https://medium.com/media/9feb8a13a50dcfa8548cf3698b2eaa72/href</a></iframe><h3>Receive Push Notifications</h3><p>Now lets code the most awaited part… Receiving Notifications! 😉</p><p><strong>Handling Permissions</strong></p><p>Before app can get any notifications, it is crucial to ask permission from user specially in iOS. If user didn’t allow your app to receive notifications, it can never get any unless user explicitly change it from Settings.</p><p>Open main component of your React Native app, from where basically routing starts i.e. <strong>App.js</strong>. Modify file as per the snippets below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d1811cf52dfe99c58f193a60811b9e3f/href">https://medium.com/media/d1811cf52dfe99c58f193a60811b9e3f/href</a></iframe><ol><li>In <strong>componentDidMount</strong>, we check if user has granted permission to receive push notifications.</li><li>If permission hasn’t been granted to our app, request user in <strong>requestPermission </strong>method. If permission is successfully assigned, proceed towards token fetch, otherwise gracefully ignore the fact.</li><li>If token was fetched earlier, it can be retrieved from <strong>AsyncStorage</strong>. If no token is found, request Firebase and save it in <strong>AsyncStorage</strong>.</li></ol><p><strong>Listening Notifications</strong></p><p>We are now ready to listen push notification events. Before proceeding, you should know about different types of notifications supported by Firebase.</p><ul><li><strong>Notification-only messages:</strong> These are display messages that are automatically handled by Firebase SDK. Notifications are thrown to device tray.</li><li><strong>Notification + optional data messages:</strong> These are also handled by Firebase SDK. Only difference here is when user taps on notification, your app receives payload associated with that notification.</li><li><strong>Data only messages:</strong> These types of notifications are handled exclusively by app. No notification is thrown on device tray unless app explicitly does so. In <strong>iOS</strong>, these types of notifications are also termed as <strong>‘Silent Push Notifications’</strong>.</li></ul><p>For more details, you can read from <a href="https://firebase.google.com/docs/cloud-messaging/concept-options">here</a>.</p><p>Add these lines in <strong>App.js.</strong></p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3110582fce75c9e2d63a71ed4064f25e/href">https://medium.com/media/3110582fce75c9e2d63a71ed4064f25e/href</a></iframe><p>I hope comments would be enough to explain all scenarios. You should be now able to receive notifications on both platforms.</p><blockquote>In <strong>iOS</strong>, you need to test on Device to receive notifications. iOS Simulator doesn’t support Push Notifications currently.</blockquote><blockquote>In <strong>Android</strong>, if you want to test on emulator, you need to install Google Play Services package.</blockquote><p>React-native-firebase is a nice wrapper over Firebase for react native. However, there are few points you should know:</p><ol><li>In Android, if you tap on notification when app is killed, this library won’t be able to catch title and body of notification. Therefore these attributes will be undefined in showAlert function. As a solution, you should also send title and body in data payload of notification.</li><li>To this date, Silent Push Notifications on iOS are not supported by this library. I have already opened an <a href="https://github.com/invertase/react-native-firebase/issues/1278">issue</a> on their repository.</li><li>To listen for data message notifications while the app is in background or killed in Android, you need to implement Headless JS functionality. For details, please refer to <a href="https://github.com/invertase/react-native-firebase-docs/blob/master/docs/messaging/receiving-messages.md#4-optionalandroid-only-listen-for-fcm-messages-in-the-background">this</a> link.</li></ol><p>Hope this tutorial saves your time and make FCM integration easy in react native. If it helps you in anyway, don’t forget to clap! Thanks :)</p><h3>References:</h3><ul><li><a href="https://rnfirebase.io/docs/v4.3.x/notifications/receiving-notifications">React Native Firebase - Simple Firebase integration for React Native</a></li><li><a href="https://github.com/invertase/react-native-firebase-docs/tree/master/docs/messaging">invertase/react-native-firebase-docs</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=349fff071591" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>