android kotlin - PreferenceFragmentCompat example

MainActivity.kt

package com.example.jetpack

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.preference.PreferenceManager
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {

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

        // Get the preferences
        val prefs = PreferenceManager.getDefaultSharedPreferences(this)

        // Get the user dark theme settings
        val isDarkTheme = prefs.getBoolean("key_dark_theme",false)

        textView.text ="Dark Theme Enabled ? $isDarkTheme"

        btn.setOnClickListener{
            // Load the settings fragment
            supportFragmentManager
                .beginTransaction()
                .replace(R.id.linearLayout,MySettingsFragment())
                .commit()
        }
    }
}
activity_main.xml

<?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">
    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Load Settings"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="24dp"
        android:text="TextView"
        android:textAppearance="@style/TextAppearance.AppCompat.Large"
        app:layout_constraintBottom_toTopOf="@+id/linearLayout"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn"
        />
    <LinearLayout
        android:id="@+id/linearLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView"
        />
</androidx.constraintlayout.widget.ConstraintLayout>
MySettingsFragment.kt

package com.example.jetpack


import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import android.widget.Toast
import androidx.preference.SwitchPreferenceCompat


class MySettingsFragment : PreferenceFragmentCompat(){
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.prefs,rootKey)

        // Get the switch preference
        val switchDarkMode: SwitchPreferenceCompat? = findPreference("key_dark_theme")

        // Switch preference change listener
        switchDarkMode?.setOnPreferenceChangeListener{ preference, newValue ->
            if (newValue == true){
                Toast.makeText(activity,"enabled",Toast.LENGTH_LONG).show()
            }else{
                Toast.makeText(activity,"disabled",Toast.LENGTH_LONG).show()
            }

            true
        }
    }
}
res/xml/prefs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    >
    <SwitchPreferenceCompat
        app:key="key_dark_theme"
        app:title="Enable Dark Theme?"
        />
    <Preference
        app:key="key_sample"
        app:title="Sample Title"
        app:summary="This is sample summary"
        />
</PreferenceScreen>
AndroidManifest.xml [add]

// AndroidX Preference Library
implementation 'androidx.preference:preference:1.1.0'

android kotlin - Notification progress bar percentage

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.*
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat


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

        // get the context
        val context = this

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)


        // Create and register notification channel api 26+
        val channelId = "My_Channel_ID"
        val notificationId = 1
        createNotificationChannel(channelId)


        // button click listener
        button.setOnClickListener{
            val builder = NotificationCompat.Builder(context,channelId)
                .setContentTitle("Download Task")
                .setContentText("Downloading your file...")
                .setSmallIcon(R.drawable.ic_action_help)

            val max = 25
            var progress = 0
            var percentage = 0
            val handler = Handler(Looper.getMainLooper())

            with(NotificationManagerCompat.from(context)){
                builder.setProgress(max,progress,true)
                notify(notificationId,builder.build())

                Thread(Runnable{
                    while (progress < max){
                        progress +=1

                        try {
                            Thread.sleep(1000)
                        }catch (e:InterruptedException){
                            e.printStackTrace()
                        }

                        handler.post(Runnable {
                            if (progress == max){
                                builder.setContentText("Download complete.")
                                builder.setProgress(0,0,false)
                            }else{
                                // Calculate the percentage comple
                                percentage = (progress*100)/max
                                builder.setContentText(
                                    "$percentage% complete $progress of $max")
                                builder.setProgress(max,progress,true)
                            }

                            notify(notificationId,builder.build())
                        })
                    }
                }).start()
            }
        }
    }



    // create notification channel
    private fun createNotificationChannel(channelId:String) {
        // Create the NotificationChannel,
        // but only on API 26+ (Android 8.0) because
        // the NotificationChannel class is new and
        // not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val name = "My Channel"
            val channelDescription = "Channel Description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel(channelId,name,importance)
            channel.apply {
                description = channelDescription
            }

            // Finally register the channel with system
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}
activity_main.xml

<?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:background="#DCDCDC"
    android:id="@+id/rootLayout"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Notification"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml [Permission]

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

android kotlin - Notification direct reply action example

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.widget.Button
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput


class MainActivity : Activity() {
    @RequiresApi(Build.VERSION_CODES.S)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // get the context
        val context = this

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)


        // Create and register notification channel api 26+
        val channelId = "My_Channel_ID"
        val notificationId = 1
        createNotificationChannel(channelId)


        // button click listener
        button.setOnClickListener {
            // The direct reply action, introduced
            // in Android 7.0 (API level 24)
            // Create an instance of remote input builder
            val remoteInput: RemoteInput = RemoteInput
                .Builder("KEY_TEXT_REPLY")
                .run {
                    setLabel("Write your message here")
                    build()
                }

            // Create an intent
            val intent = Intent(context, MyBroadcastReceiver::class.java)
            intent.action = "REPLY_ACTION"
            intent.putExtra("KEY_NOTIFICATION_ID", notificationId)
            intent.putExtra("KEY_CHANNEL_ID", channelId)
            intent.putExtra("KEY_MESSAGE_ID", 2)

            // Create a pending intent for the reply button
            val replyPendingIntent: PendingIntent = PendingIntent
                .getBroadcast(
                context,
                101,
                intent,
                PendingIntent.FLAG_MUTABLE or
                        PendingIntent.FLAG_UPDATE_CURRENT
            )

            // Create reply action and add the remote input
            val action: NotificationCompat.Action = NotificationCompat
                .Action.Builder(
                R.drawable.ic_action_backup,
                "Reply",
                replyPendingIntent
            ).addRemoteInput(remoteInput)
                .setAllowGeneratedReplies(true)
                .build()


            // Build a notification and add the action
            val builder = NotificationCompat.Builder(context, channelId)
                .setSmallIcon(R.drawable.ic_action_help_outline)
                .setContentTitle("Jones")
                .setContentText("Hello! how are you?")
                .addAction(action)

            // Finally, issue the notification
            NotificationManagerCompat.from(context).apply {
                notify(notificationId, builder.build())
            }
        }
    }



    // create notification channel
    private fun createNotificationChannel(channelId:String) {
        // Create the NotificationChannel,
        // but only on API 26+ (Android 8.0) because
        // the NotificationChannel class is new and
        // not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val name = "My Channel"
            val channelDescription = "Channel Description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel(channelId,name,importance)
            channel.apply {
                description = channelDescription
            }

            // Finally register the channel with system
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}
activity_main.xml

<?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:background="#DCDCDC"
    android:id="@+id/rootLayout"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Notification"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
MyBroadcastReceiver.kt

package com.cfsuman.kotlintutorials

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.RemoteInput


class MyBroadcastReceiver: BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
        intent?.apply {
            if ("REPLY_ACTION" == action){
                val message = replyMessage(this)
                val messageId = getIntExtra("KEY_MESSAGE_ID",0)
                Toast.makeText(context,"$messageId : $message",
                    Toast.LENGTH_LONG).show()
            }

            context?.apply {
                val notificationId = getIntExtra("KEY_NOTIFICATION_ID",0)
                val channelId = getStringExtra("KEY_CHANNEL_ID")

                // Build a notification and add the action

                val builder = channelId?.let {
                    NotificationCompat.Builder(this, it)
                        .setSmallIcon(R.drawable.ic_action_help)
                        .setContentTitle("Title")
                        .setContentText("message sent!")
                }

                // Finally, issue the notification
                NotificationManagerCompat.from(this).apply {
                    if (builder != null) {
                        notify(notificationId, builder.build())
                    }
                }
            }
        }
    }


    private fun replyMessage(intent: Intent): CharSequence? {
        val remoteInput = RemoteInput.getResultsFromIntent(intent)
        return remoteInput?.getCharSequence("KEY_TEXT_REPLY")
    }
}
AndroidManifest.xml [add]

<receiver android:name=".MyBroadcastReceiver"/>
AndroidManifest.xml [Permission]

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

android kotlin - Notification progress bar example

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.*
import android.content.Context
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat


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

        // get the context
        val context = this

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)


        // Create and register notification channel api 26+
        val channelId = "My_Channel_ID"
        val notificationId = 1
        createNotificationChannel(channelId)


        // button click listener
        button.setOnClickListener{
            val builder = NotificationCompat.Builder(context,channelId)
                .setContentTitle("Download Task")
                .setContentText("Downloading your file...")
                .setSmallIcon(R.drawable.ic_action_help)

            val max = 100
            var progress = 0
            val handler = Handler(Looper.getMainLooper())

            with(NotificationManagerCompat.from(context)){
                builder.setProgress(max,progress,true)
                notify(notificationId,builder.build())

                Thread(Runnable{
                    while (progress < 100){
                        progress +=1

                        try {
                            Thread.sleep(100)
                        }catch (e:InterruptedException){
                            e.printStackTrace()
                        }

                        handler.post(Runnable {
                            if (progress == 100){
                                builder.setContentText("Download complete.")
                                builder.setProgress(0,0,false)
                            }else{
                                builder.setContentText(
                                    "complete $progress of $max")
                                builder.setProgress(
                                    max,progress,true)
                            }

                            notify(notificationId,builder.build())
                        })
                    }
                }).start()
            }
        }
    }



    // create notification channel
    private fun createNotificationChannel(channelId:String) {
        // Create the NotificationChannel,
        // but only on API 26+ (Android 8.0) because
        // the NotificationChannel class is new and
        // not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val name = "My Channel"
            val channelDescription = "Channel Description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel(channelId,name,importance)
            channel.apply {
                description = channelDescription
            }

            // Finally register the channel with system
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}
activity_main.xml

<?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:background="#DCDCDC"
    android:id="@+id/rootLayout"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Notification"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml [Permission]

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

android kotlin - Notification messaging style example

MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.*
import android.content.Context
import android.graphics.drawable.Icon
import android.os.Build
import android.os.Bundle
import android.widget.Button
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat


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

        // get the context
        val context = this

        // get the widgets reference from XML layout
        val button = findViewById<Button>(R.id.button)


        // Create and register notification channel api 26+
        val channelId = "My_Channel_ID"
        val notificationId = 1
        createNotificationChannel(channelId)


        // button click listener
        button.setOnClickListener{
            if (Build.VERSION.SDK_INT>=28) {
                val builder = Notification
                    .Builder(context,channelId)
                    .setContentTitle("This is title")
                    .setContentText("This is content description")
                    .setSmallIcon(R.drawable.ic_action_help)

                // Person added in API level 28
                val jenny = Person.Builder()
                    .setIcon(Icon.createWithResource(
                        context,R.drawable.ic_action_edit))
                    .setName("Jenny")
                    .build()
                val faria = Person.Builder()
                    .setIcon(Icon.createWithResource(
                        context,R.drawable.ic_action_backup))
                    .setName("Faria")
                    .build()

                // Notification.MessagingStyle added in API level 24
                builder.style = Notification.MessagingStyle(jenny)
                    .addMessage("Hi! how are you?",
                        System.currentTimeMillis()-60000,jenny)
                    .addMessage("I Am fine",
                        System.currentTimeMillis()-30000,faria)
                    .addMessage("Good.",
                        System.currentTimeMillis(),jenny)
                    .setGroupConversation(true)

                with(NotificationManagerCompat.from(context)){
                    notify(notificationId, builder.build())
                }
            }else{
                val builder = NotificationCompat
                    .Builder(context,channelId)
                    .setContentTitle("This is title")
                    .setContentText("This is content description")
                    .setSmallIcon(R.drawable.ic_action_help)

                builder.setStyle(NotificationCompat
                    .MessagingStyle("jenny")
                    .addMessage("Hi! how are you?",
                        System.currentTimeMillis()-60000,"Jenny")
                    .addMessage("I Am fine",
                        System.currentTimeMillis()-30000,"Faria")
                    .addMessage("Good.",
                        System.currentTimeMillis(),"Jenny")
                    .setGroupConversation(true)
                )

                with(NotificationManagerCompat.from(context)){
                    notify(notificationId, builder.build())
                }
            }
        }
    }



    // create notification channel
    private fun createNotificationChannel(channelId:String) {
        // Create the NotificationChannel,
        // but only on API 26+ (Android 8.0) because
        // the NotificationChannel class is new and
        // not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            val name = "My Channel"
            val channelDescription = "Channel Description"
            val importance = NotificationManager.IMPORTANCE_DEFAULT

            val channel = NotificationChannel(channelId,name,importance)
            channel.apply {
                description = channelDescription
            }

            // Finally register the channel with system
            val notificationManager = getSystemService(
                Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }
}
activity_main.xml

<?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:background="#DCDCDC"
    android:id="@+id/rootLayout"
    android:padding="24dp">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Notification"
        android:textAllCaps="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
AndroidManifest.xml [Permission]

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />