Cordova-plugin-firebase: Android Status Bar Icon - All White

Created on 13 Sep 2016  ·  25Comments  ·  Source: arnesson/cordova-plugin-firebase

Hi,
I have been trying to find away to change the icon that is displayed on a android status bar when a push notification is delivered. Here is an example of what is happening:

screenshot_2016-09-13-08-53-22

As you can see the icon for my app is not a transparent image. If i change it to a transparent image the push icon looks fine but the app icon is now the transparent image and that isn't what i want. I have tried different variations of file names but nothing seems to work. When looking into the code, src/android/FirebasePluginMessagingService.java on line 73 there is this:
.setSmallIcon(getApplicationInfo().icon)

Am i correct in saying that you can not set a different icon than your app icon?
Would it be possible to set a different file for the status bar icon?
Or any other suggestions on how to get round this issue?

Most helpful comment

Thanks @blckshrk !! I finally got it working doing that!

I'm using Ionic v2 and [email protected]:
Ionic: 2.2.2
cordova: 6.5.0
npm: 4.6.1

  1. Install the custom-config plugin:
    $ ionic plugin add cordova-custom-config --fetch --save

  2. Download https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_resources.js and https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_values.js into a new directory called "package-hooks" (or whatever you want) in your project root.
    package-hooks/android_custom_resources.js
    package-hooks/android_custom_values.js

  3. Create the following directories and files in your project root (not inside platforms):
    resources/android/custom/notification_icon.png
    resources/android/values/styles.xml

notification_icon.png is your Android >= API 21 notification icon. Mine is 144x144px and it looks great.

styles.xml contains:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="red">#FF8614</color>
</resources>
  1. Edit config.xml. Important: Make sure you add that namespace in the widget tag.
    <widget ... xmlns:android="http://schemas.android.com/apk/res/android">
        <platform name="android">
            <hook src="package-hooks/android_custom_resources.js" type="after_prepare"/>
            <hook src="package-hooks/android_custom_values.js" type="after_prepare"/>
            <config-file parent="./application" target="AndroidManifest.xml">
                <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
                <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/red"/>
            </config-file>
        </platform>
    <widget>

And that's all!

All 25 comments

I have not tested this, but you should be able to set a custom icon by creating fcm_push_icon.png in all required sizes. As default the app icon will be used if fcm_push_icon.png does not exist. The icons should be in the android/res folder tree.

you can use this to generate all the different sizes: http://romannurik.github.io/AndroidAssetStudio/icons-notification.html

Hi, we are facing the same issue. We tried to place fcm_push_icon.png icons in the android/res folder tree, but the notification icon is still white.

@MikeBateman have you found a solution?

Hello, to get around the issue you can change the target sdk of your app, please check this, but of course it is not a propper solution.

I've been reasearching and got this solution:

Go to this route src/android/FirebasePluginMessagingService.java and find this line .setSmallIcon(getApplicationInfo().icon) (like @MikeBateman mentioned), now add a condition that will check if the app is running in android lollipop+, if it is true the notification should use a material design icon if it isn't, it'll use the default app's icon, the code:

...

  .setSmallIcon(getNotificationIcon())
...

//At the end of FirebasePluginMessagingService.java 
    private int getNotificationIcon() {
        boolean useWhiteIcon = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP);
        System.out.println("SCLMTEST >lollipop?:"+useWhiteIcon);
        return useWhiteIcon ? R.drawable.myMaterialIcon: getApplicationInfo().icon;
    }

I think the best would be just to put your material design icon in myappresources and the plugin do this job by itself, now I don't know how to do it so, if anybody can it would be great, hope it helps! @delphaber

fixed in 33c52c7e8a1835d5f595e58eaef43e4f49b4b23a

the plugin will now use notification_icon in drawable, if it exists. otherwise it will use the default app icon

Hey,

I don't get it. I try to put a notification_icon.png in each drawable folder (for each size), but the plugin still uses the default one (app icon). Did I missed something ?

Thanks!

@blckshrk cc/ @robertarnesson

I ran into the same thing while after updated the Android src files and adding all of the notification_icon.png files I still was just seeing the white square. I ended up following the advice from here: http://stackoverflow.com/questions/37325051/notification-icon-with-the-new-firebase-cloud-messaging-system

First I had to update my Google Repository to make the latest Firebase SDK the most up to date on my computer. This is version 9.8.0 for com.google.firebase:firebase-core at the moment of writing this and me getting it to work. (I was on 9.4.0 before)

Then I added this to my AndroidManifest.xml:

<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />

If you want to use their option to change the default_notification_color you need to add the following. Our icon is white icon with a transparent background, so we added our own color behind which is nice on the lock screen.

<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/orange" />

You also need to add a res/values/colors.xml file with the following, which your own color choice of course if you are setting the background:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="orange">#FF8614</color>
</resources>

This all works as of Firebase 9.8.0

@blckshrk how do you add the icon(s) to the project? you need to use your project's config.xml to add them to resources. just putting them in the folder won't make them visible for the code as far as I know

Currently I am using Ionic 2 to create my app and doing the following:
I have added icon files to the res folder of ionic so if I run the command ionic resources the images for different screen sizes are created.

This also adds the image paths to the config.xml file.

Can some one please make a detailed reply as to what exactly needs to be done..

  • Like where the files need to be added in which folder exactly for Android
  • do they need to be added in the config.xml file
  • what is the image size of the files

I have no knowledge of Native Android code and folder structure so do reply accordingly.

-Thanks

Actually like @prantikv I'm a little bit lost. I use Ionic 1 (but with the same workflow). I tried to put my icon in res/drawable/ and use cordova-custom-config to add <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" /> in my AndroidManifest.xml (in the manifest node directly), but nothing works as expected.

@gylippus I don't get the com.google.firebase:firebase-core part. How do you check the version ?

Thanks guys!

@robertarnesson @gylippus Have you a working example ?

I managed to make it work with cordova-custom-config

<config-file parent="./application" target="AndroidManifest.xml">
          <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

and a platforms/android/res/drawable/notification_icon.png

Thanks a lot for your help !

It could be great to have a hook to automaticaly do this job (move the file and edit the manifest) if an notification_icon.png is in the root (or resources) folder (as it is for the config files). What did think about it ?

@blckshrk
I tried adding the following code as you mentioned

<config-file parent="./application" target="AndroidManifest.xml">
          <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

But I get the following error during the build process

:processDebugResources
E:\Development\IONIC 2\allcouriertracking\allcouriertracking5\platforms\android\res\xml\config.xml:57 : AAPT: Error parsing XML: unbound prefix


 FAILED

FAILURE: Build failed with an exception.


:processDebugResources
E:\Development\IONIC 2\allcouriertracking\allcouriertracking5\platforms\android\res\xml\config.xml:57 : AAPT: Error parsing XML: unbound prefix


 FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':processDebugResources'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'I:\DEVELOPMENT PROGRAMS\android-sdk-windows\build-tools\24.0.3\aapt.exe'' finished with non-zero exit value 1

I then manually added the following to AndroidManifest.xml
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />

And it worked for Android 4.4 But it is not working for Android 5.1.

Which version did you build for?
Also did you add the notification_icon.png file in all drawable folders or just one?

@prantikv Did you install https://github.com/dpa99c/cordova-custom-config ?

Actually I use this hook https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_resources.js to automatically move the notification_icon.png file into each drawable folders.

Basicaly I have this inside the <platform name="android"> node :

<hook src="hooks/after_prepare/android_custom_resources.js" type="after_prepare"/>
<config-file parent="./application" target="AndroidManifest.xml">
    <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon" />
</config-file>

EDIT

I also managed to deal with the color by using this hook https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_values.js and the solution proposed by @gylippus (thanks!)

@blckshrk Yes I did Install the plugin..Can you let me know the Image size that you are using..The image dimentions as well as the size in KB.
And the platform that you have tested it.

Any updates on this? 20 days now and still no solution? It cannot be closed if it is still an issue?!

I had the same problem and I could solve it from the server side. I placed manually the icon to the drawable folders inside the platform-android folder with the name notification_icon.png.
Through the Firebase console I keep seeing the wrong icon, but a own server I send the following as a body of the request:

$fields = array(
  "registration_ids" => "array of registration ids",
  "notification" => array(
    "body"=>"message to send as a body",
    "icon"=>"notification_icon",
    "color"=>"your color in hex"
  ),
  "priority"=>10
);

Hope this help

Actually, after some logging and reading, it seems to me the whole notificationBuilder code in FirebasePluginMessagingService.java / sendNotification is moot as it is never run when there is a notification payload. Aside from the icon issue, I also started to suspect this as the notificationBuilder code does a .setSound(defaultSoundUri) but it is never played when notifications arrive in the tray.

This is why sergiojup's solution above works, as the notification is not being built by the plugin code but by FCM itself which takes instructions from the notification payload.

As for the why.. on Android, onMessageReceived is only called when:
*) there ONLY is a notification payload and app is in the foreground
*) there is a notification payload AND data payload and app is in the foreground
*) there ONLY is a data payload and app is in the foreground or background

So in these cases, onMessageReceived is NOT called:
*) there ONLY is a notification payload and app is in the background
*) there is a notification payload AND data payload and app is in the background

Looking at the code, the only way to have the plugin build the notification is to use data payload only, that has both title and text properties, while the app is in the background.

Thanks @blckshrk !! I finally got it working doing that!

I'm using Ionic v2 and [email protected]:
Ionic: 2.2.2
cordova: 6.5.0
npm: 4.6.1

  1. Install the custom-config plugin:
    $ ionic plugin add cordova-custom-config --fetch --save

  2. Download https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_resources.js and https://github.com/driftyco/ionic-package-hooks/blob/master/android_custom_values.js into a new directory called "package-hooks" (or whatever you want) in your project root.
    package-hooks/android_custom_resources.js
    package-hooks/android_custom_values.js

  3. Create the following directories and files in your project root (not inside platforms):
    resources/android/custom/notification_icon.png
    resources/android/values/styles.xml

notification_icon.png is your Android >= API 21 notification icon. Mine is 144x144px and it looks great.

styles.xml contains:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="red">#FF8614</color>
</resources>
  1. Edit config.xml. Important: Make sure you add that namespace in the widget tag.
    <widget ... xmlns:android="http://schemas.android.com/apk/res/android">
        <platform name="android">
            <hook src="package-hooks/android_custom_resources.js" type="after_prepare"/>
            <hook src="package-hooks/android_custom_values.js" type="after_prepare"/>
            <config-file parent="./application" target="AndroidManifest.xml">
                <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
                <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/red"/>
            </config-file>
        </platform>
    <widget>

And that's all!

I don't understand where to add the following in config.xml? Tips on that? Also, I'm not really familiar with XML, what should I add in the namespace exactly? @shamank

<widget ... xmlns:android="http://schemas.android.com/apk/res/android"> <platform name="android"> <hook src="package-hooks/android_custom_resources.js" type="after_prepare"/> <hook src="package-hooks/android_custom_values.js" type="after_prepare"/> <hook src="package-hooks/android_fixes.js" type="after_prepare"/> <config-file parent="./application" target="AndroidManifest.xml"> <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/> <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/red"/> </config-file> </platform> <widget>

@Rockforced Sorry, I've not been around these days. Take a look at the original file (with some replaced things, of course). Hope it helps.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.example" version="1.0.20" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
    <name>Test</name>
    <description>Blabla.</description>
    <author email="[email protected]" href="https://example.com/">Example</author>
    <content src="index.html"/>
    <access origin="*"/>
    <allow-navigation href="http://ionic.local/*"/>
    <allow-navigation href="http://192.168.0.1:8100"/>
    <allow-intent href="http://*/*"/>
    <allow-intent href="https://*/*"/>
    <allow-intent href="tel:*"/>
    <allow-intent href="sms:*"/>
    <allow-intent href="mailto:*"/>
    <allow-intent href="geo:*"/>
    <platform name="android">
        <allow-intent href="market:*"/>
        <hook src="package-hooks/android_custom_resources.js" type="after_prepare"/>
        <hook src="package-hooks/android_custom_values.js" type="after_prepare"/>
        <hook src="package-hooks/android_fixes.js" type="after_prepare"/>
        <config-file parent="./application" target="AndroidManifest.xml">
            <meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/notification_icon"/>
            <meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/red"/>
        </config-file>
        <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png"/>
        <icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png"/>
        <icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png"/>
        <icon density="xhdpi" src="resources/android/icon/drawable-xhdpi-icon.png"/>
        <icon density="xxhdpi" src="resources/android/icon/drawable-xxhdpi-icon.png"/>
        <icon density="xxxhdpi" src="resources/android/icon/drawable-xxxhdpi-icon.png"/>
        <splash density="port-ldpi" src="resources/android/splash/drawable-port-ldpi-screen.png"/>
        <splash density="port-mdpi" src="resources/android/splash/drawable-port-mdpi-screen.png"/>
        <splash density="port-hdpi" src="resources/android/splash/drawable-port-hdpi-screen.png"/>
        <splash density="port-xhdpi" src="resources/android/splash/drawable-port-xhdpi-screen.png"/>
        <splash density="port-xxhdpi" src="resources/android/splash/drawable-port-xxhdpi-screen.png"/>
        <splash density="port-xxxhdpi" src="resources/android/splash/drawable-port-xxxhdpi-screen.png"/>
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*"/>
        <allow-intent href="itms-apps:*"/>
        <icon height="57" src="resources/ios/icon/icon.png" width="57"/>
        <icon height="114" src="resources/ios/icon/[email protected]" width="114"/>
        <icon height="40" src="resources/ios/icon/icon-40.png" width="40"/>
        <icon height="80" src="resources/ios/icon/[email protected]" width="80"/>
        <icon height="120" src="resources/ios/icon/[email protected]" width="120"/>
        <icon height="50" src="resources/ios/icon/icon-50.png" width="50"/>
        <icon height="100" src="resources/ios/icon/[email protected]" width="100"/>
        <icon height="60" src="resources/ios/icon/icon-60.png" width="60"/>
        <icon height="120" src="resources/ios/icon/[email protected]" width="120"/>
        <icon height="180" src="resources/ios/icon/[email protected]" width="180"/>
        <icon height="72" src="resources/ios/icon/icon-72.png" width="72"/>
        <icon height="144" src="resources/ios/icon/[email protected]" width="144"/>
        <icon height="76" src="resources/ios/icon/icon-76.png" width="76"/>
        <icon height="152" src="resources/ios/icon/[email protected]" width="152"/>
        <icon height="167" src="resources/ios/icon/[email protected]" width="167"/>
        <icon height="29" src="resources/ios/icon/icon-small.png" width="29"/>
        <icon height="58" src="resources/ios/icon/[email protected]" width="58"/>
        <icon height="87" src="resources/ios/icon/[email protected]" width="87"/>
        <splash height="1136" src="resources/ios/splash/Default-568h@2x~iphone.png" width="640"/>
        <splash height="1334" src="resources/ios/splash/Default-667h.png" width="750"/>
        <splash height="2208" src="resources/ios/splash/Default-736h.png" width="1242"/>
        <splash height="2048" src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536"/>
        <splash height="1024" src="resources/ios/splash/Default-Portrait~ipad.png" width="768"/>
        <splash height="960" src="resources/ios/splash/Default@2x~iphone.png" width="640"/>
        <splash height="480" src="resources/ios/splash/Default~iphone.png" width="320"/>
    </platform>
    <preference name="webviewbounce" value="false"/>
    <preference name="UIWebViewBounce" value="false"/>
    <preference name="DisallowOverscroll" value="true"/>
    <preference name="android-minSdkVersion" value="16"/>
    <preference name="android-targetSdkVersion" value="23"/>
    <preference name="BackupWebStorage" value="none"/>
    <preference name="SplashMaintainAspectRatio" value="true"/>
    <preference name="SplashReloadOnOrientationChange" value="true"/>
    <preference name="SplashScreenDelay" value="3000"/>
    <preference name="FadeSplashScreen" value="false"/>
    <preference name="FadeSplashScreenDuration" value="0"/>
    <preference name="orientation" value="portrait"/>
    <preference name="SplashScreenBackgroundColor" value="0xFFFFFFFF"/>
    <preference name="SplashScreen" value="screen"/>
    <preference name="AutoHideSplashScreen" value="false"/>
    <preference name="KeyboardDisplayRequiresUserAction" value="false"/>
    <preference name="loadUrlTimeoutValue" value="700000"/>
    <feature name="StatusBar">
        <param name="ios-package" onload="true" value="CDVStatusBar"/>
    </feature>
    <feature name="InAppBrowser">
        <param name="ios-package" value="CDVInAppBrowser"/>
        <param name="android-package" value="org.apache.cordova.inappbrowser.InAppBrowser"/>
    </feature>
    <plugin name="cordova-plugin-app-event" spec="~1.2.0"/>
    <plugin name="cordova-plugin-device" spec="~1.1.3"/>
    <plugin name="cordova-plugin-console" spec="~1.0.4"/>
    <plugin name="cordova-plugin-whitelist" spec="~1.3.2"/>
    <plugin name="cordova-plugin-splashscreen" spec="~4.0.2"/>
    <plugin name="cordova-plugin-statusbar" spec="~2.2.2"/>
    <plugin name="ionic-plugin-keyboard" spec="~2.2.1"/>
    <plugin name="cordova-plugin-geolocation" spec="~2.4.1"/>
    <plugin name="cordova-plugin-compat" spec="~1.1.0"/>
    <plugin name="cordova-plugin-inappbrowser" spec="~1.6.1"/>
    <plugin name="cordova-plugin-nativestorage" spec="~2.2.2"/>
    <plugin name="cordova-plugin-firebase" spec="~0.1.20"/>
    <plugin name="cordova.plugins.diagnostic" spec="~3.0.4"/>
    <plugin name="cordova-plugin-googlemaps" spec="~1.4.0">
        <variable name="API_KEY_FOR_ANDROID" value="blabla"/>
        <variable name="API_KEY_FOR_IOS" value="blabla"/>
    </plugin>
    <plugin name="ionic-plugin-deeplinks" spec="~1.0.14">
        <variable name="URL_SCHEME" value="blabla"/>
        <variable name="DEEPLINK_SCHEME" value="https"/>
        <variable name="DEEPLINK_HOST" value="www.blabla.com"/>
        <variable name="ANDROID_PATH_PREFIX" value="/"/>
    </plugin>
    <plugin name="cordova-custom-config" spec="~3.2.0"/>
    <icon src="resources/ios/icon/[email protected]"/>
    <engine name="android" spec="~6.2.2"/>
</widget>

@shamank Thank you so much for this. Have been battling with version 0.1.24 all day not having any luck and your solution worked. Are you able to let me know why exactly this makes the custom icon work? I followed the instructions in the read me very closely and it just only ever showed a greyed out icon. Your solution worked immediately... I'd just like to know why!

@jskidd3 Glad it helped! It's really quit simple. The cordova-custom-config plugin lets you make changes in Cordova's final config for each platform (Info.plist / AndroidManifest.xml). So, in config-file block, you tell plugin's config for Android to search for "default_notification_icon" in the drawables directory under the new name of "notification_icon" (plugin handles file extension if I remember well). Then you define the background color in the next block (red). Now you need a way to get that file (notification_icon.png) in the right place at building time, so you need a hook to do that. That is android_custom_resources.js. It takes whatever is in resources/android/custom/* and puts in build's drawable directories (you can change this by editing the script, but it's ok for this task). Similar with additional config styles. You create this styles.xml file; define the color (I named it "red" but it can be whatever you want) and then android_custom_values.js copies it to the builded directory "platforms/android/res/values". Finally, in config.xml you bind these scripts to run in a certain moment. For this task, they need to be copied "after_prepare", which means, after Cordova prepared the builds (again, if I remember well... you can check Ionic's package hooks docs for more details/events).

@alexbonhomme's answer worked for me :) https://github.com/arnesson/cordova-plugin-firebase/issues/53#issuecomment-304573222

@shamank's decision works for me partially.
I'm using Angular + Cordova.

Everything works except one thing: android_custom_resources.js will not create folders (drawable-ldpi, drawable-mdpi etc.) and will not copy files if folders aren't existing.

So I've removed that script and used in config.xml:

Note: paths can be different due custom changes and [email protected] and > has res/ folder in another place.

`

    <resource-file src="res/custom/android/notification.png" target="app/src/main/res/drawable-mdpi/notification.png" />

    <resource-file src="res/custom/android/notification.png" target="app/src/main/res/drawable-hdpi/notification.png" />

    <resource-file src="res/custom/android/notification.png" target="app/src/main/res/drawable-xhdpi/notification.png" />

    <resource-file src="res/custom/android/notification.png" target="app/src/main/res/drawable-xxhdpi/notification.png" />

    <resource-file src="res/custom/android/notification.png" target="app/src/main/res/drawable-xxxhdpi/notification.png" />`

Anyway, thank you @alexbonhomme and @shamank !

For Ionic 3(more specifically for cordova-android@7) in @shamank 's solution paths inside:
package-hooks/android_custom_resources.js package-hooks/android_custom_values.js
shall be updated because res folder is inside platforms/android/app/src/main/ now.

  1. go to package-hooks/android_custom_resources.js and update
    var platformDir = 'platforms/android';
    to
    var platformDir = 'platforms/android/app/src/main';

  2. go to package-hooks/android_custom_values.js and update
    var platformDir = platforms/android/res/values';
    to
    var platformDir = 'platforms/android/app/src/main/res/values';

Was this page helpful?
0 / 5 - 0 ratings