title: Android FireBase Notification with optional Data, using V1 API, not working for background
body: <p>I am sure there is an answer out there, but I can't seem to find it. Most examples are using the legacy HTTP FireBase call (and 2 years ago), but I want to use the new V1 HTTP API. I can get it to work when the App is running in the foreground (who hasn't), but not in background or when the app is not running. Complicating things is we are also supporting IOS, so the same message must work for both.</p>
  
  <p>A few other items to be very clear about what I am trying to do:</p>
  
  <ol>
  <li>If App is in foreground the FireBase Service is working fine and I get the notification and get the data. I will show that code a bit later</li>
  <li>If the App is not running, when I click the Notification in the system tray I want to be able to get the Data from the notification and process it. Not Working.</li>
  <li>If the App is running in the background, when I click the Notification in the system tray I want to be able to get the Data from the notification and process it. Not Working.</li>
  </ol>
  
  <p>I suspect it have something wrong with my Setup in the AndroidManifest.xml and/or in the actual message, but I have tried a ton of variations with no success.</p>
  
  <p>First, the message I am posting from FireBase to the device currently:</p>
  
  <pre><code>{
    "message":{
       "token":"mynastylongdevicetoken...",
       "data":{
        "State":"Whatever",
       },
       "notification":{
          "title":"New Info",
          "body":"A new info has been dispatched to you"
       },
       "android": {
          "notification": {
            "click_action": ".StartActivity"
          }
       }
    }
  }
  </code></pre>
  
  <p>Note about the above message - I have tried various combinations of the "click_action" such as "StartActivity" ".StartActivity" ".SplashActivity" "SplashActivity".</p>
  
  <p>This is based on the latest documentation from FireBase:</p>
  
  <p><a href="https://firebase.google.com/docs/cloud-messaging/migrate-v1" rel="nofollow noreferrer">https://firebase.google.com/docs/cloud-messaging/migrate-v1</a></p>
  
  <p>and</p>
  
  <p><a href="https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#AndroidNotification" rel="nofollow noreferrer">https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#AndroidNotification</a></p>
  
  <p>Now my <code>AndroidManifest.xml</code>. This is bit more complicated, since I have some deeplinks implemented and I would prefer to reuse the same Activity for that, but if I need to create a new one, so be it. Currently I have two main entry point Activities. One for the launcher called <code>SplashActivity</code> which is used to throw up a splash image and one for deep linking called <code>StartActivity</code>. Here is the XML for both:</p>
  
  <pre><code>  &lt;activity
          android:name="com.mycompany.SplashActivity"
          android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
          android:label="@string/app_name"
          android:launchMode="singleTask"
          android:theme="@style/Theme.Splash" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
      &lt;activity
          android:name="com.mycompany.StartActivity"
          android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
          android:label="StartActivity"
          android:launchMode="singleTask"
          android:windowSoftInputMode="stateHidden" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.VIEW" /&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink1"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink2"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink3"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink4"/&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  </code></pre>
  
  <p>Now the source code. I have two main "chunks" of code. The first is your standard FireBase Message Servicing code which when the App is in foreground works:</p>
  
  <pre><code>public class MyCompanyFirebaseMessagingService extends FirebaseMessagingService {
      @Override
      public void onMessageReceived(RemoteMessage remoteMessage) {
          // Check if message contains a data payload.
          if (remoteMessage.getData().size() &gt; 0) {
              String test = remoteMessage.getData().get("State");
  
      }
  }
  </code></pre>
  
  <p>and</p>
  
  <pre><code>public class MyCompanyInstanceIDService extends FirebaseInstanceIdService {
      public void sendNotification ( ) {
              String token = FirebaseInstanceId.getInstance().getToken();
              if (!Utilities.stringIsBlank(token)) {
                  // Register with our server
              }
      }
  }
  </code></pre>
  
  <p>And the AndroidManifest.xml reference:</p>
  
  <pre><code>&lt;service android:name="com.mycompany.MyCompanyMessagingService"&gt;
      &lt;intent-filter&gt;
          &lt;action android:name="com.google.firebase.MESSAGING_EVENT" /&gt;
      &lt;/intent-filter&gt;
  &lt;/service&gt;
  &lt;service android:name="com.mycompany.MyCompanyInstanceIDService"&gt;
      &lt;intent-filter&gt;
          &lt;action android:name="com.google.firebase.INSTANCE_ID_EVENT"/&gt;
      &lt;/intent-filter&gt;
  &lt;/service&gt;
  </code></pre>
  
  <p>The second chunk I have put into the OnCreate of the two forementioned Activities to try to pull the data from the Intent extra in the OnCreate of the Activities. I have not see any data come in thru that mechanism that a lot of the other StackOverflows have suggested it should (they were generally over a year old and may not apply to V1 of the API?). Here is the example of it:</p>
  
  <pre><code>protected void onCreate(Bundle savedInstanceState) 
  {
      if (getIntent().getExtras() != null) {
          String test = getIntent().getExtras().getString("State", "");
      }
  }
  </code></pre>
  
  <p>I have looked at the myriad of other StackoverFlows on this subject without success. I can list them if you want - maybe I have missed something there? The one with the most hits (224,000) did not help. </p>
  
  <p>Thanks in advance!</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Thanks to Bob for the help. Just wanted to mark the changes so others will not be lost in strange way Android is handling this (IOS does not seem to have such problems, lucky them).</p>
  
  <p>First the <code>AndroidManifest.xml</code> as shown in the answer, now has a new intent filter:</p>
  
  <pre><code> &lt;activity
          android:name="com.mycompany.SplashActivity"
          android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
          android:label="@string/app_name"
          android:launchMode="singleTask"
          android:theme="@style/Theme.Splash" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.MAIN" /&gt;
              &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
          &lt;/intent-filter&gt;
          &lt;intent-filter&gt;
              &lt;action android:name="com.mycompany.NOTIFICATION_CLICK" /&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
      &lt;activity
          android:name="com.mycompany.StartActivity"
          android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
          android:label="StartActivity"
          android:launchMode="singleTask"
          android:windowSoftInputMode="stateHidden" &gt;
          &lt;intent-filter&gt;
              &lt;action android:name="android.intent.action.VIEW" /&gt;
              &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink1"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink2"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink3"/&gt;
              &lt;data android:scheme="@string/launch_protocol" android:host="deeplink4"/&gt;
          &lt;/intent-filter&gt;
      &lt;/activity&gt;
  </code></pre>
  
  <p>The code was pretty much right in the <code>onCreate()</code>. Just need to check for the <code>Intent</code> for <code>extras</code> if the app is not running or in the background. When in foreground the  <code>public void onMessageReceived(RemoteMessage remoteMessage)</code> will be called and only if a Notification is in the message. If you are data only or, like me, Notification with extra data, you will have to implement both the <code>onCreate()</code> Intent and <code>onMessageReceived()</code> in the Firebase service above.</p>
  
  <p>The new message is as follows:</p>
  
  <pre><code>{
    "message":{
       "token":"mynastylongdevicetoken...",
       "data":{
        "State":"Whatever",
       },
       "notification":{
          "title":"New Info",
          "body":"A new info has been dispatched to you"
       },
       "android": {
          "notification": {
            "click_action": "com.mycompany.NOTIFICATION_CLICK"
          }
       }
    }
  }
  </code></pre>
  
  <p>Finally, I was never able to get the notification to be picked up by selecting the App from the tool bar (when it had the indication of the notification) if the App was not already running. Not sure if that is the desired behavior or if I just messed up somewhere. </p>
  
  <p>Finally, I wanted to pull up the currently running <code>Activity</code> if the App was already running foreground or background, or start the app if it was not. To do that I had to add the following to the onCreate() of the Activity targeted to receive the notification:</p>
  
  <pre><code>protected void onCreate(Bundle savedInstanceState) 
  {
      if (getIntent().getExtras() != null) {
          String test = getIntent().getExtras().getString("State", "");
      }
      // If this activity is the root activity of the task, the app is not running
      if (isTaskRoot()) {
          setContentView(R.layout.activity_splash);
      }
      else
          finish();
  }
  </code></pre>
  
  <p>Basically it checks to see if the <code>SplashActivity</code> is the root, meaning that it is the only activity (new start) or not (app already running). If so it would just finish and pull the App forward.</p>
  
  <p>What I am surprised by is how hard this turned out to be using a Google product (Firebase) with a Google product (Android), where as with IOS (I am told) this was all easy and built it. </p>