Skip to content

Android Custom Notification Layout

Chris Scott edited this page May 8, 2019 · 2 revisions

The BackgroundGeolocation Android SDK runs as a foreground-service, which requires a persistent notification. If the default notification doesn't suit your needs (eg: you want to add custom buttons), you can design your own notification layout:

Step 1 — Create a custom layout file:

Open your application in Android Studio. Select File->New->XML->Layout XML file:

Enter any layout name (eg: notification_layout). Your file will be created in the folder app/res/layouts:

Step 2 — Edit your layout:

Even if you have no experience with Android Layouts, it doesn't take much to figure out the basics. You'll mostly be adding <TextView />, <ImageView /> and <Button /> elements. The key thing to be aware of is the android:id of these elements and how these are referenced from BackgroundGeolocation.notification configuration: your android:id must be prefixed with the word notification (eg: notificationText). There is one exception: applicationName, which the plugin will automatically render your Android application name.

Layout Special Elements

When BackgroundGeolocation renders your custom notification layout, it will be querying for the following elements addressed by their android:id. When found, their content will be updated from the corresponding "Data-source":

Layout element android:id Data-source
applicationName Application name from AndroidManifest
notificationTitle notification.title
notificationText notification.text
notificationSmallIcon notification.smallIcon
notificationLargeIcon notification.largeIcon
BackgroundGeolocation.ready({
  notification: {
    layout: "my_notification_layout",  // <-- custom layout xml file
    title: "The Notification Title", 
    text: "The Notification Text",     
    smallIcon: "mipmap/my_small_icon", // <-- defaults to app icon
    largeIcon: "mipmap/my_large_icon"
});

Custom <TextView /> Elements

You can declare your own custom <TextView /> elements and render data into them using the notification.strings parameter.

<TextView
    android:id="@+id/myCustomElement"  // <-- myCustomElement
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="notificationTitle" />

You can provide data to your custom elements using the notification.strings configuration parameter:

BackgroundGeolocation.ready({
  notification: {
    strings: {
      myCustomElement: "My Custom Element Text"
    }
  }
});

Custom <Button /> Elements:

You can declare your own custom <Button /> elements and register click-listeners upon them using the notification.actions parameter:

<Button
    android:id="@+id/notificationButtonFoo" // <-- notificationButtonFoo
    style="@style/Widget.AppCompat.Button.Small"
    android:layout_width="60dp"
    android:layout_height="40dp"
    android:text="Foo" />

Register listeners for your button using notification.actions:

BackgroundGeolocation.ready({
  notification: {
    actions: [  // <-- register button listeners
      'notificationButtonFoo',
      'notificationButtonBar'
    ]
  }
});

// Listen to custom button clicks:
BackgroundGeolocation.onNotificationAction((buttonId) => {
  console.log('[onNotificationAction] - ', buttonId);
  switch(buttonId) {
    case 'notificationButtonFoo':
      break;
    case 'notificationButtonBar':
      break;
  }
});

Sample Layout

As a starting-point for your custom layout, copy the following content into your new file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="135dp"
    android:gravity="start"
    android:adjustViewBounds="true"
    android:orientation="vertical"
    android:padding="15dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="15dp"
        android:gravity="center"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/notificationSmallIcon"
            android:layout_width="16dp"
            android:layout_height="16dp"
            android:tint="@android:color/background_dark"
            tools:srcCompat="@tools:sample/avatars" />

        <TextView
            android:id="@+id/applicationName"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingLeft="10dp"
            android:text="applicationName"
            android:textAppearance="@style/TextAppearance.Compat.Notification.Title"
            android:textColor="#888888"
            android:textSize="12sp" />
    </LinearLayout>

    <TextView
        android:id="@+id/notificationTitle"
        style="@style/TextAppearance.Compat.Notification.Title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="notificationTitle"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/notificationText"
        style="@style/TextAppearance.Compat.Notification.Line2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="notificationText"
        android:textSize="14sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:gravity="right"
        android:orientation="horizontal">

        <Button
            android:id="@+id/notificationButtonFoo"
            style="@style/Widget.AppCompat.Button.Small"
            android:layout_width="60dp"
            android:layout_height="40dp"
            android:text="FooA" />

        <Button
            android:id="@+id/notificationButtonBar"
            style="@style/Widget.AppCompat.Button.Small"
            android:layout_width="60dp"
            android:layout_height="40dp"
            android:text="Bar" />
    </LinearLayout>
</LinearLayout>

Step 3 — config.xml

Since Cordova platforms are volatile, destroyed when you cordova platform remove android, you need to save your notification_layout.xml file within your application /src folder and configure config.xml to copy the file into the android app's res/layouts folder using a <resource-file> block:

  • Create a new file in the root of your app src/android/notification_layout.xml and copy the XML content into it from the steps above.
  • Edit config.xml. Add the following block into the <platform name="android"> container:
<platform name="android">
    <resource-file
        src="src/android/notification_layout.xml" 
        target="app/src/main/res/layout/notification_layout.xml" />
    .
    .
    .
</platform>

Each time you cordova build android, your notification_layout.xml file will be copied into the android app's res/layouts folder.

Step 4 — Using your custom layout:

BackgroundGeolocation.ready({
  notification: {
    title: 'The title',
    text: 'The text',
    layout: 'notification_layout',  // <-- the name of your file (without .xml)
    actions: [
      'notificationButtonFoo',  // <-- register button click-listeners
      'notificationButtonBar'
    ],
    strings: {
      'myCustomTextBox': 'custom TextBox element'
    }
  }
});

// Listen to custom notification button clicks (notification.actions)
BackgroundGeolocation.onNotificationAction((buttonId) => {
  console.log('[onNotificationAction] - ', buttonId);
  switch(buttonId) {
    case 'notificationButtonFoo':
      // Handle button click on [Foo]
      break;
    case 'notificationButtonBar':
      // Handle button click on [Bar]
      break;
  }
});