Skip to content

Notifications Tutorial and Examples

A notification is a message that android displays outside an app’s UI to provide reminders, communication with other people or timely information from your app.

Then when the user taps the notification, the app is opened or an action can be directly taken.

Let's look at several examples

Example 1: Android Status Bar Notification Example with Vibration

Let's now look at a simple Notification example in Java. This example will do the following for us:

  1. Show a Flaoting Action Button that when clicked will show a status bar notification.
  2. When the user clicks the Notification, we will bring up a new activity where we will be receiving a Notification ID.
  3. We will vibrate the device when the notification is displayed.

Here is the video tutorial:

MainActivity

  • MainActivity class.
  • Create and show Notification with alarm sound as well.
  • Increment messageCount.
  • When notifictaion is clicked open new activity
package com.tutorials.hp.hellonotifications;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.TaskStackBuilder;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.NotificationCompat;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private int messageCount = 0;
    private static Uri alarmSound;
    // Vibration pattern long array
    private final long[] pattern = { 100, 300, 300, 300 };
    private NotificationManager mNotificationManager;

    /*
    - When activity is created.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        // DEFAULT ALARM SOUND
        alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);

        // INITIALIZE NOTIFICATION MANAGER
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showNotification();
            }
        });
    }
    /*
    - Create Notification
    - Show Notification
     */
    protected void showNotification() {
        Log.i("Start", "notification");

        // Invoking the default notification service
        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(MainActivity.this);

        mBuilder.setContentTitle("ProgrammingWizards TV");
        mBuilder.setContentText("We've just released a new android video at our channel");
        mBuilder.setTicker("New Message Alert!");
        mBuilder.setSmallIcon(R.drawable.series);

        //Increment message count when a new message arrives
        mBuilder.setNumber(++messageCount);
        mBuilder.setSound(alarmSound);
        mBuilder.setVibrate(pattern);

        // Explicit intent to open notifactivity
        Intent i = new Intent(MainActivity.this,NotifActivity.class);
        i.putExtra("notificationId", 111);
        i.putExtra("message", "http://www.camposha.info");

        // Task builder to maintain task for pending intent
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        stackBuilder.addParentStack(NotifActivity.class);

        // Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(i);

        //PASS REQUEST CODE AND FLAG
        PendingIntent pendingIntent = stackBuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pendingIntent);

        // notificationID allows you to update the notification later on.
        mNotificationManager.notify(111, mBuilder.build());
    }
    //end
}

NotifActivity.java

NotifActivity

Here are our NotifActivity.java file.

  • Our NotifActivity class.
  • Opened when notification message is clicked.
  • Receives notifictaion id as well as message and displays in a textview.
  • Then clears the statusbar of the notification once its read
package com.tutorials.hp.hellonotifications;

import android.app.NotificationManager;
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.util.Linkify;
import android.widget.TextView;

public class NotifActivity extends AppCompatActivity {
    /*
    - Set received notification to textview.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_notif);

        TextView receivedTxt = (TextView) findViewById(R.id.notificationTxt);
        receivedTxt.setText(receiveData());
        Linkify.addLinks(receivedTxt, Linkify.ALL);
    }
    /*
    - Receive intent data and return
    - Then clear notification it from statusbar
     */
    private String receiveData()
    {
        String message = "";
        int id = 0;

        Bundle extras = getIntent().getExtras();// get intent data
        if (extras == null) {
            // If it is null then show error
            message = "Error";
        } else {
            // get id and message
            id = extras.getInt("notificationId");
            message = extras.getString("message");
        }
        message = "Notification Id : " + id + "n Message : " + message;
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        // remove the notification with the specific id
        mNotificationManager.cancel(id);

        return message;
    }
}

activity_main.xml

Here is our activity_main.xml layout file.

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    tools_context="com.tutorials.hp.hellonotifications.MainActivity">

    <android.support.design.widget.AppBarLayout
        android_layout_width="match_parent"
        android_layout_height="wrap_content"
        android_theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android_id="@+id/toolbar"
            android_layout_width="match_parent"
            android_layout_height="?attr/actionBarSize"
            android_background="?attr/colorPrimary"
            app_popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

    <android.support.design.widget.FloatingActionButton
        android_id="@+id/fab"
        android_layout_width="wrap_content"
        android_layout_height="wrap_content"
        android_layout_gravity="bottom|end"
        android_layout_margin="@dimen/fab_margin"
        app_srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

content_main.xml

Here is our content_main.xml layout file.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout

    android_layout_width="match_parent"
    android_layout_height="match_parent"
    android_background="#fff"
    app_layout_behavior="@string/appbar_scrolling_view_behavior"
    tools_context="com.tutorials.hp.hellonotifications.MainActivity"
    tools_showIn="@layout/activity_main">

</android.support.constraint.ConstraintLayout>

activity_notif.xml

Here is our activity_notif.xml layout file.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout

    android_layout_width="match_parent"
     android_background="#fff"
    android_layout_height="match_parent"
    tools_context="com.tutorials.hp.hellonotifications.NotifActivity">

    <TextView
        android_id="@+id/notificationTxt"
        android_layout_width="fill_parent"
        android_layout_height="wrap_content"
        android_gravity="center"
        android_padding="5dp"
        android_textColor="#000000"
        android_textSize="20sp" />

</android.support.constraint.ConstraintLayout>

build.gradle

Here are our dependencies in our app level build.gradle file.

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.+'
    implementation 'com.android.support.constraint:constraint-layout:1.0.0-alpha7'
    implementation 'com.android.support:design:26.+'
}

Example 2: Android InBoxStyle Notification Example

Let us now look at the InBoxStyle Notification Example in Java. Here is a demo image:

InBox Style Notification Example

Step 1: Create Project

Start by creating an empty Android Studio project.

Step 2: Dependencies

No special dependencies are needed.

Step 3: Design Layouts

We will have three layouts:

(a). activity_inbox.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_inbox_"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.ankitkumar.inboxstylenotification.MainActivity">

    <TextView
        android:text="This is the Inbox and is open now"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginLeft="86dp"
        android:layout_marginStart="86dp"
        android:layout_marginTop="162dp"
        android:id="@+id/textView_inbox" />
</RelativeLayout>

(b). activity_reply_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_reply_activity"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.ankitkumar.inboxstylenotification.MainActivity">
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="This is the reply activity"
    android:textSize="20dp"/>
</RelativeLayout>

(c). activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.ankitkumar.inboxstylenotification.MainActivity">
    <Button
        android:text="Open Inxbox notification"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="228dp"
        android:onClick="inboxclick"
        android:id="@+id/button_inbox_notification" />
</RelativeLayout>

Step 4: Create Activities

We will have three activities:

(a). Inbox_Activity.java

public class Inbox_Activity extends AppCompatActivity {
    TextView txt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_inbox_);
        txt= (TextView) findViewById(R.id.textView_inbox);
    }
}

(b). Reply_activity.java

public class Reply_activity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_reply_activity);
    }
}

(c). MainActivity.java

public class MainActivity extends AppCompatActivity {
    Button btn_inbox_notification;
    private static final int INBOX_ID=100;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_inbox_notification= (Button) findViewById(R.id.button_inbox_notification);
    }
    public void inboxclick(View view)
    {
        switch (view.getId())
        {
            case R.id.button_inbox_notification:
                showinboxstylenotification();
                break;
        }
    }

    private void showinboxstylenotification()
    {
        //Style of notifiction is inbox style
        NotificationCompat.InboxStyle inboxstyle=new NotificationCompat.InboxStyle();
        inboxstyle.setBigContentTitle("Inbox style notification");
        inboxstyle.addLine("Line one");
        inboxstyle.addLine("Line two");
        inboxstyle.addLine("Line three");

        NotificationCompat.Builder builder=new NotificationCompat.Builder(MainActivity.this);
        builder.setContentTitle("Inbox Style Notification");
        builder.setContentText("Hello all \n This is my first inbox style notification");
        builder.setSmallIcon(R.drawable.ic_action_email);
        builder.setTicker("Inbox Notification");
        builder.setAutoCancel(true);
        builder.setStyle(inboxstyle);

        Intent i=new Intent(MainActivity.this,Inbox_Activity.class);
        TaskStackBuilder stackbuilder=TaskStackBuilder.create(MainActivity.this);
        stackbuilder.addParentStack(Inbox_Activity.class);
        stackbuilder.addNextIntent(i);
        PendingIntent pending_intent=stackbuilder.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

        //for the actio button
        Intent replyintent=new Intent(MainActivity.this,Reply_activity.class);
        TaskStackBuilder stackbuilder_reply=TaskStackBuilder.create(MainActivity.this);
        stackbuilder_reply.addParentStack(Reply_activity.class);
        stackbuilder_reply.addNextIntent(replyintent);
        PendingIntent pending_intent_reply=stackbuilder_reply.getPendingIntent(0,PendingIntent.FLAG_UPDATE_CURRENT);

        builder.setContentIntent(pending_intent);
        builder.setContentIntent(pending_intent_reply);
        builder.addAction(R.drawable.ic_action_email,"Reply",pending_intent_reply);

        Notification notification=builder.build();
        NotificationManager manager=(NotificationManager)this.getSystemService(NOTIFICATION_SERVICE);
        manager.notify(INBOX_ID,notification);
    }
}

Run

Copy the code or download it in the link below, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author

Android Notification Time-Sensitive

Android example of how to post a time-sensitive notification in Kotlin.

Display time-sensitive notifications:

In specific situations, your app might need to get the user's attention urgently, such as an ongoing alarm or incoming call. You might have previously configured your app for this purpose by launching an activity while your app was in the background.

This app show how to use:

  • Kotlin
  • Service Foreground
  • MediaPlayer (Play a sound)
  • Vibrator (Vibrator loop)
  • FullScreen Activity (Open the screen over the keyguard and screen off)
  • ConstraintLayout
  • Marquee textView
  • Time-sensitive
  • Head up
  • Actions buttons background colors with Android spannable

Here is the demo GIF:

Notication with Service Tutorial

NB/= The Android may choose to display a heads-up notification, instead of launching your full-screen intent, while the user is using the device.

Android AOSP choose how to display the notification see the flowchart:

Notication with Service Tutorial

Let us look at a full Notication with Service Example based on this project below.

Step 1. Dependencies

We need to add some dependencies in our app/build.gradle file as shown below:

(a). build.gradle

Our app-level build.gradle.

We Prepare our dependencies as shown below. You may use later versions.

At the top of our app/build.gradle we will apply the following 3 plugins:

  1. Our com.android.application plugin.
  2. Our kotlin-android plugin.
  3. Our kotlin-android-extensions plugin.

We then declare our app dependencies under the dependencies closure, using the implementation statement. We will need the following 4 dependencies:

  1. Kotlin-stdlib - So that we can use Kotlin as our programming language.
  2. Core-ktx - With this we can target the latest platform features and APIs while also supporting older devices.
  3. Appcompat - Allows us access to new APIs on older API versions of the platform (many using Material Design).
  4. Constraintlayout - This allows us to Position and size widgets in a flexible way with relative positioning.

Here is our full app/build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.layon.android.androidnotificationtimesentive"
        minSdkVersion 26
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

Step 2. Our Android Manifest

We will need to look at our AndroidManifest.xml.

(a). AndroidManifest.xml

Our AndroidManifest file.

This project will have 2 Activities. For them to be accessible we have to register them. We do that below. We will be creating a single Service so we have to register it as well. Here we will add the following permission:

  1. Our FOREGROUND_SERVICE permission.
  2. Our USE_FULL_SCREEN_INTENT permission.
  3. Our VIBRATE permission.

Here is the full Android Manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.layon.android.androidnotificationtimesentive">

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".FullScreenActivity"
            android:theme="@style/AppTheme.NoActionBar"></activity>

        <service android:name=".ForegroundService"></service>

        <activity android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Step 3. Design Layouts

For this project let's create the following layouts:

(a). activity_full_screen.xml

Our activity_full_screen layout.

This layout will represent our Screen Full Activity's layout. Specify androidx.constraintlayout.widget.ConstraintLayout as it's root element then inside it place the following widgets:

  1. TextView
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".FullScreenActivity"
    android:id="@+id/fullscreenactivity">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Full Screen Activity"
        android:textStyle="bold"
        android:textSize="50sp"
        android:textAlignment="center"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

(b). activity_main.xml

Our activity_main layout.

This layout will represent our Main Activity's layout. Specify androidx.constraintlayout.widget.ConstraintLayout as it's root element then inside it place the following widgets:

  1. TextView
  2. Button
  3. CheckBox
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="20dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="150dp"
        android:layout_marginBottom="149dp"
        android:ellipsize="marquee"
        android:fadingEdge="horizontal"
        android:marqueeRepeatLimit="marquee_forever"
        android:singleLine="true"
        android:text="Android notification time-sensitive example in Kotlin"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toTopOf="@+id/checkBox_play_sound"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonPost"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginBottom="50dp"
        android:text="Post"
        android:background="@android:color/holo_green_dark"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/buttonCancel"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/buttonCancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="9dp"
        android:layout_marginBottom="50dp"
        android:text="Cancel"
        android:background="@android:color/holo_red_light"
        android:textColor="@android:color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/buttonPost" />

    <CheckBox
        android:id="@+id/checkBox_play_sound"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:text="Play sound"
        android:checked="true"
        app:layout_constraintEnd_toEndOf="@+id/textView3"
        app:layout_constraintStart_toEndOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />

    <CheckBox
        android:id="@+id/checkBox_vibrate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="11dp"
        android:text="Vibrate"
        android:checked="true"
        app:layout_constraintStart_toStartOf="@+id/checkBox_play_sound"
        app:layout_constraintTop_toBottomOf="@+id/checkBox_play_sound" />

    <CheckBox
        android:id="@+id/checkBox_delay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="11dp"
        android:text="Delay 5s"
        app:layout_constraintStart_toStartOf="@+id/checkBox_vibrate"
        app:layout_constraintTop_toBottomOf="@+id/checkBox_vibrate" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="295dp"
        android:text="Options:"
        android:textStyle="bold|italic"
        android:textSize="15sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Step 4. Write Code

Finally we need to write our code as follows:

(a). ForegroundService.kt

Our ForegroundService class.

Create a Kotlin file named ForegroundService.kt and add the necessary imports. Here are some of the imports we will be using: 1. ForegroundColorSpan from the android.text.style package. 2. Log from the android.util package. 3. Toast from the android.widget package. 4. NotificationCompat from the androidx.core.app package. 5. ContextCompat from the androidx.core.content package.

Then extend the Service and add its contents as follows:

First override these callbacks:

  1. onCreate().
  2. onStartCommand(intent: Intent?, flags: Int, start: Int): Int.
  3. onDestroy().
  4. onBind(intent: Intent): IBinder?.

Then we will be creating the following functions:

  1. stopService(context: Context, message: String).
  2. playsound(parameter) - Our function will take a Boolean object as a parameter.
  3. createNotificationChannel().
  4. postNotification(): Int.
  5. getActionText(string : String, color : Int): Spannable?.

(a). Our postNotification() function

Write the postNotification() function as follows:

    private fun postNotification(): Int {
        Log.d("layonf", "postNotification")

        //create the fullScreen Intents
        val fullScreenIntent = Intent(this, FullScreenActivity::class.java)
        val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
            fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Time-Sentive Notification")
            .setContentText("An example of how to show an Android time-sentive notification in kotlin")
            .setSmallIcon(R.drawable.ic_baseline_new_releases_24)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setCategory(NotificationCompat.CATEGORY_CALL)
            .addAction(R.drawable.ic_baseline_phone_enabled_24,
                getActionText("Action1", Color.RED), null)
            .addAction(R.drawable.ic_baseline_phone_disabled_24,
                getActionText("Action2", Color.GREEN), null)
            .setFullScreenIntent(fullScreenPendingIntent, true)
            .build()

        startForeground(NOTIFICATION_ID, notification)
        return START_NOT_STICKY
    }

(b). Our startService() function

Write the startService() function as follows:

        fun startService(context: Context, message: String, playsound: Boolean, vibrate: Boolean,
        delay: Int) {
            //startService with a delay
            Handler(Looper.getMainLooper()).postDelayed({
                val startIntent = Intent(context, ForegroundService::class.java)
                startIntent.putExtra("playsound", playsound)
                startIntent.putExtra("vibrate", vibrate)
                Toast.makeText(context, message, Toast.LENGTH_LONG).show()
                ContextCompat.startForegroundService(context, startIntent)
                Log.d("layonf", "startService")
            }, delay.toLong()) // 5s
        }

(c). Our stopService() function

Write the stopService() function as follows:

        fun stopService(context: Context, message: String) {
            val stopIntent = Intent(context, ForegroundService::class.java)
            Toast.makeText(context, message, Toast.LENGTH_LONG).show()
            context.stopService(stopIntent)
            Log.d("layonf", "stopService")
        }

(d). Our getActionText() function

Write the getActionText() function as follows:

    private fun getActionText(string : String, color : Int): Spannable? {
        val spannable: Spannable = SpannableString(string)
        if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) {
            spannable.setSpan(
                ForegroundColorSpan(color), 0, spannable.length, 0
            )
        }
        return spannable
    }

(e). Our playsound() function

Write the playsound() function as follows:

    fun playsound(play: Boolean){
        Log.d("layonf", "playsound")
        mediaPlayer?.setLooping(true)
    }

(f). Our createNotificationChannel() function

Write the createNotificationChannel() function as follows:

    private fun createNotificationChannel(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(CHANNEL_ID, "Time-sentive Notification",
            NotificationManager.IMPORTANCE_HIGH)
            val manager = getSystemService(NotificationManager::class.java)
            manager!!.createNotificationChannel(serviceChannel)
        }
    }

Here is the full code:

package replace_with_your_package_name

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.media.MediaPlayer
import android.os.*
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.util.Log
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat


class ForegroundService : Service() {

    private val CHANNEL_ID = "Time-Sentive Notification in Kotlin"
    private val NOTIFICATION_ID = 1
    private var mediaPlayer: MediaPlayer? = null
    private var vibrator: Vibrator? = null

    //function to start and stop the foregroundservice
    companion object {
        fun startService(context: Context, message: String, playsound: Boolean, vibrate: Boolean,
        delay: Int) {
            //startService with a delay
            Handler(Looper.getMainLooper()).postDelayed({
                val startIntent = Intent(context, ForegroundService::class.java)
                startIntent.putExtra("playsound", playsound)
                startIntent.putExtra("vibrate", vibrate)
                Toast.makeText(context, message, Toast.LENGTH_LONG).show()
                ContextCompat.startForegroundService(context, startIntent)
                Log.d("layonf", "startService")
            }, delay.toLong()) // 5s
        }
        fun stopService(context: Context, message: String) {
            val stopIntent = Intent(context, ForegroundService::class.java)
            Toast.makeText(context, message, Toast.LENGTH_LONG).show()
            context.stopService(stopIntent)
            Log.d("layonf", "stopService")
        }
    }

    override fun onCreate() {
        super.onCreate()
        //get media player
        mediaPlayer = MediaPlayer.create(this, R.raw.shapeofyou)
        mediaPlayer?.setOnPreparedListener {
            println("PLAY")
        }
        //get vibrator
        vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
    }

    fun playsound(play: Boolean){
        Log.d("layonf", "playsound")
        mediaPlayer?.setLooping(true)
    }

    override fun onStartCommand(intent: Intent?, flags: Int, start: Int): Int {
        Log.d("layonf", "onStartCommand")
        //Do heavy work on a background thread

        //need play sound?
        val playsound = intent?.getBooleanExtra("playsound", false)
        if(playsound!!) {
            Log.d("layonf", "play")
            mediaPlayer?.setLooping(true)
            mediaPlayer?.start()
        }

        //need vibrate?
        val vibrate = intent?.getBooleanExtra("vibrate", false)
        if(vibrate!!) {
            Log.d("layonf", "vibrate")

            if (Build.VERSION.SDK_INT >= 26) {
                vibrator?.vibrate(VibrationEffect.createWaveform(
                    longArrayOf(1500L, 800L, 800L), 0))
            } else {
                vibrator?.vibrate(5000)
            }
        }

        //create channel
        createNotificationChannel()

        //return the postNotification to finish
        return postNotification()

    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("layonf", "onDestroy")
        //stop the play if need
        mediaPlayer?.stop()
        //stop the vibrate if need
        vibrator?.cancel()
    }


    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    private fun createNotificationChannel(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val serviceChannel = NotificationChannel(CHANNEL_ID, "Time-sentive Notification",
            NotificationManager.IMPORTANCE_HIGH)
            val manager = getSystemService(NotificationManager::class.java)
            manager!!.createNotificationChannel(serviceChannel)
        }
    }

    private fun postNotification(): Int {
        Log.d("layonf", "postNotification")

        //create the fullScreen Intents
        val fullScreenIntent = Intent(this, FullScreenActivity::class.java)
        val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
            fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

        val notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setContentTitle("Time-Sentive Notification")
            .setContentText("An example of how to show an Android time-sentive notification in kotlin")
            .setSmallIcon(R.drawable.ic_baseline_new_releases_24)
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setCategory(NotificationCompat.CATEGORY_CALL)
            .addAction(R.drawable.ic_baseline_phone_enabled_24,
                getActionText("Action1", Color.RED), null)
            .addAction(R.drawable.ic_baseline_phone_disabled_24,
                getActionText("Action2", Color.GREEN), null)
            .setFullScreenIntent(fullScreenPendingIntent, true)
            .build()

        startForeground(NOTIFICATION_ID, notification)
        return START_NOT_STICKY
    }

    //this method return a spannable the set background color on action button name
    private fun getActionText(string : String, color : Int): Spannable? {
        val spannable: Spannable = SpannableString(string)
        if (VERSION.SDK_INT >= VERSION_CODES.N_MR1) {
            spannable.setSpan(
                ForegroundColorSpan(color), 0, spannable.length, 0
            )
        }
        return spannable
    }
}

(b). FullScreenActivity.kt

Our FullScreenActivity class.

Create a Kotlin file named FullScreenActivity.kt and add the necessary imports. Here are some of the imports we will be using: 1. Log from the android.util package. 2. View from the android.view package. 3. WindowManager from the android.view package. 4. AppCompatActivity from the androidx.appcompat.app package. 5. * from the kotlinx.android.synthetic.main.activity_full_screen package.

Then extend the AppCompatActivity and add its contents as follows:

First override these callbacks:

  1. onCreate(savedInstanceState: Bundle?).

Here is the full code:

package replace_with_your_package_name

import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_full_screen.*


class FullScreenActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_full_screen)

        //start the activity over keyguard and screen off
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setShowWhenLocked(true)
            setTurnScreenOn(true)
            val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            keyguardManager.requestDismissKeyguard(this, null)
        }

        //disable navigation and statusbar
        window.decorView.apply{
            systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
                    View.SYSTEM_UI_FLAG_FULLSCREEN
        }

        Log.i("layonf", "create incoming call")

        //go to start activity when touch in fullscreen activity
        fullscreenactivity.setOnClickListener({
            Log.i("layonf", "touch")
            val i = Intent(this, MainActivity::class.java)
            startActivity(i)
        })
    }
}

(c). MainActivity.kt

Our MainActivity class.

Create a Kotlin file named MainActivity.kt and add the necessary imports. Here are some of the imports we will be using: 1. AppCompatActivity from the androidx.appcompat.app package. 2. Bundle from the android.os package. 3. View from the android.view package. 4. * from the kotlinx.android.synthetic.main.activity_main package.

Then extend the AppCompatActivity and add its contents as follows:

First override these callbacks:

  1. onCreate(savedInstanceState: Bundle?).

Here is the full code:

package replace_with_your_package_name

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //enabled the marquee
        textView.setSelected(true)

        buttonPost.setOnClickListener(View.OnClickListener {
            //need play sound?
            var playsound = if(checkBox_play_sound.isChecked) true else false

            //need vibrate?
            var vibrate = if(checkBox_vibrate.isChecked) true else false

            //need vibrate?
            var delay = if(checkBox_delay.isChecked) 5000 else 0

            ForegroundService.startService(this, "Foreground Service is running...",
            playsound, vibrate, delay)
        })
        buttonCancel.setOnClickListener(View.OnClickListener {
            ForegroundService.stopService(this, "Foreground Service is stopping...")
        })
    }
}

Reference

Download the code below:

No. Link
1. Download Full Code
2. Read more here.
3. Follow code author here.