add notifcaiton support with unmount button

This commit is contained in:
2026-03-10 01:01:20 +05:00
parent 0c5524a9a5
commit 93c239eb12
9 changed files with 259 additions and 0 deletions
@@ -0,0 +1,109 @@
package sh.sar.isodroid.notification
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 androidx.core.app.NotificationCompat
import sh.sar.isodroid.MainActivity
import sh.sar.isodroid.R
import sh.sar.isodroid.data.MountStatus
import sh.sar.isodroid.data.MountType
class NotificationHelper(private val context: Context) {
companion object {
const val CHANNEL_ID = "iso_drive_mount_status"
const val NOTIFICATION_ID = 1001
const val ACTION_UNMOUNT = "sh.sar.isodroid.ACTION_UNMOUNT"
@Volatile
private var instance: NotificationHelper? = null
fun getInstance(context: Context): NotificationHelper {
return instance ?: synchronized(this) {
instance ?: NotificationHelper(context.applicationContext).also { instance = it }
}
}
}
private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
init {
createNotificationChannel()
}
private fun createNotificationChannel() {
val channel = NotificationChannel(
CHANNEL_ID,
"Mount Status",
NotificationManager.IMPORTANCE_LOW
).apply {
description = "Shows when an ISO/IMG file is mounted"
setShowBadge(false)
}
notificationManager.createNotificationChannel(channel)
}
fun showMountedNotification(mountStatus: MountStatus) {
if (!mountStatus.mounted || mountStatus.path == null) {
hideNotification()
return
}
val fileName = mountStatus.path.substringAfterLast("/")
val mountType = when (mountStatus.type) {
MountType.CDROM -> "CD-ROM"
MountType.MASS_STORAGE -> "Mass Storage"
else -> "USB"
}
val accessMode = if (mountStatus.readOnly) "Read-Only" else "Read-Write"
// Intent to open the app when notification is tapped
val openIntent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val openPendingIntent = PendingIntent.getActivity(
context,
0,
openIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
// Intent for unmount action
val unmountIntent = Intent(context, UnmountReceiver::class.java).apply {
action = ACTION_UNMOUNT
}
val unmountPendingIntent = PendingIntent.getBroadcast(
context,
1,
unmountIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("ISO Mounted")
.setContentText(fileName)
.setSubText("$mountType - $accessMode")
.setOngoing(true)
.setShowWhen(false)
.setContentIntent(openPendingIntent)
.addAction(
R.drawable.ic_eject,
"Unmount",
unmountPendingIntent
)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_STATUS)
.build()
notificationManager.notify(NOTIFICATION_ID, notification)
}
fun hideNotification() {
notificationManager.cancel(NOTIFICATION_ID)
}
}
@@ -0,0 +1,43 @@
package sh.sar.isodroid.notification
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import sh.sar.isodroid.isodrive.IsoDriveManager
import sh.sar.isodroid.isodrive.MountEventBus
class UnmountReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == NotificationHelper.ACTION_UNMOUNT) {
val pendingResult = goAsync()
CoroutineScope(Dispatchers.IO).launch {
try {
val isoDriveManager = IsoDriveManager.getInstance(context)
val result = isoDriveManager.unmount()
CoroutineScope(Dispatchers.Main).launch {
if (result.success) {
Toast.makeText(context, "Unmounted successfully", Toast.LENGTH_SHORT).show()
NotificationHelper.getInstance(context).hideNotification()
MountEventBus.emitUnmounted()
} else {
Toast.makeText(context, "Unmount failed: ${result.message}", Toast.LENGTH_LONG).show()
}
pendingResult.finish()
}
} catch (e: Exception) {
CoroutineScope(Dispatchers.Main).launch {
Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_LONG).show()
pendingResult.finish()
}
}
}
}
}
}