99 lines
3.6 KiB
Kotlin
99 lines
3.6 KiB
Kotlin
package eu.depau.ddroid.abc
|
|
|
|
import android.app.IntentService
|
|
import android.app.Notification
|
|
import android.app.NotificationChannel
|
|
import android.app.NotificationManager
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import eu.depau.ddroid.R
|
|
import eu.depau.ddroid.utils.getFileName
|
|
import eu.depau.ddroid.utils.toHRSize
|
|
|
|
|
|
abstract class UsbWriteService(name: String) : IntentService(name) {
|
|
val TAG = name
|
|
val FOREGROUND_ID = 1931
|
|
val WRITE_PROGRESS_CHANNEL_ID = "eu.depau.ddroid.notifications.USB_WRITE_PROGRESS"
|
|
private var prevTime = System.currentTimeMillis()
|
|
private var prevBytes = 0L
|
|
private var notifyChanRegistered = false
|
|
|
|
fun getNotificationBuilder(): Notification.Builder {
|
|
if (!notifyChanRegistered) {
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
val channame = "USB write progress"
|
|
val description = "Displays the status of ongoing USB writes"
|
|
val importance = NotificationManager.IMPORTANCE_LOW
|
|
val channel = NotificationChannel(WRITE_PROGRESS_CHANNEL_ID, channame, importance)
|
|
channel.description = description
|
|
|
|
// Register the channel with the system; you can't change the importance
|
|
// or other notification behaviors after this
|
|
val notificationManager = getSystemService(NotificationManager::class.java)
|
|
notificationManager!!.createNotificationChannel(channel)
|
|
}
|
|
notifyChanRegistered = true
|
|
}
|
|
|
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
|
Notification.Builder(this, WRITE_PROGRESS_CHANNEL_ID)
|
|
else
|
|
Notification.Builder(this)
|
|
}
|
|
|
|
fun updateNotification(usbDevice: String, uri: Uri, bytes: Long, total: Long) {
|
|
// Notification rate limiting
|
|
val time = System.currentTimeMillis()
|
|
if (time <= prevTime + 1000)
|
|
return
|
|
|
|
val speed = ((bytes - prevBytes).toDouble() / (time - prevTime).toDouble()).toHRSize()
|
|
prevTime = time
|
|
prevBytes = bytes
|
|
|
|
val perc: Int = (bytes.toDouble() / total * 100.0).toInt()
|
|
|
|
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
|
notificationManager.notify(FOREGROUND_ID, buildForegroundNotification(usbDevice, uri, bytes, total, "$perc% • $speed/s"))
|
|
}
|
|
|
|
fun errorNotification() {
|
|
val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
|
|
|
|
val b = getNotificationBuilder()
|
|
.setContentTitle("Write failed")
|
|
.setContentText("The USB drive may have been unplugged while writing.")
|
|
.setOngoing(false)
|
|
.setSmallIcon(R.drawable.ic_usb_white_24dp)
|
|
|
|
notificationManager.notify(FOREGROUND_ID, b.build())
|
|
}
|
|
|
|
fun buildForegroundNotification(usbDevice: String, uri: Uri, bytes: Long, total: Long, subText: String? = null): Notification {
|
|
val progr: Int
|
|
val indet: Boolean
|
|
|
|
if (total < 0) {
|
|
progr = 0
|
|
indet = true
|
|
} else {
|
|
progr = (bytes.toFloat()/total * 100).toInt()
|
|
indet = false
|
|
}
|
|
|
|
val b = getNotificationBuilder()
|
|
|
|
b.setContentTitle("Writing image")
|
|
.setContentText("${uri.getFileName(this)} to $usbDevice")
|
|
.setOngoing(true)
|
|
.setSmallIcon(R.drawable.ic_usb_white_24dp)
|
|
.setProgress(100, progr, indet)
|
|
|
|
if (subText != null)
|
|
b.setSubText(subText)
|
|
|
|
return b.build()
|
|
}
|
|
|
|
} |