Local notification in Android with Jetpack compose
In the realm of Android app development, creating an engaging and user-friendly experience often involves incorporating notifications. Notifications serve as a crucial means of communication, providing users with timely information and updates.
This blog post will be in two parts, the first part of our exploration focuses on the importance and detailed implementation of simple notifications, unraveling the steps to create an effective and user-centric notification system. In the second part, we will explore the implementation of different types of local notifications in Android with Jetpack Compose.
Importance of local notification
Local notifications play a pivotal role in enhancing the overall user experience of mobile applications. Here are several key reasons why local notifications are important in mobile applications:
1. User Engagement:
- Timely Updates: Local notifications allow apps to provide timely information, updates, and reminders to users, keeping them engaged and informed.
- Relevance: Notifications can be personalized based on user preferences and behavior, delivering content that is relevant to individual users.
2. Retaining User Attention:
- Attention Grabbers: Notifications serve as attention-grabbing elements, drawing users back to the app by alerting them to new content, messages, or events.
- App Recall: Regular and well-timed notifications help in maintaining the app’s presence in the user’s mind, increasing the likelihood of users returning to the app.
3. User Interaction
- Interactivity: Local notifications can include interactive elements, allowing users to take actions directly from the notification without opening the app.
- Efficient Communication: Notifications provide a quick and efficient way for users to respond to events or messages without navigating through the entire app.
4. Enhancing User Experience:
- Personalization: Local notifications can be tailored to match the app’s design and branding, contributing to a consistent and seamless user experience.
- Customization: Users can often customize notification preferences, allowing them to control the type and frequency of notifications they receive.
5. Task Reminders and Alerts:
- Task Management: Notifications serve as reminders for tasks, appointments, or events, helping users stay organized and on top of their schedules.
- Alerts and Warnings: Important alerts and warnings can be conveyed through notifications, ensuring users are promptly informed of critical information.
6. Offline Interaction:
- No Dependency on Connectivity: Local notifications function independently of network connectivity, making them reliable for delivering messages even when the device is offline.
7. Marketing and Promotions:
- Promotional Messages: Apps can use notifications for marketing purposes by sending promotions, discounts, or announcements, driving user engagement and potential conversions.
8. Background Processes:
- Background Tasks: Local notifications enable background processes, allowing apps to perform tasks such as updates or syncing data even when the app is not actively in use.
9. User Satisfaction and Loyalty:
- Enhanced Experience: Well-implemented local notifications contribute to an overall positive user experience, increasing user satisfaction and loyalty.
- App Stickiness: Apps that effectively utilize notifications are more likely to retain users and create a loyal user base.
In summary, local notifications are a powerful tool for mobile applications, facilitating effective communication, user engagement, and task management.
Overview of the Local notification Implementation
Key Components:
1. Dependencies and Permissions:
We’ll begin by setting up the project with the necessary dependencies. This includes the addition of the accompanist-permissions
library and declaring the POST_NOTIFICATIONS
permission in the AndroidManifest.xml
.
2. Notification Application Setup:
The NotificationApplication
class takes center stage in this process. It creates a notification channel, providing a structured approach to manage and organize notifications effectively.
3. Crafting Notifications with NotificationHandler:
The NotificationHandler
class is where the magic happens. It utilizes the NotificationCompat.Builder
to craft various types of notifications. We'll focus on a simple notification as a starting point.
4. Integration with Jetpack Compose:
Our notification system seamlessly integrates with Jetpack Compose in the MainScreen
. This component initiates the notification service and provides a user-friendly interface for triggering notifications.
5. Bringing It All Together:
The MainActivity.kt
orchestrates the entire application, ensuring the proper initialization of the NotificationApplication
and setting up the Jetpack Compose UI. This section emphasizes the cohesive flow from the main activity to the user interface.
Let’s code!!
Now that we’ve explored the importance and advantages of local notifications, let’s dive into the exciting part — the code implementation. Get your coding gear ready as we walk through the steps to bring these notifications to life in your app!
Starting with build.gradle.kts (:app)
—
implementation("com.google.accompanist:accompanist-permissions:0.31.1-alpha")
This library streamlines the process, making it hassle-free to handle permissions. Now that we’ve added the required dependencies to our project, let’s sync the project to make sure everything is up-to-date.
Once the sync is complete, give our app a little permission boost! To make things work smoothly, we need to add the POST-NOTIFICATION permission. It’s like giving our app the green light to share notifications with you!
AndroidManifest.xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
Awesome! We’ve set up our app with the needed tools. Now, let’s talk about something called a ‘notification channel.’ Think of it like a VIP pass for notifications. This special channel helps organize and manage notifications, making sure they’re delivered in a way that’s just right for you.
So, let’s set up this notification channel in our NotificationApplication.kt
file!
import android.app.Application
import android.app.NotificationChannel
import android.app.NotificationManager
import android.os.Build
import androidx.annotation.RequiresApi
class NotificationApplication : Application() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate() {
super.onCreate()
val notificationChannel = NotificationChannel(
"notification_channel_id",
"Notification name",
NotificationManager.IMPORTANCE_HIGH
)
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
// Setting up the channel
notificationManager.createNotificationChannel(notificationChannel)
}
}
NotificationApplication
that extends theApplication
class. This signifies that it's an application-level class, allowing it to perform actions when the app is created.notificationChannel
creates aNotificationChannel
object. Where,notification_channel_id
is a unique identifier for the channel.Notification name
is the display name of the channel.NotificationManager.IMPORTANCE_HIGH
sets the importance level of the notifications to high, indicating that they should be shown with high priority.notificationManager
obtains theNotificationManager
service, which is responsible for managing notifications.- And last we sets up the created channel, making it ready for use in the app.
- Before we dive into crafting our notification in the
NotificationHandler
class, there's one more step we need to take. Don't forget to let our app know about our shiny newNotificationApplication
! Open up yourAndroidManifest.xml
file and add a declaration for it. This way, our app will recognize and make use of the awesome notification channel we just set up.
<application
android:name=".NotificationApplication"
.
.
.
</application>
At this stage, we’re almost there! We’ve successfully set up a notification channel, and now we’re going to build our first notification. It’s like giving our notification its own identity, starting with something simple — a small icon, a title, and a short description.
Create a class file called NotidicationHandler
, and in there, we’ll work our magic to bring our notification to life!
import android.app.NotificationManager
import android.content.Context
import androidx.core.app.NotificationCompat
import kotlin.random.Random
class NotificationHandler(private val context: Context) {
private val notificationManager = context.getSystemService(NotificationManager::class.java)
private val notificationChannelID = "notification_channel_id"
// SIMPLE NOTIFICATION
fun showSimpleNotification() {
val notification = NotificationCompat.Builder(context, notificationChannelID)
.setContentTitle("Simple Notification")
.setContentText("Message or text with notification")
.setSmallIcon(R.drawable.round_notifications_24)
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setAutoCancel(true)
.build() // finalizes the creation
notificationManager.notify(Random.nextInt(), notification)
}
}
notificationManager
obtains theNotificationManager
service, allowing us to interact with notifications.notificationChannelID
holds the ID of the notification channel, ensuring that the notification is associated with the correct channel.- In
showSimpleNotification()
function we’ll create ournotification
. So initiates the notification builder, associating it with the specified channel. In that we set the title, text and small icon. setAutoCancel(true)
makes the notification automatically dismissable when tapped.notificationManager.notify(Random.nextInt(), notification)
:
This line triggers the display of the notification.Random.nextInt()
generates a unique identifier for the notification, ensuring that each notification is treated as a separate instance.
We’re good to go! We’ve made a simple notification, and now, let’s create a button in Compose. When you tap it, our notification will pop up.
import android.Manifest
import android.content.Context
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun MainScreen(context: Context) {
val postNotificationPermission = rememberPermissionState(permission = Manifest.permission.POST_NOTIFICATIONS)
val notificationHandler = NotificationHandler(context)
LaunchedEffect(key1 = true) {
if (!postNotificationPermission.status.isGranted) {
postNotificationPermission.launchPermissionRequest()
}
}
Column {
Button(onClick = {
notificationHandler.showSimpleNotification()
}) { Text(text = "Simple notification") }
}
}
postNotificationPermission
is a state variable to manage the permission state for posting notifications.notificationHandler
is an instance of theNotificationHandler
class, which will be used to handle the creation and display of notifications.LaunchedEffect
is a Compose effect that runs a given block of code when the composable is first launched.- Inside the effect block, it checks if the
POST_NOTIFICATIONS
permission is granted. If not, it launches a permission request. - When button clicked, it triggers the
showSimpleNotification
method of thenotificationHandler
.
Lastly, make sure to call our Compose function within our MainActivity.kt
to make everything come to life!
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.RequiresApi
class MainActivity : ComponentActivity() {
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MainScreen(this)
}
}
}
Now, launch the app on your device or emulator and tap the button. If you’re on Android 13, you might see a permission dialog because, by default, it’s denied. Just grant it, and there you go! You’ll receive your notification. If you’re on Android 12 or an older version, no need to stress about notification permissions — it’s smooth sailing!
Congratulations on successfully implementing the simple notification!
Also consider:
Different types of local notification in Android using Jetpack compose
Level-up your local notification:
Scheduled local notification in Android using AlarmManager
I hope this article has provided valuable insights and assistance for your Android journey. Your support means a lot to me, so if you found this content helpful, please start following me and don’t hesitate to show some love with a hearty round of applause!👏
Your feedback fuels my passion for creating quality content. For any Android queries or just to connect, reach out on LinkedIn and Twitter.
Thanks for reading — looking forward to staying in touch!
Happy Coding!!